Spring - JPA - Hibernate how to use EntityManager - java

I'm trying to build REST application using following tech stack:
Spring
VueJs
JPA (Hibernate)
This is my first experience in writing Sping application and web app development overall.
I have 4 tables in my DataBase:
Language
Sentence
Rule
User
For example in Rule there is :
Rule create(EntityManagerFactory factory, String type, String hint, String help, Language language);
List<Rule> readAll(EntityManagerFactory factory);
Rule readID(EntityManagerFactory factory, int id);
void update(EntityManagerFactory factory, String type, String hint, String help, Language language);
So there is my questions:
When I create Controllers for each table, I use the CRUD methods to modify (or not) my database, and I return a view for my HTML and VueJS part. But my method need an EntityManagerFactory, should I create a field in each Controllers class or this is not how I'm supposed to do ?
Do I need to create a bean file and configure it or persistence.xml and pom.xml are enough?
Thanks

Seems like your first question can be broken up into multiple concerns.
When I create Controllers for each table, I use the CRUD methods to modify (or not) my database, and I return a view for my HTML and VueJS part. But my method need an EntityManagerFactory, should I create a field in each Controllers class or this is not how I'm supposed to do?
Since you have already accepted an answer that recommends the use of spring-data-jpa. You will be dealing with entities and repositories.
Entities are JPA managed beans that will interact with your database.
#Entity
#Table(name = "rule")
public class Rule {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
long id;
String type;
...
#OneToOne
#JoinColumn(...)
Language language;
}
Repositories will provide all the necessary operations required to perform an action against your database. With JPA you can create an interface that extends CrudRepository which would provide you with some CRUD operations that come free with it. findOne(/* id */), delete(), save()
#Repository
public interface RuleRepository extends CrudRepository<Rule, Long> {
// You can easily specify custom finders
public List<Rule> findByType(String type);
}
But my method need an EntityManagerFactory, should I create a field in each Controllers class or this is not how I'm supposed to do?
It's typically frowned upon to have a request/response object to be JPA entity. See the linked answer for should i use jpa entity in rest request and/or response
There are multiple approaches that you can take to take a controller request and send a response to your client side project.
#Controller
public class RuleController {
#Autowired
private RuleRepository ruleRepository;
// Approach 1: Use Request Parameters - enforce inputs
#PostMapping("/rule/:id")
public Rule postWithRequestParams(#PathParam("id") Long id,
#RequestParam("type") String type,
#RequestParam("hint") String hint,
#RequestParam("languageField1") String languageField1) {
Rule inputRule = new Rule(id, type, hint, new Language(languageField1));
Rule responseRule = ruleRepository.save(inputRule);
return responseRule; // I would imagine you would want to set up a model for the response itself
}
// Approach 2: Use RequestBody - serialize Rule from the request
#PostMapping("/rule/:id")
public Rule postWithRequestParams(#PathParam("id") Long id, #RequestBody Rule inputRule) {
Rule responseRule = ruleRepository.save(inputRule);
return responseRule;
}
Do I need to create a bean file and configure it or persistence.xml and pom.xml are enough?
If you have added spring-boot-starter-data-jpa as a dependency, a lot of the bean configuration has already been done for you.
In your main/src/resources (you should have an application.properties or application.yml)
spring.datasource.url= # JDBC url of the database.
spring.datasource.username= # Login user of the database.
spring.datasource.password= # Login password of the database.
Spring does a lot of the magic and heavy lifting for you.

If you are using spring Boot then you don't need entity manager. All you need to do is to define Datasource in you properties file. And create a Bean in our Configuration class just like:
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource datasource() {
return DataSourceBuilder.create().build();
}
Now rest of the things you can handle with repositories.They will be like:
import org.springframework.data.repository.CrudRepository;
public interface RuleRepository extends CrudRepository<Rule, Long> {
}
In your controllers you will use it like:
#Autowired
private RuleRepository ruleRepository;
#Get
#Path("/getRule/:id")
public Rule find(#PathParam("id")Long id){
return ruleRepository.findOne(id);
}
These dependencies I used in my gradle project. You will find Maven version for same:
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile group: 'mysql', name: 'mysql-connector-java'

You definitely need to have a look on Spring Boot(http://start.spring.io), it allows easier to start web app development. As for persistence layer you could use Spring Data JPA(already includes Hibernate) module which also can be easily integrated with Spring Boot. The beauty of Spring Data that is already have written by default most queries like save(), remove(), find() and so on. You only need to define Objects which will be used by Spring Data.
Update: See my Spring Boot REST API example here

Related

Should i never use 'new' keyword on a spring boot project?

I'm working on Spring Boot Rest API, and I did end up using the new keyword here and there.
I'm wondering, did I do something wrong when I used the new keyword for my program. And if it is absolutely forbidden to use new keyword on a real project.
If the answer is yes should i annotate each class i wrote with #component annotation so i can instantiate an object using #autowired.
If the answer is no when can we break that rule ?
You can create objects using the new keyword in a spring application.
But these objects would be outside the scope of the Spring Application Context and hence are not spring managed.
Since these are not spring managed, any nested levels of dependency (such as your Service class having a reference to your Repository class etc)
will not be resolved.
So if you try to invoke a method in your service class, you might end up getting a NullPointer for the repository.
#Service
public class GreetingService {
#Autowired
private GreetingRepository greetingRepository;
public String greet(String userid) {
return greetingRepository.greet(userid);
}
}
#RestController
public class GreetingController {
#Autowired
private GreetingService greetingService;
#RequestMapping("/greeting")
public String greeting(#RequestParam(value = "name", defaultValue = "World") String name) {
return String.format("Hello %s", greetingService.greet(name));
}
#RequestMapping("/greeting2")
public String greeting2(#RequestParam(value = "name", defaultValue = "World") String name) {
GreetingService newGreetingService = new GreetingService();
return String.format("Hello %s", newGreetingService.greet(name));
}
}
In the above example /greeting will work but /greeting2 will fail because the nested dependencies are not resolved.
So if you want your object to be spring managed, then you have to Autowire them.
Generally speaking, for view layer pojos and custom bean configurations, you will use the new keyword.
There is no rule for using or not using new.
It's up to you if you want Spring to manage your objects or want to take care of them on your own.
Spring eases object creation, dependency management, and auto wiring; however, you can instantiate it using new if you don't want that.
I think its fine to use new keyword, but you should learn the difference between different stereotype (Controller, Service, Repository)
You can follow this question to get some clarity:
What's the difference between #Component, #Repository & #Service annotations in Spring?
Using appropriate annotation will allow you to correctly use DI (dependency injection), that will help in writing sliced tests for your spring boot application. Also the Service,Controller and Repository components are created as Singleton, so lesser GC overhead. Moreover components that you create using new keyword are not managed by Spring, and by default Spring will never inject dependencies in a object created using new.
Spring official documentation:
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
You will need new on Spring mock tests when you will have to create an object as service and inject mock object as dao.
Look at the following code; here as you see, based on a condition it's necessary to dynamically load advertisements on demand. so here you can not #autowire this group of items because all the information are loaded from DB or an external system, so you just need to fill you model accordingly.
if (customer.getType() == CustomerType.INTERNET) {
List < Advertisement > adList = new ArrayList < Advertisement > ();
for (Product product: internetProductList) {
Advertisement advertisement = new Advertisement();
advertisement.setProduct(product);
adList.add(advertisement);
}
}
Note it's appropriate to use Spring for managing external dependencies
like plugging a JDBC connection into a DAO or configurations like
specifying which database type to use.

What is the right design pattern to get a prototype-bean from a component-bean?

I am just wondering what a good architecture design looks like.
Let's say we have a CarRepository which manages all beans of type Car in a car rental application.
Car beans are of type prototype
CarRepository bean is of type repository (singleton)
Now, the CarRepository is asked to create a new Car bean, e.g. when the rental company has bought a new car.
Of course, I could implement ApplicatioContextAware and use context.getBean("car"), but for me, it doesn't fit well to the idea of dependency injection. What is best-practice for injecting a shorter-lived bean into a singleton?
Update: Maybe I should add an example to make it more clear.
#Repository
public class CarRepository {
private List<Car> cars;
public void registerNewCar(int id, String model) {
// I don't want to access the Spring context via ApplicationContextAware here
// Car tmp = (Car) context.getBean("car");
// car.setId(id);
// car.setModel(model);
// cars.add(tmp);
}
}
#Scope("prototype")
public class Car {
private int id;
private String model;
// getter and setters
}
Spring offers a mechanism that handles injecting a shorter-lived bean in a longer-lived one. It's called a scoped proxy. How it works is that the singleton is injected with a proxy that will handle method calls by searching the shorter scope (like session or request) for a bean instance and delegating to that instance.
You didn't specify, if you are using xml or annotations to configure your application or what version of Spring you are using. You can read more about configuring the scope proxy with xml in the reference guide. I'm going to give you an example how to configure it with annotations in a Spring 4-ish environment.
For me the best way is to use the meta-annotations mechanism. It allows you to create your own annotations that will be later used by Spring to configure your app. For example:
#Retention(RUNTIME)
#Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS)
public #interface SessionScoped{
}
Such an annotation, when specified on a #Component (or #Service or any other specialization) class or a #Bean method in your Java config will cause that bean to be injected as a proxy. For example:
#Configuration
#EnableAspectJAutoProxy
public class MyConfig{
#SessionScoped
#Bean
public MyClass myBean(){
// return your bean
}
}
All that being said, your example really makes me think you should be working with entities (Car) and repositories. See Spring Data if you are designing the model layer and you want to store Cars data in your database etc.
If you do not want to use context.getBean(...), then, you can construct the car using new Car(...) as it will have same effect.
These are only two ways!

Connecting Java Webapplication to MySQL with JPA and/or Hibernate?

Some days ago I heard about spring-boot.
So I started to setup my project from zero, include jpa and dont use older setups from existing projects. But now there is an understanding problem between what I've learned and what I've read about the "easy setup" with spring boot and jpa.
Usually my projects have this structur.
Model (for excample Car)
ModelDao (CarDao with the following code-example)
#Component
public class CarDao {
/** The Hibernate session factory. */
#Autowired
private SessionFactory sessionFactory;
#Transactional
public void save(Car car) {
sessionFactory.getCurrentSession().saveOrUpdate(car);
}
CarServiceImpl thats works with DAO´s (includes methods like findAll(), getCarById() or saveCar(Car car))
But now I only read about #Entity and JPA-repositorys.
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation? And my ServiceImples and JPA-repositorys have the same functionality? What happend with the SessionFactory? Is all managed automatically?
You dont need DAO if you are going to use JPA-Repositories.
As well Session-Factory also not required.
Just you need one Class as model and one interface as repository and you all done.
example:
#Entity
#Table(name="COUNTRY")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="COUNTRY_ID", nullable = false)
private Integer country_id;
#Column(name="COUNTRY_CODE")
private String country_code;
//Add getter and setter
}
interface
public interface CountryRepository extends PagingAndSortingRepository<Country, Integer> {
}
Yes you need to configure in spring.xml about where your above repository is located
<jpa:repositories base-package="com.repository" />
create transactionManager in spring.xml
and access it by using below code
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring.xml");
countryRepository = (CountryRepository) ctx.getBean("countryRepository");
Country country = countryRepository.findOne(1);
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation?
#Entity annotation is used on models your POJOs. #Entity maps the POJO i;e class properties to the db table. How would you write your business logic if you get rid of models.
Service layer, DAO layer are all components of application design. They have their specific role. ServiceImpl proverbially manages the transactions whereas DAO/Repository layer manages the communication with the db.
Here your CarDao class should be annotated with #Repository annotation. It is a DAOImpl class.
And all your transactional methods should move to the Service layer.
And my ServiceImples and JPA-repositorys have the same functionality?
No, as I've already stated they have specific respective functionality. They are not same.
What happend with the SessionFactory? Is all managed automatically?
SessionFactory is always injected into the DAO layer. You can either manage the sessions yourself or let hibernate manage the sessions.

How to disable Hibernate validation in a Spring Boot project

I have a spring boot project that has a CrudRepository, an Entity and a Controller. I am basically trying to persist an entity based on the data passed to the Controller.
To do this, I am using spring-boot-starter-jpa. My Entity is annotated with JSR-303 annotations, which are checked in the controller before the data gets passed to the CrudRepository for persistence.
Controller method:
#RequestMapping(value = "users", method = { RequestMethod.POST })
public SuccessfulResponse<User> addUser(#Valid #RequestBody User user, BindingResult validation) {
if (validation.hasErrors()) {
throw new ValidationException(validation);
}
User saved = this.users.save(user);
return new SuccessfulResponse<User>(saved);
}
Entity:
#Entity /* JPA */
public class User {
#Id /* JPA */
#Column(name="email_address", nullable=false, length=255) /* JPA */
#UserUnique
private String emailAddress;
}
The cause of my issues is the UserUnique annotation. Its validator looks like this:
public class UserUniqueValidator implements ConstraintValidator<UserUnique, String> {
private UserRepository users;
#Autowired
public UserUniqueValidator(UserRepository users) {
this.users = users;
}
#Override
public void initialize(UserUnique annotation) {}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return users.findOne(value) == null;
}
}
What seems to be happening is, the validation is getting run twice. Once in the controller via the #Valid annotation, and once when Hibernate tries to persist the object. However, when Hibernate tries to persist the object, it throws:
javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: class test.UserUniqueValidator`
This seems to be because its not spring-aware and cant inject the dependency into the constructor. So, what I want to do is disable Hibernate validation completely (as its redundant and already happening in the controller).
There seems to be a property called javax.persistence.validation.mode which you can set to none. However, I cant for the life of me figure out where to set it in a code-based configuration.
I realise there are questions like JSR-303 dependency injection and Hibernate but these are all using xml config and manually configuring parts of the persistence layer.
What I want to do is "post-configure" the required parts of the persistence layer that Spring Boot creates for me because if I define my own then I am no longer leveraging Spring Boot's auto configuration. Can anyone help me determine if 1) this is possible and 2) which parts do I need to configure and how?
Thanks!
As [M. Deinum] mentioned in a comment on my original post, the solution is to set:
spring.jpa.properties.javax.persistence.validation.mode=none
In the application.properties file.
Additionally, this behaviour is described here (its easy to miss because no example is provided).
#Erin Drummond's Answer is for database entity validation (individual records)
But if someone ran into a problem with schema validation below property works well.
# Hibernate ddl auto (create, create-drop, validate, update, none)
spring.jpa.hibernate.ddl-auto=none
Actually, in spring boot 2.x. it is:
spring.jpa.hibernate.ddl-auto: none
for spring boot unless you add validation dependency the spring validation would not kick in.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

How to Create a bean validation framework using Spring

I am having bean AddressBean, which has some properties like addressLine1, city etc.
Before persisting it to DB using AddressBeanService, I am prevalidating it, and after saving, i am post validating it, using preValidate and postValidate function in ValidateAddressService. And all this i am triggering from a AddressBeanHelper class.
class AddressBeanHelper{
AddressBean bean =null;
AddressBeanHelper(AddressBean bean){
this.bean=bean;
}
ValidationService validate=new ValidateAddressService();
function doStuff(){
validate.preValidateAddressBean (bean);
//business logic for AddressBean
validate.preValidateAddressBean (bean);
}
}
class ValidateAddressService implements ValidationService <AddressBean>{
preValidateAddressBean (AddressBean bean){
//here is the issue
}
preValidateAddressBean (AddressBean bean){
//here is the issue
}
}
I want some framework or trick in spring by which i just need to write generic code in validation functions and externalize my validation rule outside the code itself.
Like a rule engine which can automatically validates each and every property of bean.
currently my application infrastructure is spring/hibernate for server side, jsp/jquery on client side and deployment server is on heroku.
Have a look at this one:
http://hillert.blogspot.com/2011/12/method-validation-with-hibernate.html
It supports JSR-303, so its a standard. Its very easy to implement, and it supports, custom and some predefined ready to use validators.
You can also find some references here:
http://java.dzone.com/articles/method-validation-spring-31

Categories