We have now configured the persistence layer of our Spring application. We are finally ready to create our first Spring Data JPA repository.
This blog post describes how we can create a repository that provides CRUD operations for todo entries.
Let’s get started.
If you are not familiar with Spring Data JPA, you should read the following blog posts before you continue reading this blog post:
- Spring Data JPA Tutorial: Introduction provides a quick introduction to Spring Data JPA and gives an overview of the Spring Data repository interfaces.
- Spring Data JPA Tutorial: Getting the Required Dependencies describes how you can get the required dependencies.
- Spring Data JPA Tutorial: Configuration describes how you can configure the persistence layer of a Spring application that uses Spring Data JPA.
Creating the Repository
Before we can create our first Spring Data JPA repository, we have to create an entity class that contains the information of a single todo entry. The relevant part of the Todo class looks as follows:
import org.hibernate.annotations.Type; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.PrePersist; import javax.persistence.Table; import javax.persistence.Version; import java.time.ZonedDateTime; @Entity @Table(name = "todos") final class Todo { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "creation_time", nullable = false) @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime") private ZonedDateTime creationTime; @Column(name = "description", length = 500) private String description; @Column(name = "modification_time") @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime") private ZonedDateTime modificationTime; @Column(name = "title", nullable = false, length = 100) private String title; @Version private long version; //The constructor, builder, and other methods are omitted }
We are now ready to create our first Spring Data JPA repository. We can create the repository that provides CRUD operations for Todo objects by using one of the following methods:
- Create an interface that extends the CrudRepository interface.
- Create an interface that extends the Repository interface and add the required methods to the created interface.
Let’s take a closer look at these methods.
Extending the CrudRepository Interface
If we create our repository by extending the CrudRepository interface, we have to provide two type parameters:
- The type of the entity that is managed by our repository.
- The type of the entity’s id field.
In other words, when we create the repository that provides CRUD operations for Todo objects, we have to provide the following type parameters:
- The type of the entity is Todo.
- The type of the entity's id field is Long.
The source code of the TodoRepository interface looks as follows:
import org.springframework.data.repository.CrudRepository; interface TodoRepository extends CrudRepository<Todo, Long> { }
The CrudRepository interface declares many methods, but the methods that are relevant for this blog post are described in the following:
- The void delete(T entity) method deletes the entity whose id is given as a method parameter.
- The Iterable<T> findAll() method returns all entities that are saved to the database.
- The T findOne(Long id) method returns the entity whose id is given as method parameter. If no entity is found, this method returns null.
- The T save(T entity) method saves the entity given as a method parameter and returns the persisted entity.
Let’s find out how we can create a repository interface that extends the Repository interface.
Extending the Repository Interface
If we create our repository by extending the Repository interface, we have to follow these steps:
- Provide two type parameters:
- The type of the managed entity (Todo).
- The type of the entity’s id field (Long).
- Add the required methods to the repository interface:
- The void delete(Todo deleted) method deletes the Todo object given as a method parameter.
- The List<Todo> findAll() method returns all Todo objects that are found from the database.
- The Optional<Todo> findOne(Long id) method finds the todo entry whose id is given as a method parameter. If no todo entry is found, this method returns an empty Optional.
- The Todo save(Todo persisted) method saves the Todo object given as a method parameter and returns the persisted object.
The source code of the TodoRepository interface looks as follows:
import org.springframework.data.repository.Repository; import java.util.List; import java.util.Optional; interface TodoRepository extends Repository<Todo, Long> { void delete(Todo deleted); List<Todo> findAll(); Optional<Todo> findOne(Long id); Todo save(Todo persisted); }
Additional Reading:
- The Javadoc of the Repository interface
- Spring Data JPA Reference Manual: 3.3.1 Fine-tuning repository definition
- What’s New in Spring Data Dijkstra (search for 'support for wrapper types as return values')
Let’s move on and find out which method we should use.
Which Method Should We Use?
It depends.
I know that this is probably the most annoying answer one can give to a question. That is why I created two rules that we can follow when we are creating Spring Data JPA repositories. These rules are:
- If we want to expose all repository methods that are declared by the CrudRepository interface AND we don’t want to return Optional (Guava / Java 8) objects, our repository interfaces should extend the CrudRepository interface.
- If we don’t want to expose all repository methods that are declared by the CrudRepository interface OR we want to return Optional (Guava / Java 8) objects, our repository interfaces must extend the Repository interface.
Case closed?
Not exactly. I argue that we should always use the second method. This opinion is based on two reasons:
- When we create an interface, we should not add unnecessary methods to it. We should keep the interface as small as possible because small interfaces are easier to use and they help us to create components that have only one job.
- Optional helps us to create better APIs because it reveals that there might not be a return value.
If we create our repositories by extending the Repository interface and adding the required methods to the created repository interfaces, we need to add the "same" methods to every interface. Right?
Wrong.
We can avoid this by following these steps:
- Create a base interface that extends the Repository interface and add the common methods to that interface.
- Create the actual repository interface that extends our base interface.
Let’s move on and take a closer look at these steps.
First, we have to create a base interface that declares the methods shared by our repositories. We can do this by following these steps:
- Create the BaseRepository interface that extends the Repository interface. This interface has two type parameters:
- T describes the type of the managed entity.
- ID describes the type of the entity’s id field.
- Annotate the created interface with the @NoRepositoryBean annotation. This ensures that Spring Data JPA doesn’t try to create an implementation for our base repository interface.
- Add the common methods to the created interface.
The source code of the BaseRepository interface looks as follows:
import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.Repository; import java.util.List; import java.util.Optional; @NoRepositoryBean interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> { void delete(T deleted); List<T> findAll(); Optional<T> findOne(ID id); T save(T persisted); }
Second, we have to create the actual repository interface that extends our base interface. We can do this by following these steps:
- Create the TodoRepository interface.
- Extend the BaseRepository interface and provide two type parameters:
- The type of the managed entity is Todo.
- The type of the entity’s id field is Long.
The source code of the TodoRepository interface looks as follows:
interface TodoRepository extends BaseRepository<Todo, Long> { }
We have now created a repository hierarchy that allows us to:
- Create repositories that provides CRUD operations for entities without declaring the "same" methods in every repository interface.
- Create repositories that do not provide all CRUD operations. For example, we can create a repository that provides only the findAll() method.
The following figure illustrates the benefits of this solution:
Let’s move on and summarize what we learned from this blog post.
Summary
This blog post has taught us three things:
- We can create repository interfaces by extending either the CrudRepository or the Repository interface.
- We should create our repositories by extending the Repository interface and adding the required methods to the created repository interface.
- If our application has more than one repository, we should create a base repository interface that declares the methods that are shared by our "concrete" repositories.
The next part of this tutorial gives an introduction to query methods.
P.S. You can get the example application of this blog post from Github.
Great stuff.
Hello,
Thanks for your article. But where is the controller.createRedirectViewPath(REDIRECT_PATH) method in the net.petrikainulainen.spring.datajpa.controller.AbstractControllerTest class?
Best regards.
Chris
Hi Chris,
it is good to hear that you liked the article. The method you mentioned is found from the net.petrikainulainen.spring.datajpa.controller.AbstractController class. The AbstractControllerTest class declares the inner class called TestController only because the AbstractController class is abstract and it cannot be instantiated.
Why bother with dtos? I thought that was ejb 2 nonsense
Hi Rance,
Thanks for your comment. I prefer using DTOs as form objects from following reasons:
1) Since the transaction boundary is on the service layer, the model object is no longer associated with the persistence context when the transaction ends (unless you use an extended persistence context but that is an another story). This means that if you are using them as a form objects, you will have to synchronize its state with the database. Even though you "can" use the merge() method of the EntityManager interface, it can be PITA, and a source of interesting features. Thus, I prefer to avoid this if possible.
2) The domain model should not be designed to make sense as a form object. It should be designed and implemented to make sense in the context of its domain. Also, you have to often make some ORM related compromises. This means that the building forms by using entity classes as form objects can be cumbersome. It is often easier to use DTOs even though it is not so "sexy".
3) Often you have to add validation related metadata to the form objects. Adding these annotations to an entity object will object produce messy outcome, since entities are already annotated with JPA related annotations.
I know that using DTOs as form objects means that I have to write some boilerplate code. However, it helps me to isolate the different layers of my software and to avoid weird features, which are sponsored by the used ORM.
Hi.
First of all congratulations for your blog and for the tutorials that you post, they are very interesting and useful! I've also read your Spring Data book, and I have found this page that your are the author :) !
I've reached this page searching google for DTO. So my problem is more related to usage of DTO than to the usage of JPA, but if you have few minutes to spare, I would make you my question.
Most likely you have had to deal with applications where the same domain Entity must be able to be modified by users with different privileges, and depending on the user privilege, only a subset of the fields could be editable.
I think that it is one of the case where usage of DTOs make sense!
In my case I have a Job entity that can be modified by different user with different roles, and based on the role only some field can be modified.
So my question: a good approach could be to define an entity related DTO for each user ROLE? (For example: JobAdminDTO, JobUserDTO, JobGuestDTO).
So in MVC application controller, given the user role i create the correct DTO and pass it to the view. I think that could be a bit harder to handle the correct type of the object returned from the view..
In your opinion, could it be a good approach?
Thanks again and sorry if I've bored
Marco
Hi Marco,
That is an interesting question because the requirement which you have to implement is quite common. As always, there are many ways to implement this requirement.
You found the first one which often comes to mind (use different DTOs for different roles).
This approach has four problems:
The second option is to use the same DTO for all roles and limit the editability of the form fields by using the
authorize
tag of the Spring Security JSP tag library.You can also create a custom HandlerMethodArgumentResolver which makes it possible to add the logged in user as a method parameter to your controller method.
This approach has two problems:
There is also a third option but it might not be usable if you are implementing a "normal" Spring MVC application (no REST API) because it requires that you add several submit buttons to your page. This option is that you are create one form for the fields which are common for all users and one form per each user role.
As you can see, this problem has no "right" answer. There are several ways to implement this requirement and each one has different pros and cons. However, I hope that was able to give you something to think about.
Great tutorial, it really helped clear up some confusion I had. I have been playing with this code and i was wondering if you could show how to use Jersey REST instead of Spring MVC? I have not been able to replace the Servlet with the Jersey SpringServlet because of the need to load the context programatically (which I love how you did).
I tried this in the DataJPAExampleInitializer but of course it failed:
rootContext.addApplicationListener(new org.springframework.web.context.request.RequestContextListener());
rootContext.addApplicationListener(new org.springframework.web.util.Log4jConfigListener());
SpringServlet springServlet = new com.sun.jersey.spi.spring.container.servlet.SpringServlet();
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, springServlet);
Any ides on how this might work?
David,
Thanks for your comments. It is good to hear that this tutorial was useful to you. Regarding to your problem:
The attached source code does not set an url mapping for the springServlet. What kind of exception are you getting? Is it related to the missing url mapping?
Petri,
I was trying to use the Jersey Spring Servlet instead of the DispatchServlet. But two things convinced me to change my direction and stick with SpringMVC:
1) Version 3.1.1 added much better REST support, which previous attempts were so kludgy I went with Jersey.
2) While looking at the Jersey site for a solution, I see that they will be releasing 2.0 that will not be backwards compatible, and I really don't feel like rewriting my work for that in the near future.
Thank you again for a great tutorial, and I look forward to learning how SpringMVC and JPA work together now.
Hi David,
I am happy to hear that you found an answer to your problem. Also, I agree that the REST support of Spring Framework is rather good at the moment.
Please remember that you can use JPA with Spring Framework without using Spring Data JPA but that does not really make any sense if you can build your applications from scratch.
On the other hand, if you are working with existing applications, you might not want to replace existing persistence layer with Spring Data JPA repositories.
Hi Petri,
Great articles on spring data jpa. One thing I noticed was the update method on the serviceImpl is not actually updating. I tested the code and the updates don't seem to get persisted. Am I making a mistake or is it really missing? Let me know. I am a bit confused because after so many views, none have pointed that one out.
-Ramesh
Hi Ramesh,
Thanks for your feedback. Did you experience this issue when running my example application? The reason why I am asking this is that I just tested the example application (https://github.com/pkainulainen/Examples/tree/master/Spring/data-jpa/tutorial-part-two) and found out that updating the information of a person works on my computer (Yeah, epic excude). Anyway, if you are running this example application application and the update method does not work, could you let me know. Also, if you have made any changes to the code, could you paste them to Pastebin so that I can help you out.
If you are trying to apply the principles mentioned in this blog entry in another application, ensure that when the update method is called, you are inside a read-write transaction. The save() method of the repository is not called in my example because all changes made to persistent objects are flushed back to the database when a read-write transaction is committed.
Thanks for the reply Petri. I was not exactly trying out your example, but had followed your example in a sample project of mine. I've extracted the relevant pieces and loaded it into paste bin at http://pastebin.com/SMR9fbWV. I have the disable method as a part of the transaction. Please take a look and let me know. In the meantime, I will also test our your application as it is.
Hi Ramesh,
The codes you pasted in Pastebin seems fine to me. It would be helpful if you could answer to following questions:
- Are you using Hibernate or some other persistence provider? Which version do you use?
- Which version of the Spring Data JPA are you using?
- Which transaction manager are you using?
- Which database you are using?
This would help me to replicate your environment which helps me to find the reason of your problem.
Hi Petri,
- Are you using Hibernate or some other persistence provider? Which version do you use?
I am using hibernate 3.5.6
- Which version of the Spring Data JPA are you using?
1.0.3
- Which transaction manager are you using?
Spring's transaction manager
- Which database you are using?
HSQLDB
I have the relevant parts of the POM in paste bin here http://pastebin.com/igSc1MK9
Hi Ramesh,
I tried changing the dependency versions of my example application to match yours, and updating the information of a person is working without calling the save() method of the PersonRepository. When you said that you are using Spring's transaction manager, were you referring to the JpaTransactionManager (I use it in my example application)?
Hi Petri,
I was not able to reply to your last comment. So doing it here. First, thank you for your patience and persistence in trying to find the cause. It rare to find people like that. In my case, I pretty much use the same configuration as yours, but I use XML instead of java for configuration. Relevant parts of my configuration are at http://pastebin.com/ix2v6hmY. I have not yet tried your exact application. I will do so tonight and update you.
Thanks,
Ramesh
Hi Ramesh,
It is always nice to do some detective work and solve interesting problems. :)
I looked at the configuration, which you added at Pastebin, and it looked fine to me. However, have you enabled the annotation driven transaction management in your application context configuration file? If you are using XML, you can do this by adding the following line to your application context configuration (or by adding the @EnableTransactionManagement annotation to your application context configuration class):
<tx:annotation-driven transaction-manager="transactionManager"/>
More information about this is found at the reference documentation of Spring Framework 3.1.x:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#transaction-declarative-annotations
Hi Petri,
very nice tutorial, learning new things, very helpful.
can you just show how to block crud operations.
I created one entity and repository using spring-data-Jpa extending CrudRepository. But I dont want to allow CRUD operations, I need to block them. For in case if I want to delete any entry in database throu service I need to get an error code. Is there any way to block crud operations? Thanks
Hi Applebee,
I would use Spring Security to deny access to unwanted operations. Check out the homepage of the Spring Security project: http://static.springsource.org/spring-security/site/.
can you show with an example how to use Spring Security to deny access?
Hi Applebee,
The exact process is too long to be described in a comment but there are several Spring Security tutorials available on the internet. Here are few of them:
Hi Petri,
Thanks for your reply. I have one more question, from the above Person example
when I created the PersonRepository I added one method findByFirstName which I am able to get the results. Here I don't want to add findBy for other attributes.
So when I was trying to search with other attibutes it is giving 500 Internal Server Error. Is there any way to customize that kind of exceptions.
Thank you.
Hi Applebee,
If you are talking about the exceptions that are thrown by Spring Data JPA or Spring Framework, it is not possible to customize them without changing the source code of the framework in question.
However, it is possible to configure an exception handler that specifies the view that is rendered when a specific exception is thrown. More information about this is found from the reference manual of Spring Framework:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers
Also, I would probably use the approaches described in later parts of my Spring Data JPA tutorial for implementing the search function you mentioned. Using the query generation from method name strategy for this purpose is not very user friendly because is not possible to implement a case insensitive search with it.
Hi Petri,
this is Jagadeesh i am developing one web application in which i am using spring mvc4.0 and spring data jpa .In this application i am developing simple registration page which contains fields of three entities now, the problem is how to insert data into three tables or three entites by form submission of registration page.Along with i am having small doubt i.e. in JPA we are having save() which meant for saving data into database
but for updating data is their any default method in JPA?
The above are the two problems which i am facing from few days onwards
if Know please help me to get rid of this problem
Thanks&Regards
jagadeesh
Hi Petri,
I have a database view "Example"
Example
id name
--------------------
100 HELLO
100 HELLO WORLD
200 TEST
200 TEST123
300 APPLE
Created entity and repository for Example using JPA Annotations
Entity: Example.java and the repository class ExampleRepository extends CrudRepository
HTTP GET to the application:
localhost:8080/data
{
"_links" : [ {
"rel" : "data",
"href" : "http://localhost:8080/data/data"
} ]
}
localhost:8080/data/data
{
"_links" : [ {
"rel" : "data.Example.100",
"href" : "http://localhost:8080/data/data/100"
}, {
"rel" : "data.Example.100",
"href" : "http://localhost:8080/data/data/100"
}, {
"rel" : "data.Example.200",
"href" : "http://localhost:8080/data/data/200"
}, {
"rel" : "data.Example.200",
"href" : "http://localhost:8080/data/data/200"
}, {
"rel" : "data.Example.300",
"href" : "http://localhost:8080/data/data/300"
}, {
"rel" : "data.search",
"href" : "http://localhost:8080/data/data/search"
} ]
}
Is there any way I can search using multiple parameters like
localhost:8080/data/data/search/id?id=(100,200)
or using IN operator
Thanks
Hi Applebee,
One comment about your web layer:
I would consider using POST and sending the search conditions as JSON in the request body. This makes a lot more sense than your current approach since it seems that you want to send 0..* ids to your controller method.
About the query creation:
I would use Querydsl or the JPA Criteria API to build the actual query. If you have no experience from these techniques, you might want to check out these blog entries:
However, the creation of a query that uses the IN operator is not described in those entries. I managed to find one article that has an example of the usage of IN operator and the JPA Criteria API: Dynamic, typesafe queries with JPA 2.0.
Hi Petri,
Your tutorial is honestly the best source of information about Spring Data right now, you are also very good at explaining everything.
Unfortunately, I recently encountered a problem and didn't really figured out any easy way to deal with it.
Let's say you want to add the following Column to Person.java
@Column(name = "Alias", unique = true)
private String alias;
How would you ensure the Uniqueness of this alias. So far, adding a custom validator that check for unicity using a query at the DTO level doesn't really solve the problem as any concurrent transaction could modify data after a manual check but before the commit of the ongoing transaction. And secondly, as I'm not using @Validator on the Entity itself but on the DTO, there's isn't any straightforward way to get the errors and feed it back to my view.
Any idea on how to solve this problem?
Thank you
Hi Marc,
It is good to hear that you like my tutorial. About your problem:
This is indeed a tricky one since you cannot really know whether a unique constraint is broken until you save the entity to the database (I am assuming that you have got unique constraint for the Alias column at database). There are some useful pointers at stackoverflow:
It seems that there is no elegant and portable way to handle this. However, we can do something about it. I would try to minimize the chance that the unique constraint is broken by following these steps:
What do you think about this solution?
Petri,
Thanks for the wonderful tutorials!
It is not rare for real-world application to involve a couple of hundred database tables. Normally we would use code-generation tools such as Jboss Tools to reverse-engineer an existing database and automatically generate entity classes and JPA annotations. The Person class in your tutorial is highly customized. How do you generate that kind of customized code if you have to deal with a couple of hundred tables?
Hi Don,
It was nice to hear to that you like my tutorials. Also, I want to thank for an excellent question.
Unfortunately, as far as I know, there is no way generate "customized" domain model classes automatically. As you said, one can use code generators to generate entities from an existing database but typically this leads in to a anemic domain model. For a quite long time I was writing applications that used this approach and I was perfectly happy with it.
However, then I read a book called Domain Driven Design and saw the light. The problem with my old approach was that I kind of got all the problems caused by object-relational mismatch and got none of the benefits. All my business logic was scattered around the service layer, which made my service classes look like a mess. Now, when I moved the business logic from the service layer to the domain model, I got the following benefits:
Because of these benefits I am ready accept that I will spend a lot of time working with my domain model. Also, since I have been mostly participated in software development projects that uses Agile methods, the implementation and design of the application is divided in to sprints so I never have to face the horrible task of fixing the whole domain model at once (As you stated, it would be a huge task since the databases of real world applications tend to have a lot of tables).
Why is it so difficult to write package statements in the code?
some libraries is not in the initial pom file e.g. apache lang commons
Hi Mladen,
I left the import statements out because I felt that including them would make this blog entry too long. Also, since I have included a fully functional example application, I thought that adding them would add little value. It seems that I might have rethink my attitude and add import statements (I will leave the obvious ones out though) to the code samples that are attached to my blog entries. This might take some time so be patient. :)
Regarding to your second point, the pom file of my example application declares all the required dependencies (including commons lang).
Hi Petri,
Great tutorial!! Excellent Job!! I'm having some trouble running the tutorial on Tomcat could you guide me on how to migrate it from jetty to tomcat? I tried removing the webdefault.xml and writting an new web.xml but it isn't working the Spring context is not beeing loaded.
Thanks in advance
Mildo
Hi Mildo,
Thanks for your comment. It is nice to know that you like this tutorial.
Are you trying to deploy the created war file directly to Tomcat or are you using the Tomcat Maven plugin? The webdefault.xml file is required only because the sample project is using an old version of the Jetty Maven plugin. I should probably update this plugin and remove the unnecessary files from the sample project.
Update: Check this comment out if you are using Tomcat 6.
Hi Petri
Thanks for the wonderful article but cannot deploy the example on tomcat
Can you please send me a web.xml for tomcat asap
Regards
Vipul
Hi Vipul,
Thanks for your comment!
This example requires that a Servlet 3.0 compliant servlet container is used and it should work fine with Tomcat 7. If you are using an older version of Tomcat, you cannot configure your web application by using programmatic configuration. In other words, you have to delete the
DataJPAExampleInitializer
class and create a web.xml file. This process is explained in the following article:Bootstrapping a web application with Spring 3.1 and Java based Configuration, part 1
Also, let me know if you are using Tomcat 7 and cannot deploy the example application.
Petri,
Perhaps I'm missing the advantage of using the builder pattern because of the simplicity of its use in the Person class, but it doesn't seem like it is buying you anything more than a straight constructor or a static method would. Instead by using it you have to construct an extra object and make an extra call.
What am I missing?
Hi Josh,
you are right. In this example the builder pattern is definitely an overkill and it would be better to use a regular constructor. However, I used it on this example because wanted to emphasize that it is a good way to create new objects (especially when the created object has a lot of optional parameters). The alternatives of the builder pattern are:
The builder pattern combines the safety of the telescoping constructor pattern and the readability of the Javabeans style construction. That is why it should be used on model objects unless you have a REALLY good reason not to use it.
So, perhaps the issue I'm having in seeing the applicability is that all of the main fields in the Person object are required. How does this pattern take care of the telescoping constructor pattern for optional parameters? Say you add height, weight, and hairColor to Person. Do you just end up with telescoping parameters in your builder object? Or do you construct the object with the builder and then resume using the setters for the rest?
When I searched for the pattern online the applicability seemed to center on complex construction tasks, like in the cases where object creation involves the coordination of several other objects or involves some tricky sequencing.
Thanks
Hi Josh,
Optional properties are dealt with by creating so called property methods that are used to set the optional parameters. Here is the source code of the Person class that has the optional parameters you suggested:
Here are some examples that illustrate the usage of these property methods:
I hope that this example answered to your question.
Thanks, yes that helps. So from your latest example I can see where you could put some integrity checks in the build() method allowing you to ensure that the optional attributes are set consistently with each other before giving access to the Person object. However, I can also see where you would need to be careful with this pattern as your objects could easily become immutable or very difficult to update without client classes also maintaining a reference to the builder that created the object in the first place.
what is difference bettween setId(String id) and id(String id)
is the second method so helpfull ?
You should take a look at the blog post titled: The builder pattern in practice. It provides a very nice explanation of the builder pattern and describes its benefits as well.
Hi Petri,
I want to thank you for creating such an excellent post! This series has definitely given me a good introduction to Spring Data JPA.
I'm comparing your Builder pattern with how it's demonstrated in the book, 'Effective Java', by Joshua Bloch. One difference I notice is that you don't re-define the properties within the nested 'Builder' class. Is the way you are doing it a cleaner technique because you don't have to re-define the properties again (once in the 'Person' class and then once again the nested 'Builder' class)?
Also, I've heard that one advantage of the a Builder class is that it can be immutable, however, I notice you have an 'update' method, a 'preUpdate' method, and some other methods that effectively update the class after it's been instantiated. Wouldn't this break the contract of it being an immutable class? Or is there no way around this and you need these "updating" methods because of how Spring Data JPA works? Instead of these "updating" methods, could you create a new 'Person Object' with the new properties it needs and use that as the new updated object somehow?
Hi Belden,
it is good to hear that this tutorial has been useful to you. I will answer to your questions in the following:
"Is the way you are doing it a cleaner technique because you don’t have to re-define the properties again (once in the ‘Person’ class and then once again the nested ‘Builder’ class)?"
Yes. That was my original reason for doing this. However, this approach has a serious drawback: you cannot really create immutable objects because you cannot use the
final
keyword in the fields of the created class. That is why I have abandoned my approach and started using the approach described by Joshua Bloch. The reason why I haven't updated my old blog posts is that it would take too much work.Also, I’ve heard that one advantage of the a Builder class is that it can be immutable
Yes. That is one advantage of the builder patter. Another advantage is that you can create a domain-specific language for building new object.
however, I notice you have an ‘update’ method, a ‘preUpdate’ method, and some other methods that effectively update the class after it’s been instantiated. Wouldn’t this break the contract of it being an immutable class?
Yes.
Or is there no way around this and you need these “updating” methods because of how Spring Data JPA works? Instead of these “updating” methods, could you create a new ‘Person Object’ with the new properties it needs and use that as the new updated object somehow?
The problem is that if you use an ORM tool, it means that entities must be mutable (e.g. Hibernate requires that each entity has a default constructor). However, you can reduce mutability by using immutable value types (
@Embeddable
classes). I try to move as much information as I can to value types because this way I can minimize the effects of mutability.Hi,
First of all a big thank you - this is the tutorial I have been looking for, great job!
I do have one issue. I guess it is a configuration issue (or a stupid typo I did as it works for everyone else). I created my own application using yours as a template. I use tomcat 7, I start it from Eclipse (Juno).
Server starts without issues at http://localhost:8080/myapp/ and shows me the list of records I put in the database.
As soon as I click any of the links, my url becomes:
http://localhost:8080/person/edit/2
... which does not exist (is your app designed to run as ROOT.war in Tomcat by any chance?)
As soon as I change the URL to http://localhost:8080/myapp/person/edit/2, I get to the edit view.
However, all the links on the edit page change either to
http://localhost:8080/ (back)
or
http://localhost:8080/person/edit (save)
so needles to say, both save and back do not work.
To sum it up: How do I change the configuration when using Java configuration in Spring so that I can deploy your application just like I did?
Thank you,
Jan
Hi Jan,
Good to hear that you liked this tutorial.
I have to confess that I was a bit lazy when I created the user interface of the example application. Like you suspected, the links are working correctly only if the context path of the application is '/'.
Luckily, this problem should be pretty easy to fix: You can use the url tag to construct an url that contains the context path. Check out this StackOverflow question for more details about this: how to use <spring:url /> with an <a> tag?
Hi Petri,
Thank you for your quick answer. I will try the solution first thing in the morning tomorrow. I got a bit rusty on the subject of creating a new project from the scratch ... and in the meantime the world has changed ;-).
Oh I would not dare to call you lazy after all the tutorial parts you published and after answering all the questions on your page!
If you ever come to Holland, I owe you a beer ;)
Regards,
Jan
Jan,
I have to come to visit Holland then!
About the fix, let me know if it did the trick. I know at least one other way to fix this but that fix is kind of ugly. That is why I did not suggest it as the first option.
Excellent article. It got me interested in your book. I can't import part five, six and eight of the source code as there's an error when setting up maven plugin connectors in Eclipse Juno ( SpringSource Tool Suite 3.1): "No marketplace entries found to handle /pom.xml in Eclipse."
I installed m2e-apt from Jboss. This is not enough? Anyone know?
MiB,
Thank you for you comment. I have not been using Eclipse for a while now but I found some links that might help you out:
Let me know if this solved your problem.
I had to replace the bean definition in applicationContext.xml:
and update Spring Data Jpa to 1.2 in the pom in order to avoid the error "sch.props.correct.2: A schema cannot contain two global components of the same name" in Springsource Tool Suite.
"Spring Data- JPA Schema validation error in STS" https://jira.springsource.org/browse/DATAJPA-160
MiB,
Good to hear that you were able to solve your problem. Also, if you want to get rid of the XML configuration file which is used to configure Spring Data JPA, you can simply add the
@EnableJpaRepositories
annotation (supported in Spring Data JPA 1.2) to your application context configuration class and delete the XML configuration file.Well, I also had to set m2e to ignore execution of the maven-apt-plugin.
I got this classic before that:
"Plugin execution not covered by lifecycle configuration: com.mysema.maven:maven-apt-plugin:1.0.2:process (execution: default, phase: generate-sources)"
Then run that generate-sources phase, set source folder, then clean build. For some reason in some cases — Part five I think — I had to run the tests as junit tests and not maven tests in order for them to run green.
Unfortunately the Maven APT plugin does not work very well with Eclipse. However, at least one of my readers has managed to configure it. See the comment written by Eric B for more details.
Thanks!
You are welcome.
Thank you very much for your tutorials!
I'm currently digging into Spring Data, Hibernate and JPA. The goal is to build a simple application that involves Wicket for web logic and Spring Data for easy persistence support. I'm struggling a bit with configure Spring Data outside of a Spring MVC context: What configuration files are relevant and where to put them? For example you named you applicationContext-persistence.xml instead of just applicationContext.xml. Does this have impact on how the file is handled? Do you have examples for how to use Spring Data outside of a Spring MVC application? Do I have to understand the whole Spring framework at the end or is it possible to use just a potion of the framework without getting to much invovled with the others?
Furthermore, I learn a lot about application infrastructure and patterns just by reading your comments. Thank you for sharing your expertise!
The example application configures the Spring application context by using a combination of Java and XML configuration. This approach is described in the first part of my Spring Data JPA tutorial.
I have also written a comment to that blog entry which describes how you can configure Spring Data JPA, Hibernate and Spring transaction management by using XML configuration.
I guess the question is: Do you want to configure your application context by using Java configuration or XML configuration files?
About Wicket and Spring Data:
Unfortunately, all my Spring Data examples use Spring MVC. However, I have used Spring with Wicket (1.4.x) in the past and I think that I can give you some pointers which should help you to get started:
I hope that this answered to your question. If you have any other questions, feel free to ask them!
Hi Petri,
Your example is very good for beginners to start with as an console based application. Can u give me simple example of Spring Data JPA with MVC integration using MySql and Maven.
If u can help me out in this , it would be great help for me
Thankxxxx
Hi Ankit,
You can enable the MySQL support of the example application by following these steps:
I hope that this answered to your question.
Hi Petri, great tutorial to begin the journey of Spring Data JPA :D
i see your code in the Github and there's no Unit Test for Repository class
my assumption is because it is part of the framework, so we just can trust the author lol
if we want to test how can we do it, i didn't see you write the implementation of the Repository interface
thanks,
wupss i meant Integration Test
I answered your original comment before I saw this comment. :)
Anyway, check out my answer to your original comment. It has an link to an example application which has integration tests for its repository interface.
Hi Agung,
Thank you for your comment.
The reason why there is no unit test for the repository interface is that when you are using Spring Data JPA, you don't have to implement your repository interfaces. Spring Data JPA is capable of providing an implementation for them as long as your repository interfaces extends one of the "special" interfaces of Spring Data. The base interface of these "special" interfaces is the
Repository
interface.You can however write integration tests to your repository interfaces. I have been planning to write a blog post about for some time now. Perhaps I should do it in the near future?
In the meanwhile, you can check out the example application of my blog post which describes how you can use Querydsl in a multi-module Maven project. This application has integration tests for the repository interface.
Update: I took look at the project and it seems that I wrote integration tests for the service implementation. You can, however, use the same technique when you are writing integration tests for your repositories. It seems that I should probably write a blog post about this soon.
I hope that this answered to your question.
HI ,
great work there , i'm new to webapps i was wondering how can i deploy this application on jboss 7.1.0 as
You can do it by following these steps:
I hope that this answered to your question.
Update: JBoss might not support Spring applications which use Java configuration.
Hello Petri, you are really a great writter. Like every one else, I have seen a lot of tutorial websites, however, you are the only person who literally replies to every single comment. I greatly admire your spirit. Wish you have even greater success on your future career.
Hi Bowen,
Thank you for your kind words. I really appreciate them.
Yes, I like to reply to every comment I get (especially if there is a question) because I feel that it makes no point to give a reader the possibility to comment your blog posts unless you are willing to communicate with them.
I think that the comments I get are valuable in two ways:
I wish you all the best in your future career as well!
Hi Petri, I've followed this tutorial (thanks a lot) and everything worked perfectly until I added a one-to-many relationship. I'm encountering an EntityNotFoundException and just can't figure it out. I've tried so many different methods, but still stuck. Posted a question on stackoverflow if you have time to check it out. Thanks. http://stackoverflow.com/questions/18237689/hibernate-4-2-onetomany-entitynotfoundexception/
It seems that you found the answer to your question while I was sleeping (based on the StackOverflow question). Am I correct?
Petri, it appeared to be working but ran into an issue after I added subsequent records. The primary key on the keywords table is text in my solution, but I wanted it to be the docid. Didn't realize that until I had duplicate keywords in other documents. Any ideas?
So your problem is that you cannot add new documents because the same keyword appears in more than one document?
You have to add a new field to the
Keyword
class and use that field as the id of the entity. You cannot use the docid column as the private key because this means that you could add only one keyword per document (private key has to be unique).That's right, each `Document` could have similar keywords. Last night I experimented with a `kywd_id` on the `Keyword` class, but then the keywords were duplicated on updates. `kywd_id` was auto-incrementing.
Say `Document` has keywords: one, two, three. And the `docid` is `abcd`.
Then the table rows looked like,
1, one, abcd
2, two, abcd
3, three, abcd
If I added a new keyword to `abcd`, then the table looked like,
1, one, abcd
2, two, abcd
3, three, abcd
4, one, abcd
5, two, abcd
6, three, abcd
7, four, abcd
I'm expecting,
1, one, abcd
2, two, abcd
3, three, abcd
4, four, abcd
If I added a new document `efgh` and it has the same keywords, I'd expect the table to have,
1, one, abcd
2, two, abcd
3, three, abcd
4, four, abcd
5, one, efgh
6, two, efgh
7, three, efgh
8, four, efgh
I can't figure out the primary keys or constraints for this scenario. I was thinking the keywords table could have a unique constraint on `docid` and `text` and both be primary keys.
Something I just realized might not be handled automatically is if we remove keywords from a document.
I assume that you are not loading the document (and its keywords) from the database when you are updating it?
Because the
Keyword
objects of your document are transient, new rows are added to the database.You don't get duplicate documents because the your
Document
has a docid (I assume that you read it from the XML file). The repository implementation notices this and calls themerge()
method of theEntityManager
class instead of thepersist()
method.I recommend that you you follow this approach (inside a read-write transaction):
Document
object from the database.That sounds like a nice approach. One question before I get into that. On `Document` I have, @JoinColumn(name = "docid_fk"). Is there any way to make `docid_fk` and `text` both primary keys on `kywd_t` since `docid_fk` isn't directly defined on `Keyword`?
It is possible to use composite private keys with JPA 2. However, I would not use them unless it is absolutely necessary (they tend to make your code a bit complex). If you want to use a composite private key anyway, you should check out the following tutorials / websites:
I hope that this answered to your question.
I'd rather not make it unnecessarily complex if possible. Seems many people agree with you too. Right now I'm tinkering with a @JoinTable but it has some issues as well.
In `Document`,
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "mtdt_kywd_t",
joinColumns = {
@JoinColumn(name="docid", referencedColumnName="docid", unique = true)
},
inverseJoinColumns = {
@JoinColumn(name="text", referencedColumnName="text")
}
)
@XmlPath("head/meta/kb:keywords/kb:keyword")
private Set keywords;
And in `Keyword`,
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(
name = "mtdt_kywd_t",
joinColumns = {
@JoinColumn(name="text", referencedColumnName="text", unique = true)
},inverseJoinColumns = {
@JoinColumn(name="docid", referencedColumnName="docid")
}
)
private Document document;
I don't want to take anymore of your time, you've been most helpful. If/When I discover a solution I'll report back. Thanks Petri.
Petri, been working on this for quite a while with a coworker and he figured it out yesterday afternoon. Here's what we came up with.
On `Document` we have,
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@OrderColumn
@JoinColumn(name = "docid")
@XmlPath("head/meta/kb:keywords/kb:keyword")
private Set keywords;
On `Keyword` we have an auto-generated id now,
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@XmlTransient
private Long id;
and,
@ManyToOne
@JoinColumn(name = "docid", insertable = false, updatable = false)
@XmlTransient
private Document document;
Thanks again for the help.
You are welcome! Also, it is great to hear that you could solve your problem.
Hello Petri,
First of all I want to thank you for your excellent work here.. you are simply great. you explained things very simply.... I worked in Spring , Hibernate projects in 2006 / 2007 after that I had to work in a middleware Microsoft Biztalk sever. But recently I started looking my old old skills and happened to find your articles.
I have some Questions to you. :-)
Do we have any tools that support following sequence of development?
1. Develop Database tables and relationships first using any tool.
2. Then based on those tables auto generate Java entity classes and Service for CRUD operations
3. Then Auto Generate the Skeleton for the controller classes.
4. Then Auto generate Model/View for those CRUD operations.
5. Then Build and Deploy.
My aim is to generate an initial working web application skeleton with minimal or zero lines of java code manually. Later we can change and customize the auto generated code.
Is this Possible Using Eclipse latest version? If so would it be possible to post the minimal sequence of steps that need to perform to make a working skeleton of REST full java web app. I
Any help would be greatly appreciated.
Regards
Vikas
You are welcome! I am happy to hear that I could help you get started again.
You might want to check out the following projects:
These are a bit different projects but they have the same goal: help you to get started as soon as possible.
Based on your questions, Spring Roo might be what you are looking for. I haven't personally tried it out, but the reference manual of Spring Roo looks quite promising.
Also, I think that Hibernate Tools can create domain model classes from an existing database.
Once again Thank you Petri .. I will explore these and see how fast we can develop
Vikas
Petri, I followed your steps in this post to set up my repository. But when I try to test it against real database, updated data wasn't actually reflected in database unless I call save. Any idea what could be the problem?
Hi Katie,
One possible reason is that your code is not executed inside a read-write transaction. Have you annotated your service method with the
@Transactional
annotation?The changes made to persistent objects should be updated back to the database as long as changes are made inside a read-write transaction. That is why you don't have to call the
save()
method when you are updating information inside a read-write transaction.Also, you might find want to read my blog post which talks about the integration testing of Spring Data JPA repositories.
If this didn't solve your problem, please let me know. :)
Petri,
I use your tutorial and it's very helpful but in my application I have to use postgresql and I don't know how to configure it. When I uncomment in your application parts about postgres (in pom and application.properties) it doesn't work. I start app, got info:
'DEBUG - LogicalConnectionImpl - Obtaining JDBC connection'
and nothing happens. Could you tell me what should I change to fix it?
Thanks,
Alicja
If you want to use PostgreSQL, you have to make following changes to the example application:
If you want to use PostgreSQL, the database and Hibernate configuration found from the src/main/resources/application.properties file looks as follows:
I hope that this answered to your question.
Very good java tutorials for beginners
Thank you for your kind words. I really appreciate them.
Great blog and tutorials! How do you handle entities that have a lot of properties (5 or more)? The update method's parameter list gets too large in these cases and it seems having setters would be a bit cleaner.
Thank your for your kind words. I really appreciate them.
You are absolutely right. If entities have a lot of properties, having a single update method is not practical. Typically I separate the properties into value objects (e.g.
Address
and so on) and create a separate update method per value object.On other hand, if the properties are entities, I try to follow a pattern called aggregate. At the moment it seems to make perfect sense to me but I might change my mind after a few years or so (this happens).
I hope that you find this answer useful.
@Petri ... Awesome Job ... As Expected... ;-)
FYI ... Running a modified version of this on Glassfish required me to implement Serializable on the DTO or I was getting Invalid Attribute errors .... FWIW ...
Great Job Chief!!!
Thank you for you kind words. I really appreciate them.
Also, thanks for leaving a note regarding the Glassfish & Serializable problem. Maybe It will be useful to someone.
Hi Petri
I have three entities like below
1. CompanyInfo
2. UserInfo
3. Roles
and created the repositories for the above three entities now I want to query using hibernate relations like
In CompanyInfoRepository
1. I have userId and I want get the user companyInfo. we can get using two ways, one is from UserInfoRepository table which is straight forward and the other is from companyInfo table. Now the problem is I tried to query from CompanyInfoRepository but didn't succeeded.
I kept :userID for the argument and I used "IN" because in companyInfo UserInfos is a list
In UserInfoRepository
similary I have roleId and I want query it from UserInfoRepository(relation between UserInfo and Roles is ManyToMany) and here also I am getting error , I have userId and want to query from Roles table
Hi Varun,
Have you tried using inner join instead of the IN expression? Here is an example JPQL query which uses inner join (you can use the same approach for getting the users which have a specific role):
Hi Petri,
First of all, thanks a lot for such a nice tutorial. I am learning JPA and your tutorials are really helpful. As a matter of study, I have tried creating a maven project using the example you have given above through eclipse and then added JPA and JSF facets to the project. The necessary jar files are in place. My problem is whenever I call inbuilt methods findOne(), findAll(), save() etc of the JPARepository, It throws Null Pointer Exception. I am stuck up at this point.
I have uploaded my project files on dropbox public folder and sharing the same here. Kindly help me on this.
Entity:- Person.java
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/Person.java
Repository:- PersonRepository.java (This extends JPARepository)
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/PersonRepository.java
Service:- PersonService.java
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/PersonService.java
Service Implementation:- RepositoryPersonService.java
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/RepositoryPersonService.java
Transfer Object:- PersonDTO.java
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/PersonDTO.java
UI:- PersonController.java
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/PersonController.java
Webpage:- index.xhtml
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/index.xhtml
Also attached pom.xml, persistence.xml, applicationContext.xml, faces-config.xml and web.xml for reference.
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/pom.xml
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/applicationContext.xml
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/faces-config.xml
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/web.xml
https://dl.dropboxusercontent.com/u/16250517/JPA%20Project/persistence.xml
Thanks in Advance,
Nikhil
Hi Nikhil,
Thank you for your kind words. I really appreciate them.
I have never used JSF so I have no idea how you can use Spring beans in an application which uses JSF. However, I did find this blog post which describes how you can use Spring in web applications that use JSF 2. Maybe it will help you to solve your problem.
Hi Petri,
Thanks for the link. I will go through the same. Meanwhile, I tried to find the mistake from my side and it looks like the repository is not getting initialized. So, it looks like the methods are not throwing NullPointer but the repository is. Is there any way to check whether repository is initialized or not? Please let me know.
Thanks in Advance,
Nikhil
Hi Nikhil,
Unfortunately I don't know if it is possible to detect this in a JSF application. In a Spring application the Spring container throws an exception if it cannot create a bean.
Hi Petri,
I am totally new to spring mvc. Currently i am working with struts 2, spring and hibernate with Model driven. I see too many classes here to do CRUD operations. The way i use i have one struts layer class and one service layer class and the domain object class(Entity) and the DAO class. I feel like some kind of messy here. Please don't misunderstand me. I just need to learn the technology with a good design pattern. :)
I'm trying to run your application with Postgres however it fails with the following stacktrace:
Caused by:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactoryBean' defined in class net.petrikainulaine
n.spring.datajpa.config.ApplicationContext: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreExc
eption: Factory method [public org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean net.petrikainulainen.spring.datajpa.config.Applicati
onContext.entityManagerFactoryBean() throws java.lang.ClassNotFoundException] threw exception; nested exception is java.lang.IllegalStateException: re
quired key [hibernate.hbm2ddl.auto] not found
Did you make any changes to the example application? The reason why I am asking this is that the error message suggests that the property
hibernate.hbm2ddl.auto
was not found.This property is found from the application.properties file and the
PersistenceContext
class sets the Hibernate properties to theLocalContainerEntityManagerFactoryBean
.If you didn't change anything, let me know so that I can investigate this issue.
Also, thank you for asking this question. It helped me to notice that this wasn't mentioned in the first part of my Spring Data JPA tutorial. I think that I will have to update that blog post next week.
Hi Petri:
Your blog is amazing .. honestly. Your examples are very pertinent and useful - thanks!
I have a question about this example. I'm also going to pull down your github example on this and test out your code with this scenario.
You use 'version' and the annotation, but you don't set the version in your DTO and you don't set it in your Builder classes. Why? Doesn't this mean that version (i.e. optimistic locking) is therefore being ignored?
In my application, if I use findOne and do not detach I am able to save Entities that 'violate' the version property (i.e. second version overwrites first). If I use findOne and then detach and update, I get the update.... OR if I create a brand new Entity and set the ID in (if it existed) and then save I also get the Optimistic Locking Exception.
So I'm curious why you don't have a version property in your DTO and how your example would work with optimistic locking otherwise?
I've also read your book and in your chapter on this you do not manage Version there either.
Thanks!!
Jim
Hi Jim,
Thank you for your kind words. I really appreciate them!
About your question: The optimistic locking isn't handled properly in this blog post (or in my book) because handling it isn't really a Spring Data JPA specific issue. Another reason why I decided to not handle it was that it keeps the code a bit cleaner. Now that I think about this, I should have probably mentioned this in the book. :(
Like you said, the ideal way to handle this is to put the version field to the DTO and check its value in the service method before updating the information of the entity. If you use this approach, you can decide how you should handle this. You can either overwrite the information or ask user to decide what to do.
Also, like you suspected, the optimistic locking is ignored if other transactions haven't changed the data when the current transaction is committed (this is the typical case). If other transactions have modified the data when the current transaction is committed, an
OptimisticLockException
is thrown and the current transaction is rolled back (this is a rare situation but it can happen).Thanks for the confirmation Petri.
Makes perfect sense to me, it's funny that most examples use the @Version but I haven't really seen 1 example that discusses the implications of this if you are going to use a DTO based approach, maybe b/c most examples assume the entity will be surfaced at all tiers.
Which brings me to another question I wonder if you know the answer to. The key to the above approach working is either detaching the object PRIOR to copying any edits from the DTO class OR creating a new entity (detached) and then setting the primary key id into it .. which essentially is the same result (i.e. the JPA figures out what the row is and updates it accordingly).
What I don't understand is WHY the entity needs to be detached for the updates to work? I would have thought the end result was the same, but I'm obviously missing something.
Any insight appreciated. Thanks again!
Jim
Hi Petri,
Regarding optimistic locking, what will happen if I just put the Version annotation in my entity and do not check for its value in the service layer? Should it throw an OptimisticLockException automatically?
Also I was wondering about the locking mechanism implemented by JPA providers and the locking mechanism provided by the databases (i.e., in MySQL the "lock tables ..." command). Does the optimistic locking need any table locking permission for the underlying database?
Hi Sayem,
Yes. The Javadoc of the
OptimisticLockException
class states that:"Thrown by the persistence provider when an optimistic locking conflict occurs. This exception may be thrown as part of an API call, a flush or at commit time. The current transaction, if one is active, will be marked for rollback."
Vlad Mihalcea has written three great blog posts that answer to your question better than I ever could. These blog posts are:
Hi Petri,
An awesome work, thanks for it and am using spring-data-dynamodb and I used annotation based confuguration and for validation is it possible to configure through annotation at present. Am struggling in that phase because am entirely new to spring environment. If its possible please guide me with a good link/sample to go through in it.
Overall like the article but I think tests should be the first step not the last step. Write a failing test that does what you expect users to do then build the bare minimum you need to pass it, rinse and repeat. It will help stop things such as scope creep and adding in code that is not needed.
I agree that TDD is very useful design tool but I am not sure if the test first approach works very well in tutorials (unless you are writing a TDD tutorial). However, I think that I might use this approach when I write my testing book.
Thank you for your tutorial and codes. I find it very useful as I feel my way around JPA for my project.
I have one question.
My understanding is that,
methods like create, delete in PersonService (implemented by RepositoryPersonService) use a PersonRepository instance to save to the database using the JpaRepository commands (save and delete)
However, the update method only calls person.update. The value of the instance will be updated, but am i right i saying that the changes wont be written to the database?
The reason why you don't have to call the
save()
method when you are updating the information of aPerson
object is that the object is inmanaged / persisted
state, and the changes made to this object are automatically saved to the database when the transaction is committed.If you want to get more information about this, you should read the Chapter 3. Persistence Contexts of the Hibernate reference manual.
Thank you for your prompt reply. You explanation helped.
Hi Petri,
The your tutorial seem to be very helpful for me as I am new to learn Spring Data JPA.
Please with me so that I can do well.
All the Best and thans for precious guidance.
Nikhil Agrawal
I got lost, how to config DB connection? Which file do I need? Which driver?
The first part of this tutorial describes how you can configure Spring Data JPA. Remember that you can get rid off the XML configuration by using the
@EnableJpaRepositories
annotation (this tutorial was published before it was possible to use that annotation).I have fair knowledge on Spring -DI and Hibernate with JPA. I need to know, who create entity bean/object. Is it repository or service?
I just tried calling ${person.name} in my JSP page. It worked. therefore, I have this question.
There are two answers to this question:
save()
method of thePersonRepository
interface is invoked.The following articles will shed more light to the entity life cycle:
Hi Petri,
I really appreciate your blog and those are great tutorials.
I'm facing the following in my current project:
I have 2 entities Process and SubProcess. Those are split for a reason and cannot be merged. Although I want to display them in one single paged grid on the ui.
I was thinking to create a repository that would extend both repositories I already have for the process and subProcess. (So infine create a superRepo). My question is the following: would the find All(Pageable) of that superRepo get the findAll of both extended repositories?
If not what would be the direction I should go?
thanks in advance
To be honest, I don't know the answer to your question.
Could you tell a bit more about the relationship of the
Process
andSubProcess
classes? If they are totally "separate" entities, it is hard to see how the super repository could work because it should support two entities and afaik this is not possible (without using inheritance).Hello Petri,
Thanks for your prompt answer. Yes they are completely separate entites. I guess I'll solve this with displaying 2 grids instead of one. Out of curiosity I'd be interested on how you would imagine solving it with inheritance, because at the moment I don't see how.
Thanks in advance
I cannot see it either. I just wondered if the
SubProcess
extends theProcess
class.The reason I mentioned inheritance was that you can actually create a repository for a super class and obtain all sub class objects (regardless of their type) by using its
findAll()
method.If I would have to solve this problem, I would probably follow these steps:
List<DTO>
orPage<DTO>
object (if you need pagination meta data, returnPage
object). I would probably implement this method by using JDBC because Spring Data JPA doesn't have a very good support for querying DTOs (it is possible but the support is a bit awkward).Do you think that this could work?
Hello,
Thanks for your answer, yes this seems to work, and yes the spring data queriying of a DTO is ackward. Now I just need to convince my TA that this is the solution :)
Hi Francois,
Does TA mean technical architect?
Anyway, you can probably convince this person by arguing that this is the most efficient (in terms of performance) and the cleanest way to do this.
My second point is of course a matter of opinion, but if you need to show everything in the same table, it is hard to figure out another solution which would be cleaner than this solution.
I got
Description Resource Path Location Type
The import org.apache.commons.lang cannot be resolved Person.java /data-jpa-tutorial-part-one/src/main/java line 3 Java Problem.
Can't download it by maven. Temporary I download it from the site not I am looking more clean way.
What's wrong here?
You need to add the commons-lang to your pom.xml file. The example application of this blog post uses version 2.6 (see the pom.xml file), but the newest available version is 3.3.2.
You mentioned that you cannot download it by using Maven. What do you mean?
The same problem
Description Resource Path Location Type
The import org.hibernate.validator.constraints.NotEmpty cannot be resolved PersonDTO.java /data-jpa-tutorial-part-one/src/main/java line 2 Java Problem
You need to add hibernate-validator to your pom.xml file. The example application uses version 4.2.0.Final. See its pom.xml file for more details about this.
Hi Perti,
Thanks it works, there is one more question how can I use it with spring version 4.
Just update pom.xml? How?
Well,
you should probably update all dependency versions since some of them are very old (Spring and Spring Data JPA to mention a few).
If you are working on a greenfield project, I recommend that you take a look at the Spring IO platform. Its goal is to make dependency management easier for developers by providing a POM file which contains the dependency versions which are known to work.
If you want get more information about the Spring IO Platform, you should read its reference manual.
It works thanks, In additional I like to use spring 4.xx with jdk 7 not 8.0 which changes requires?
The configuration of the Maven compiler plugin sets the "version" of the source code and the "version" of the byte code. You should change this version from '1.6' to '1.7.' (search for the
source
andtarget
elements).Thanks again, In additional I miss how JpaRepository interface knows on which DB connec
useful, I mean "who" realize something like repository.setConnection(mycon) or repository.setEntitymanager() ,and how can I do it dynamically (similar to JDBC style)?
I mean entityManager.set(myJPARepository) where myRepository is my own class impements
JPARepository or custom interface which extends a standard Spring interface.
The first part of this tutorial describes how you can configure Spring Data JPA. It is a bit outdated (it configures Spring Data JPA by using XML configuration instead of using the
@EnableJpaRepositories
annotation), but it should still provide some answers to your questions.The beans which are relevant to your question are:
DataSource
bean configures the used database connection.LocalContainerEntityManagerFactoryBean
is responsible of creating newEntityManager
objects. The method which configures this bean is responsible of configuring the used JPA provider (in this case Hibernate).Spring Data JPA finds your repositories by scanning the configured base package (and its child packages). You can set this base package by using either the
base-package
attribute of therepositories
element or thebasePackages
attribute of the@EnableJpaRepositories
annotation.But how application knows that is entityManagerFactoryBean which time is really occurs?
On server start-up?
In other words I have to implement on method with any name which return LocalContainerEntityManagerFactoryBean? Don't I? And what about public JpaTransactionManager transactionManager() throws ClassNotFoundException {} which part of application run it . And last, who responsible to open/close JDBC connection?
Well, actually the application doesn't know about it. The Spring container injects a proxy implementation of the repository interface to all beans which use it.
This happens when the Spring IoC container is started. If your application is a web application, this happens when on server start-up. If you are not familiar with the Spring IoC container, you should read the Chapter 4 of the Spring Reference Manual.
If you want to use JPA, you have to create this bean. Read the section 14.5 of the Spring Reference Manual for more details about this.
That method configures that transaction manager bean. If you use JPA, you should use the
JpaTransactionManager
as a transaction manager bean.You can get more information about transaction management by reading the chapter 11 of the Spring Reference Manual.
You can request a new connection from the
DataSource
bean, but you don't have to do it yourself. If you use Hibernate as a JPA provider, it will take care of this.I have a Entity class Trade.java which uses a composite key TradeKey.java. I am using @EmbeddedId annotation.
TradeKey has two attributes tradeId and companyNumber.
I have written a ITradeRepository which extends CrudRepository.
I want to select all trades based on companyNumber. How to write find method in ITradeRepository?
You could try something like this:
Note that the
key
is the name of the composite key property that is found from theTrade
class.Hi,
Great tutorial! Can you help with this bcoz Im using Spring Data JPA, I thought you could help on this : http://stackoverflow.com/questions/25771892/column-insertable-updateble-dont-go-well-with-spring-jpa
Hi,
When you are creating a new
Offer
object, do you get theChannel
object from the database or simply just create a newChannel
object?If you aren't fetching the
Channel
object from the database, Hibernate probably performs insert to thechannel
table when you save a new offer because theChannel
object is not in themanaged
state.Unfortunately the code that you added to your StackOverflow question didn't reveal how the
Channel
object is created. If you can shed some light to this issue, I can probably give you a better answer.Hi,
very intresting and clear tutorial. I have a couple of question left before to start evolving an old project to Spring.
1. You mentioned you would use VOs instead of the 'monolitich' DTO in case of more complex entities, I suppose this is valid also in case of collection fields (@OneToMany relations). Will you in that case include in VO/DTO collection of Domain Entity (as in the Domain entity itself) or collections of reduced DTO/VTO tailored to the needs of the client? Where Will you put the logic to assemble/dissassemble Domain Objects in DTO/VO? Specific servers or into the Domain Object itself?. How will you handle transactions when different entities are involved? bit confused...
2. In your example, Person is the Domain Entity AND the Persistence Object, DTO/VO are involved only from domain to UI and viceversa. Is this the common/best practice with spring? You don't want to separate the data layer, just in case you need to move from a RDMS to a NoSQL DB or...
3. For some Domain Object I actualy retrive some data from the database AND some other from somewere else (today is the filesystem, but I'm late to provide access to a legacy filesharing application, and It's easy precognize the needs for clouds based or web services). How will you handle this without create new artificial domain entities? Now I've a method directly in the Entity class, but as you could understand, this is on e of the majr concerne that move me to reengineer the application.
Quite articulate question, sorry about that.
Marco
Thank you for you kind words. I really appreciate them. Also, thank you for writing such an awesome question!
I only fetch and return the information that is needed by the client (in case of REST API) or the view. Even though I call these objects DTOs, I guess you call them view objects as well.
I might reuse the same DTO if two two views need exactly the same information or two REST API endpoints return exactly the same information.
If I need to return an object that contains a collection of objects, I will create a separate DTO that contains the information of the objects found from that collection. In other words, I will create a DTO that has a collection of DTOs.
I never return domain model objects (entities or value objects). However, the example application of this tutorial uses a different approach because it was written a few years ago. Nowadays I use the approach which I described here.
If I am inside a read-write transaction, I put the logic to a special mapper classes and use these classes in my service layer. I might also use a library such as jTransfo, Dozer, and ModelMapper.
If I am inside a read-only transaction, I query DTOs directly from the database. This way I can get only the information I need and avoid the overhead of Hibernate (or any other JPA provider). In this case, I put the logic that converts query results into DTOs to my repository class. Typically I use the
JdbcTemplate
and theBeanPropertyRowMapper
classes for this purpose.Spring Framework has a comprehensive support for transactions. I use the annotation driven transaction management, and add the
@Transactional
annotation to my service methods.I want to avoid complexity when it is not absolutely necessary. In other words, if the requirements of the application don't state that the application must support both relational databases and NoSQL databases, I won't take this possibility into account when I design and implement the application.
The truth is that no one cannot know what happens in the future. This means that there are many variables that can change, and if we want to support all of them, we need to over engineer everything. Over engineering has two big problems:
This is of course a tradeoff, but I have noticed that doing the simplest thing that works is often the best choice.
I would create a new domain object that has references to the entity (or entities) in question and to the information that you fetch from the file sharing application. This gives you the possiblity to keep that information together, and you can also add relevant business logic to that domain object. On the other hand, if you only need to provide that information to the user's of your application and you don't need any business logic, adding a transient field to the entity is probably fine as well.
Hi, great answers and I'll need some time to elaborate them.
I understand your point about avoiding complexity and it was what I did at the beginning, using Swing application famework with netbeams. It was usefull and now at least I know very well the 'domain' of the application, but is time to evolve, and my concern are:
a. provide a better integration and distribution respect as today.
b. enable web and mobile clients for all or at least part of the application domain.
c. move from swing to other (and more modern and rich) 'rich' GUI container (if one is still needed).
d. be ready to move from mySQL + MS/SAMBA directory sharing to other DBMS and fileservers/clouds application.
Your advise will be greatly appreciated on every point, but strictly to the point of this blog d. only is involved. Your answer state You don't want take care of what is not a requirement at the moment, but what if it is? Would you still handle it with spring?
I've read the spring tutorial and I'm aware is possible to have different datasouces at the same time for differents entitities, but in that tutorial persistence.model.entity and domain.model.entity are two separated class and this pattern will for sure lend to many heavy extracost (i.e you are going to always deal with detached entities and updates must be atomics, a real nightmare with collection fields), I'm not aware of tools who could help you using this pattern, but maybe you are.
What is not clear to me and urged me to my first question to you is: is this a required pattern with Spring using different datasources?
If not, is it the best/common practice?
Why not use the same Entity Class instead (as you did) eventually implementing different interfaces for different needs (i.e one interface is 'anhemic' and rapresent the entity in the data layer, onother is rich and rapresent the entity in the domain layer) in order to ensure 'logical' separation?
Of course when heavy security (?) or performance constraints apply, then you have no choice.
Probably I'm wrong, but I'm interested in your opinion.
Regards, Marco.
Don't know why I posted as anonimus... sorry about that.
Thank you for writing another great question.
It seems that you might want to take a look at the following Spring projects:
Well, Spring does provide a good support for relational databases and NoSQL databases. The first thing that you should do is to find the answer to the following questions:
If you want to store all information either to a relational database or to a NoSQL database, there is no framework that can save you from the additional complexity. This means that you have to create a domain model and encapsulate the database specific details into your repositories. Spring can help you to implement these repositories because the Spring Data project provides a first class support for both relational and NoSQL databases.
If you want to store information to a relational database and some information to a NoSQL database, Spring can make your job a lot easier because it you can eliminate the boilerplate code by using Spring Data.
Are you talking about a specific tutorial? It would be easier to answer to this question if you would identify the tutorial you are talking about.
Well, if you want to use Spring Data JPA and some other Spring Data project, you have to create a domain model that is supported by both projects. This can tie your hands because
That is why it is a better idea to encapsulate the persistence specific details into your repositories and use a common domain model that isn't database specific.
This is the simplest thing than could possibly work. Using the same entities might seem like a simple idea, but you might run into problems when you need to support relationships between different entities and the other stuff supported by JPA. If you want to use JDBC or a "native" NoSQL database client library, you can probably dodge this bullet, but this means that you have to add a lot of boilerplate code to your repositories.
See my previous answers.
Again, if you think that I missed something or you have some additional questions, feel free to ask them!
Hi, thanks again for your precious help.
This is the tutorial: http://spring.io/guides/tutorials/data/
I understand your answer and I think I'm in an intermediate situation:
1.The 'core' is based on one RDB an I could not see the need of more (filesystem apart, as we already discussed. I'm cosidering to move the filesystem integration to the service layer (as you suggested), that way the 'core' (and any module) will interact with only one persistence subsystem).
2. Other part of the system (say modules) are served by web services and they are loosely coupled by design.
3. It could be possible in the near future to replace the filesystem and/or web service access with one or more additional database access, this could introduce the need of one more persistence subsystem, but not necessarly will lend to a tighter integration between modules.
In this situation, and accepting the risk that could arise if needs will change in future, I could not see any caveat in adopting your way, even if in the whole system more than one persistence subsystem is used, but probably I'm missing the point.
Any way, if I'll have to go the other way, as you wrote I'll have to write a lot of boilerplate and code just to map the domain objects to the entities. Then arise my question about how to handle updates, particolary in case of entities with collection fields (relations). I was not able to find any Spring tutorial on that matter, are you aware of any example or tutorial about this?
p.s.
I'll be very happy to owe you a beer, but considering you gave me seven more project/library to study... I think I'm not going to earn much money in the next couple of months :).
Marco.
Hi Marco,
you are welcome. And thank you for coming back and asking more questions (these questions help me to learn new things).
I took a quick look at it and it seems that this tutorial separates the "core domain" and the "persistence data model" because the application needs to support multiple different databases / data storages. I wouldn't use this approach unless it is absolutely necessary because most of the time this adds unnecessary complexity to the application.
Often the best solution is to find a some kind of compromise between flexibility and simplicity. The thing is that there is no perfect solution that would be suitable for every situation.
If you decide that you need to be able switch from a relational database to a NoSQL database (and vice versa) without making any changes to the source code, you have to write more code before you can "release" your application.
On the other hand, if you want to write less code before you can "release" your application, you cannot switch from a relational database to a NoSQL database (and vice versa) without making changes to the source code.
However, you can identify the modules that have to support multiple different databases, and add this support only to these modules. I know that this isn't a perfect solution but it can be a good compromise.
I wrote a very similar update function today at work. I can share it here but I have to "anonymize" it first. I think that I can do that tomorrow. I will send you an email after I have published it.
But you won't spend any money either because you will spend the next couple of months at home studying these libraries... ;)
By the way, you might want to read my latest blog post titled: Understanding Spring Web Application Architecture: The Classic Way.
Hi,
I'm looking forward for your update function, and I'll read for sure your blog, write the web app will be next step.
Marco
Hi Marco,
My use case is very simple but essentially I have two entities:
Task
andTag
. Their source code looks as follows:Now, I had to write an update method that updates every
Tag
object that is linked with aTask
object. Also, I could assume that existing tags are not removed and new tags are not added. The source code of my update method looks as follows:Any feedback?
HI, tanks for the example, for the matter of updating the collection field is similar to the one I was thinking of (but I need also add and remove methods, so I'm actualy thinking on a 'sub service' to handle the inner collection, with findRemoved, remove, findAdded, add, find and update methods). If interested in it, I could post an early version as soon as I'll have sketched, but I think you got the idea.
My real concern is: what if you have other fields and maybe other collections in Task? Will you then have differerent 'atomic' TaskUpdateService for each field? Same for Tags and any other entity.
Using non atomic updates (on detached entities) could land you in big troubles of 'logical' concurrency, depending on the number of users and lasting life of DTO's.I don't think @Transactional is going to help us in this matter.
From a genaral point of view, I don't like the idea to have this kind of stuff in the service layer (no business logic here, it's just a different implementation of the data access layer than using an ORM), maybe - if we really need it - we are better introducing a layer of abstraction between repositories and the service layer, so Service layer will not change if we change kind and number of datasources or repo implementation.
Marco.
I would just add the
addTag()
andremoveTag()
methods to the service class, and then delegate the request forward to theTask
object since it is the aggregate root (DDD Aggregate).It depends. My situation is pretty simple since I only need to update one field. If I would have to update a few fields, I would update them all at the same time. But if I would have to update a child collection of a
Task
object or more than just a few fields, things would get ugly.That is why I would update all fields inside the same transaction.
Actually I decided move this logic to the
Task
class. I added theupdateTag(Long id, String name)
method to theTask
class. This method finds the updatedTag
object and updates its name. Of course this works only because aTask
object won't have manyTag
objects and I have to update only one field.Hi, If I well understand your point, you will have the
addTag(Task task, Long tagId, String TagName);
removeTag(Task task, Tag tag);
in your TaskService class that delegate to same methods in Task:
addTag(Long tagId, String TagName);
removeTag(Tag tag);
assuming addTag has to first create the tag (if not exists) and removeTag delete the tag if not used anymore, where you will add this logics?
If in Task, it will not be a DTO anymore, but a Class that incapsulate data and logics, very similar to the concept of Entity in my opinion. More, Task must know how to persist/remove Tag. This breaks the original requirement to be able to switch the way Task or Tag are persisted.
For this reason I was thinking - if and only if we really need this capability - to introduce an intermediate level of abstraction - let's call it TaskIntermediate - between the DAO/DTO (TaskDAO, TagDAO, TaskDTO, TagDTO) and the domain object Task.
This way Task only have addTag(Tag tag) and RemoveTag(Tag tag) abstract methods, TaskIntermediate implements the methods via call to:
Tag tag = TagDTO.create(tagId, TagName) ;
TagDTO.persist(tag);
this.getTagList().add(tag);
and so on.
The benefit is that you could use ORM to handle DTOs and generics for CRUD operations in DAOs, concentrate the 'assembling' logics in the Intermediate Class (and an intermediate server implementing the aggregate CRUD operations onto the aggregate) and live with 'clean' and not anhemic at all domain objects and services, completely unrelated to where and how data are stored.
Thanks to you I've cleared up my mind and now I could better articulate my original question: If TaskIntermediate is just TaskDTO + the logics to handle related Tags (the add/remove methods) and the list of tags, could TaskIntermediate extend TaskDTO via inheritance or composition? if not why?
Same for Task vs. TaskImplementation, assuming Task adds some business related methods.
Looking forward for your opinion.
Marco.
Hi Marco,
Yes, and no. In this case the
TaskService
class would have the following methods:And the
Task
class would have the following methods:Actually I don't have the
removeTag()
method because there is no way to remove tags (they aren't really tags).I would add this logic inside the
Task
class because of two reasons:Yes. The
Task
class is an entity (at least in my application).It doesn't have to know this as long as it returns the added / removed
Tag
object. When you get the returnedTag
object, you can do what you want with it.I am not sure if I understand what you mean. I use DTOs to transform information between different layers (web -> service and service -> web), and I think that there shouldn't be any dependencies between DTOs and entities. If I need to assemble objects that requires special assembling logic, I create a domain service that creates those objects.
On the other hand, If would have to support multiple different databases, I would probably just separate the domain model and the data model by using the approach that was described on the Spring Data tutorial (it seems that the link is not working anymore so I couldn't link to it).
I am not sure if I understand this because my DTOs aren't passed to the data access layer. Also, since I don't have to support multiple different databases, I can just use JPA entities (this means that my data model and domain model are kind of the same thing).
I think that I don't understand what the role of the intermediate layer is. Is it a some kind of domain service that assembles objets that require complex assemling logic? Or is it a mapper layer that separates the service layer from the repository layer?
What is the difference between
Task
andTaskImplementation
?Hello Petri.
First of all, thanks for your great posts. I'm working in an app using the architecture defined here and Spring Data JPA. I'm enjoying programming this following your advices but there is a thing that I don't understand. According to your diagram, web layer should use only DTOs and in this post you return a list of Person insteand a PersonDTO. Is there a justification for this? If not, how could I rewrite that method to return DTOs instead?
Thanks again por your help. Great job! ;)
Hi David,
Thank you for your kind words. I really appreciate them.
I assume that you are talking about the diagram that is found from this blog post?
Anyway, the only reason why the service layer of the example application returns entities is that it was written almost three years ago, and three years ago I thought that returning entities is a good idea.
If you want to return DTOs from your service layer, you have to simply transform the domain objects into DTO objects and return the created DTO objects from your service methods.
If you want to see an example application that uses this approach, check out the example application of my Using jOOQ with Spring tutorial.
Its service methods transform domain objects into DTOs by using jTransfo and return the created DTO objects. However, you don't have to use an external library. You can simple write the mapper code yourself if it makes more sense to you.
I hope that this answered to your question.
Hi Perti,
Thank you so much.Its very helpful tutorial.
I have a requirement to connect with multiple (let's say two as of now) databases. So I am creating two repositories and using both of them in one service method.
I am trying to fetch record from one repo and persist in second repo but getting below error -
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2:
Hi,
That exception was thrown because Spring expected to find only one
PlatformTransactionManager
bean but it found twoPlatformTransactionManager
beans. Did you configure the used transaction manager when you annotated your configuration class with the@EnableJpaRepositories
annotation?Also, you might want to read this blog post. It describes how you can use multiple databases with Spring Data JPA.
Hi your site is excellent.
Thank you for your hard work.
Maybe you can write one some think like this - "how to use spring-data-jpa-tutorial-part-two-crud in Rest resources" I mean "how to inject/@Autowire @Repository variable in rest resource"
Thank you for your kind words. I really appreciate them.
Also, thank you for your suggestion. I think that I will add a few practical blog posts to my Spring web application architecture tutorial (read the first part of this tutorial). What do you think?
Thank you very much for the wonderful articles.
When you created the BaseRepository, you added @NoRepositoryBean, so that spring will not try to create implementation of it. And that makes sense.
But when i see the CrudRepository Interface from the org.springframework.data.repository package, it have the @NoRepositoryBean annotation on top of the class.
Why is this annotation needed for the crudRepository interface ? Don't we need spring to create implementation of the methods for the methods in the crudRepository interface ?
Hi Ben,
Thank you for your kind words. I really appreciate them.
Check out the Javadoc of the
@NoRepositoryBean
annotation. These interfaces are annotated with that annotation because we don't want that the Spring container creates beans for those base interfaces. Instead, we want that the Spring container creates beans for our "concrete" repository interfaces.purpose: update some columns of same table by given list of primary keys and return ordered int[] to indicate if a row update is successful or not
query (not native): update MyEntity e set e.col_1 = :v1, e.col_2 = :v2 where e.id in :ids
@Modifying(clearAutomatically = true) @Transactional public int updateCols(@Param("v1") String v1, @Param("v2") String v2, @Param("ids") List idList);
Spring JpaTransactionManager is used
Questions: 1) With Spring Data JPA only, how to do that? (customize repository not an option due to large existing codes), we want to achieve effects equivalent to JDBC batch update with Spring data JPA only. 2) Is it possible that spring data JAP will return an integer by the update method above that is less then the input list size? If that could happen, how do we know which one on my input list failed? In any order? 3) Noticed that after the above method successfully finished, database rows not being updated at all. How could we force it synchronized with database with spring data jpa? 4) If the entity update not flushed by spring data JPA, then even we update one by one instead of in a batch, still we will not see database changes? Thanks in advance
Not clear as article, Repository topic it's not clear enough.
Could you clarify that comment? I am not sure what you mean.
Hi Pettric,
need your help regarding the below
EntityClass{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID",columnDefinition=" INT UNSIGNED")
private Integer id;
@Column(name="TOKEN_CODE",length=80,nullable=false,unique=true)
private String regionId;
@Column(name="FM_NAME",length=80)
private String fmName;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="COURIER_NO")
private Courier courier;
@OneToMany(mappedBy="admin")
private List privilege = new ArrayList();
I have tried two scenario 1-when using findbyid for retrieving the object and try to set the data in the object in the same field then we are getting an identity already attached with other session 2-when we commented all property setter method which has one to one then it is always creating a new entity in(admin) the table which has one to many relationship As saveorUpdate also not available in Spring Data JPA so could any suggest how we can do the cascade update in Spring Data
Petri,
The way you have written these blogs in layman's terms is so refreshing. I have learned so much so far from you spring data tutorials. keep up the great work!
Thank you for your kind words. I really appreciate them!
Is there any support of deleteby with "and" clause . e.g. : deleteByFirstNameAndLastName
Hi,
As far as I know, the query generation from the method name supports only
SELECT
queries. In other words, if you want to createDELETE
queries, you have to either invoke thedelete()
method or use the@Query
annotation.big help, thanks sir
You are welcome.
Hi Petri
Thank you for taking time to write blogs in addition to your book. I have used JPA in my past projects and did not get chance to use it in the past few years. I wanted to use it again on a new project and I am running in to a strange issue.
WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TodoRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.repositories.BaseRepository.findAll(org.springframework.data.domain.PageRequest)! No property findAll found for type TodoEntity!
Hi,
Thank you for your kind words. I really appreciate them. About your problem, there are a couple of things you can check:
BaseRepository
when you enabled Spring Data JPA (check the value of the@EnableJpaRepositories
annotations'basePackages
attribute).TodoEntity
entity is scanned by the entity manager. You can configure this package when you create theLocalContainerEntityManagerFactoryBean
bean.Also, if your application is based on any of my examples, you shouldn't change the Spring Data JPA version of the example. The reason for this is that the newer versions of Spring Data JPA use a bit different API which might cause compilation failures and other issues.
Hi Petri,
Can you please create a tutorial or at-least guide me to write Java Entities on three tables that are mapped together in OneToMany. More details can be seen here (https://www.w3resource.com/sql/sql-table.php). I want to write a program that can do the CRUD operations on those three tables using Hibernate. Thank you very much in advance.
Hi,
You should take a look at Vlad's blog post on this subject. Also, you might take a look at this blog post that describes the best practices for many-to-one and one-to-many association mappings.
Can I extend TodoRepository in another Repository and create an Implementation? I have 3 services with these common methods create(), deleteById(), findAll(), getById() and update().
I would like to turn them into interface and create the implementation with the business logic in them.
Would it be a good practice to create an interface with these common methods to extend then implement them? Because every time I have to be creating these methods.
Example:
TodoRepository with Crud methods
AuthorService extend GenericService and has its findByName() method.
public interface AuthorService extends TodoRepository {
public AuthorEntity findByName(String name); }
AuthorServiceImpl implements GenericService with the AuthorService method.
@Service
public class AutorServiceImpl implements AutorService {/...../}
Hi Petri
How would an update work in case of M-to-M relationship, using Spring Boot and JPA. For instance consider, Student has a list of Subjects, I may update only one subject of his, but that involves looping twice, which I find to be increasing unnecessary time complexity. Is there a way through which I can perform the update without costing additional overhead?