How to connect Spring with MySQL database? - java

I have a simple project, based on this guide. I created a simple REST interface and I want it to use my database. I added Hibernate to the dependencies and created the DAO class. I'm using Spring Tool-Suite for IDE. As far as I understand I should add some beans to tell the classes what to use but I don't understand how. Here are my classes.
Application.java
package com.learnspring.projectfirst;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Marker.java
package com.learnspring.projectfirst;
#Entity
public class Marker {
#Id
#Column
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Column
private double longitude;
#Column
private double latitude;
#Column
private String address;
public Marker() {
// Empty constructor
}
public Marker(long id, double longitude, double latitude, String address) {
this.id = id;
this.longitude = longitude;
this.latitude = latitude;
this.address = address;
}
//Getters and Setters
}
MarkerController.java
package com.learnspring.projectfirst.controller;
#Controller
public class MarkerController {
private Logger logger = Logger.getLogger(MarkerController.class.getName());
#Autowired
private MarkerServiceImplementation markerService;
#RequestMapping(value="/markers", method=RequestMethod.GET)
public #ResponseBody List<Marker> getMarkers(#RequestParam(value="city", defaultValue="") String city) {
return this.markerService.getAllMarkers();
}
#RequestMapping(value="/markers/new", method=RequestMethod.POST)
public #ResponseBody Marker addMarker(#RequestBody Marker marker) {
this.markerService.addMarker(marker);
return marker;
}
}
MarkerDaoImplementation.java
package com.learnspring.projectfirst.dao;
#Repository
public class MarkerDaoImplementation implements MarkerDaoInterface {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addMarker(Marker marker) {
this.sessionFactory.getCurrentSession().save(marker);
}
#Override
public void deleteMarker(int markerId) {
this.sessionFactory.getCurrentSession().delete(this.getMarker(markerId));
}
#Override
public Marker getMarker(int markerId) {
return (Marker) this.sessionFactory.getCurrentSession().get(Marker.class, markerId);
}
#Override
public List<Marker> getAllMarkers() {
return this.sessionFactory.getCurrentSession().createQuery("from Marker").list();
}
}
MarkerServiceImplementation.java
package com.learnspring.projectfirst.service;
#Service
public class MarkerServiceImplementation implements MarkerServiceInterface {
#Autowired
private MarkerDaoImplementation markerDao;
#Transactional
public void addMarker(Marker marker) {
this.markerDao.addMarker(marker);
}
#Transactional
public void deleteMarker(int markerId) {
this.markerDao.deleteMarker(markerId);
}
#Transactional
public Marker getMarker(int markerId) {
return this.markerDao.getMarker(markerId);
}
#Transactional
public List<Marker> getAllMarkers() {
return this.markerDao.getAllMarkers();
}
}
And here is the file structure:
I understand that I should tell my program the database name and the columns using beans but I don't understand how. How can I link the java code to the beans? Sorry I pasted so much code, I just wanted to make sure you have everything needed. Thank you in advance!

This is the one you need: Spring Boot with MySQL

Refer this example : Spring MVC with JdbcTemplate Example

The annotations in your "Marker" class determine the MySQL table and column names (based on the class and class variable names). The tablename will be "marker", with the columns "id", "longitude", "latitude", "address".
You forgot the most important part in your code: your spring configuration. it determines how the SessionFactory instance will be initialized before being injected into your DAO class. Here you have to set an appropriate connection to the MySQL Server (e.g. via an JNDI Resource)

Related

ReactiveMongoRepository can't save to database

I'm newbie with Java. I'm create an API with Webflux and ReactiveMongoRepository.
I try to save my data from another API.
My repository:
#Repository
public interface AccountApiTrackingRepo extends ReactiveMongoRepository<AccountApiTracking, String> {
}
My service implements:
#Override
public void findByIdAccountsApiTrack(User user, String accountId){
AccountApiTracking accountApiTracking = new AccountApiTracking();
accountApiTracking.setUser(user);
accountApiTracking.setAccountId(accountId);
accountApiTracking.setAction("Find account by Id");
System.out.println(accountApiTracking);
accountApiTrackingRepo.save(accountApiTracking);
}
My services:
#Service
public interface AccountApiTrackingService {
public void createAccountsApiTrack(User user, AccountDto accountDto);
public void findByIdAccountsApiTrack(User user, String accountId);
Flux<AccountApiTrackingDto> findAll();
}
My model:
#Document
#Data
#NoArgsConstructor
#AllArgsConstructor
public class AccountApiTracking implements AutoMapping<AccountApiTrackingDto> {
#Id
private String id;
private User user;
private String action;
private AccountDto payload;
private String accountId;
#Override
public String toString() {
return String.valueOf(action);
}
}
After function findByIdAccountsApiTrack() run I can't find any document created in my database.
I can see my variable accountApiTracking have data. But accountApiTrackingRepo.save doesn't work.
What I'm missing?
In Reactive programming should subscribe to any reactive instruction.
you should
return accountApiTrackingRepo.save(accountApiTracking);
to till your usage for example in the controller.
or for your test case, you can use ".subscribe()" after your method call.

Efficient way of reusing multiple Services having the same functionality but dealing with different entity

I am dealing with multiple entity classes but they have the same attributes.
It's not a good data structure but according to my use case, I have to deal with two entities having the same attributes. As of now I am using multiple controllers, multiple request/response and multiple interfaces and implementations to do the logic part and save into the two corresponding tables.
Is there any efficient way that I could combine both into a single interface, with the DB operations happening in multiple DBs.
Following is a sample code:
#RestController
..
public class FooController {
#Autowired
private FooService fooService;
#GetMapping
public FooResponse findFoo(
#PathVariable(FOO_CONSTANT.PATH_VARIABLE_FOO_ID) String fooId)
throws FooException {
return fooService.findFoo(fooId));
}
}
public interface FooService{
FooResponse findFoo(String fooId);
}
#Service
public class ProspectAssetServiceImpl implements ProspectAssetService {
#Autowired
private FooRepository fooRepository;
#Override
public FooResponse findFoo(String fooId){
FooEntity fooEntity = fooRepository.findByFooId(fooId));
return convertBomToMessaging(fooEntity);
}
}
public class Foo {
private String fooId;
private String fooName;
//getters and setters
}
#Entity
#Table(name = "foo_table")
public class FooEntity {
private String fooId;
private String fooName;
//getters and setters
}
Second Service:
#RestController
..
public class ZooController {
#Autowired
private ZooService ZooService;
#GetMapping
public ZooResponse findZoo(
#PathVariable(Zoo_CONSTANT.PATH_VARIABLE_Zoo_ID) String ZooId)
throws ZooException {
return ZooService.findZoo(ZooId));
}
}
public interface ZooService{
ZooResponse findZoo(String ZooId);
}
#Service
public class ProspectAssetServiceImpl implements ProspectAssetService {
#Autowired
private ZooRepository ZooRepository;
#Override
public ZooResponse findZoo(String ZooId){
ZooEntity ZooEntity = ZooRepository.findByZooId(ZooId));
return convertBomToMessaging(ZooEntity);
}
}
public class Zoo {
private String ZooId;
private String ZooName;
//getters and setters
}
#Entity
#Table(name = "Zoo_table")
public class ZooEntity {
private String ZooId;
private String ZooName;
//getters and setters
}
Suggest me an efficient way to combine these two together?

How to properly publish DDD domain events with spring?

I am trying to implement domain driven design in my project.
Here is my base Aggregate class:
public abstract class UUIDAggregate {
private final DomainEventPublisher domainEventPublisher;
protected void publish(DomainEvent domainEvent) {
domainEventPublisher.publish(domainEvent);
}
}
Let's say we have UserAccount aggregate:
public class UserAccount extends UUIDAggregate {
private String email;
private String username;
private String password;
private String firstName;
private String lastName;
public void update() {
publish(new DomainEventImpl());
}
}
Here is my DomainEventPublisher:
public interface DomainEventPublisher {
void publish(DomainEvent event);
}
Here is DomainEventPublisherImpl:
#Component
public class DomainEventPublisherImpl implements DomainEventPublisher{
#Autowired
private ApplicationEventPublisher publisher;
public void publish(DomainEvent event){
publisher.publishEvent(event);
}
}
Now, this seems like a good idea, the domain is separated from implementation but this does not work. DomainEventPublisher cannot be Autowired because UUIDAggregate is not a #Component or #Bean . One solution would be to create DomainService and publish event there but that seems like leaking of domain to domain service and if I go that way, I am going to anemic model. Also what I can do is to pass DomainEventPublisher as a parameter to every aggregate but that also does not seems like a good idea.
One idea would be to have a factory for domain objects:
#Component
class UserAccountFactoryImpl implements UserAccountFactory {
#Autowired
private DomainEventPublisher publisher;
#Override
public UserAccount newUserAccount(String email, String username, ...) {
return new UserAccount(email, username, ..., publisher);
}
}
Then your code creating a domain object is "publisher-free":
UserAccount userAccount = factory.newUserAccount("john#example.com", ...);
Or you might slightly change the design of the event-publishing:
public abstract class UUIDAggregate {
private final List<DomainEvent> domainEvents = new ArrayList<>();
protected void publish(DomainEvent domainEvent) {
domainEvents.add(domainEvent);
}
public List<DomainEvent> domainEvents() {
return Collections.unmodifiableList(domainEvents);
}
}
#Component
class UserAccountServiceImpl implements UserAccountService {
#Autowired
private DomainEventPublisher publisher;
#Override
public void updateUserAccount(UserAccount userAccount) {
userAccount.update();
userAccount.domainEvents().forEach(publisher::publishEvent);
}
}
This is different from your proposal: the service publishes the events, but doesn't create then - the logic stays in the domain object.
Further, you can change your publisher to minimize the boiler-plate code:
public interface DomainEventPublisher {
void publish(UUIDAggregate aggregate);
}
Vaughn Vernon in his book IDDD just uses singleton like this:
DomainEventPublisher.instance().register(...);
DomainEventPublisher.instance().publish(...);
I know this approach doesn't use spring injection but it's much simplier than passing publisher to every aggregate and not that hard to test.

#JsonCreator not working for #RequestParams in Spring MVC

#JsonCreator not deserialising #RequestParam of type enum
I am working on a Spring application where the controller is receiving list of request params that Spring is binding to a wrapper object. One of the params is of type enum where I am receiving it by some property name.
Endpoint example: http://localhost:8080/searchCustomers?lastName=Smith&country=Netherlands
#RequestMapping(value = "/search/customers", method = RequestMethod.GET)
public CustomerList searchCustomers(#Valid CustomerSearchCriteria searchCriteria)
public class CustomerSearchCriteria {
private String lastName;
private Country country;
}
public enum Country {
GB("United Kingdom"),
NL("Netherlands")
private String countryName;
Country(String countryName) {
countryName = countryName;
}
#JsonCreator
public static Country fromCountryName(String countryName) {
for(Country country : Country.values()) {
if(country.getCountryName().equalsIgnoreCase(countryName)) {
return country;
}
}
return null;
}
#JsonValue
public String toCountryName() {
return countryName;
}
}
I am expecting Spring to bind enum Country.Netherlands to CustomerSearchCriteria.country but its not doing it so. I tried similar annotations with #RequestBody and that works fine, so I am guessing he Spring binding is ignoring #JsonCreator.
Any helpful tips would be appreciated.
Here is the code that is behind #Mithat Konuk comment.
Put in your controller something like:
import java.beans.PropertyEditorSupport;
#RestController
public class CountryController {
// your controller methods
// ...
public class CountryConverter extends PropertyEditorSupport {
public void setAsText(final String text) throws IllegalArgumentException {
setValue(Country.fromCountryName(text));
}
}
#InitBinder
public void initBinder(final WebDataBinder webdataBinder) {
webdataBinder.registerCustomEditor(Country.class, new CountryConverter());
}
}
More information ca be found here: https://www.devglan.com/spring-boot/enums-as-request-parameters-in-spring-boot-rest.

Spring Mongo DB with Annotation based configurations

I am learning Spring Boot and I am trying to make a very simple app that fetches data from Mongo DB by using Dynamic Queries. I am using Intellij as my IDE.
FILE: application.properties (inside resource folder)
spring.mongo.host=127.0.0.1
spring.mongo.port=27017
spring.mongo.databaseName=spring
FILE: person.java
#Document (collection = "person")
public class Person {
#Id
String id;
int age;
String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
FILE: MyRepo.java
#Repository
public interface MyRepo extends PagingAndSortingRepository<Person, String> {
public List<Person> findAllByName(String name);
}
FILE: Config.java
#Configuration
#EnableMongoRepositories(basePackages = {"mongo.customQueries"})
public class Config {
}
FILE: Main.java
public class Main {
#Autowired
public static MyRepo myRepo;
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
MyRepo myRepo = context.getBean(MyRepo.class);
System.out.println(myRepo.findAllByName("Avishek"));
}
}
When I run the project, I get an error
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [mongo.customQueries.MyRepo] is defined
What is it that I am missing here? Why is my MyRepo bean not created as most of the examples in net are doing so.
The problem is you want to annotation the MyRepo in the Main class, please remove it as below:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
MyRepo myRepo = context.getBean(MyRepo.class);
System.out.println(myRepo.findAllByName("Avishek"));
}
}
If someone could just give me a simple example to run Dynamic Queries
in Spring boot with mongo. Some examples similar to that of above. Or
how can I make the above example correct.
You can see working example here. And find explanations here.

Categories