Getting started with Spring Data JPA |
|

As we have just released the first milestone of the Spring Data JPA project I’d like to give you a quick introduction into its features. As you probably know, the Spring framework provides support to build a JPA based data access layer. So what does Spring Data JPA add to this base support? To answer that question I'd like to start with the data access components for a sample domain implemented using plain JPA + Spring and point out areas that leave room for improvement. After we've done that I will refactor the implementations to use the Spring Data JPA features to address these problem areas. The sample project as well as a step by step guide of the refactoring steps can be found on Github.
The domain
To keep things simple we start with a tiny well-known domain: we have Customers that have Accounts.
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
// … methods omitted
}
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private Customer customer;
@Temporal(TemporalType.DATE)
private Date expiryDate;
// … methods omitted
}
The Account has an expiry date that we will use at a later stage. Beyond that there's nothing really special about the classes or the mapping – it uses plain JPA annotations. Now let's take a look at the component managing Account objects:
@Repository
@Transactional(readOnly = true)
class AccountServiceImpl implements AccountService {
@PersistenceContext
private EntityManager em;
@Override
@Transactional
public Account save(Account account) {
if (account.getId() == null) {
em.persist(account);
return account;
} else {
return em.merge(account);
}
}
@Override
public List<Account> findByCustomer(Customer customer) {
TypedQuery query = em.createQuery("select a from Account a where a.customer = ?1", Account.class);
query.setParameter(1, customer);
return query.getResultList();
}
}
I deliberately named the class *Service to avoid name clashes as we will introduce a repository layer when we start refactoring. But conceptually the class here is a repository rather than a service. So what do we have here actually?
The class is annotated with @Repository to enable exception translation from JPA exceptions to Spring's DataAccessException hierarchy. Beyond that we use @Transactional to make sure the save(…) operation is running in a transaction and to allow setting the readOnly-flag (at the class level) for findByCustomer(…). This causes some performance optimizations inside the persistence provider as well as on the database level.
As we want to free the clients from the decision whether to call merge(…) or persist(…) on the EntityManager we use the id-field of the Account to decide whether we consider an Account object as new or not. This logic could of course be extracted into a common superclass as we probably don't want to repeat this code for every domain object specific repository implementation. The query method is quite straight forward as well: we create a query, bind a parameter and execute the query to get a result. It's almost so straight forward that one could regard the implementation code as boilerplate as with a little bit of imagination it's derivable from the method signature: we expect a List of Accounts, the query is quite close to the method name and we simply bind the method parameter to it. So as you can see, there‘s room for improvement.
Spring Data repository support
Before we start refactoring the implementation, note that the sample project contains test cases that can be run in the course of the refactoring to verify the code still works. Let's now see how we can improve the implementation.
Spring Data JPA provides a repository programming model that starts with an interface per managed domain object:
public interface AccountRepository extends JpaRepository<Account, Long> { … }
Defining this interface serves two purposes: First, by extending JpaRepository we get a bunch of generic CRUD methods into our type that allows saving Accounts, deleting them and so on. Second, this will allow the Spring Data JPA repository infrastructure to scan the classpath for this interface and create a Spring bean for it.
To have Spring create a bean that implements this interface, all you need to do is use the Spring JPA namespace and activate the repository support using the appropriate element:
<jpa:repositories base-package="com.acme.repositories" />
This scans all packages below com.acme.repositories for interfaces extending JpaRepository and creates a Spring bean for it that is backed by an implementation of SimpleJpaRepository. Let's take a first step and refactor our AccountService implementation a little bit to use our newly introduced repository interface:
@Repository
@Transactional(readOnly = true)
class AccountServiceImpl implements AccountService {
@PersistenceContext
private EntityManager em;
@Autowired
private AccountRepository repository;
@Override
@Transactional
public Account save(Account account) {
return repository.save(account);
}
@Override
public List<Account> findByCustomer(Customer customer) {
TypedQuery query = em.createQuery("select a from Account a where a.customer = ?1", Account.class);
query.setParameter(1, customer);
return query.getResultList();
}
}
After this refactoring, we simply delegate the call to save(…) to the repository. By default the repository implementation will consider an entity new if its id-property is null just like you saw in the previous example (note, you can can gain more detailed control over that decision if necessary). Additionally, we can get rid of the @Transactional annotation for the method as the CRUD methods of the Spring Data JPA repository implementation are already annotated with @Transactional.
Next we will refactor the query method. Let’s follow the same delegating strategy for the query method as with the save method. We introduce a query method on the repository interface and have our original method delegate to that newly introduced method:
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
List<Account> findByCustomer(Customer customer);
}
@Repository
@Transactional(readOnly = true)
class AccountServiceImpl implements AccountService {
@Autowired
private AccountRepository repository;
@Override
@Transactional
public Account save(Account account) {
return repository.save(account);
}
@Override
public List<Account> findByCustomer(Customer customer) {
return repository.findByCustomer(Customer customer);
}
}
Let me add a quick note on the transaction handling here. In this very simple case we could remove the @Transactional annotations from the AccountServiceImpl class entirely as the repository's CRUD methods are transactional and the query method is marked with @Transactional(readOnly = true) at the repository interface already. The current setup, with methods at the service level marked as transactional (even if not needed for this case), is best because it is explicitly clear when looking at the service level that operations are happening in a transaction. Beyond that, if a service layer method was modified to do multiple calls to repository methods all the code would still execute inside a single transaction as the repository's inner transactions would simply join the outer one started at the service layer. The transactional behavior of the repositories and possibilities to tweak it are documented in detail in the reference documentation.
Try to run the test case again and see that it works. Stop, we didn't provide any implementation for findByCustomer(…) right? How does this work?
Query methods
When Spring Data JPA creates the Spring bean instance for the AccountRepository interface it inspects all query methods defined in it and derives a query for each of them. By default Spring Data JPA will automatically parses the method name and creates a query from it. The query is implemented using the JPA criteria API. In this case the findByCustomer(…) method is logically equivalent to the JPQL query select a from Account a where a.customer = ?1. The parser that analyzes the method name supports quite a large set of keywords such as And, Or, GreaterThan, LessThan, Like, IsNull, Not and so on. You can also add OrderBy clauses if you like. For a detailed overview please check out the reference documentation. This mechanism gives us a query method programming model like you're used to from Grails or Spring Roo.
Now let's suppose you want to be explicit about the query to be used. To do so you can either declare a JPA named query that follows a naming convention (in this case Account.findByCustomer) in an annotation on the entity or in your orm.xml. Alternatively you can annotate your repository method with @Query:
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
Now let's do a before/after comparison of the CustomerServiceImpl applying the features that we've seen so far:
@Repository
@Transactional(readOnly = true)
public class CustomerServiceImpl implements CustomerService {
@PersistenceContext
private EntityManager em;
@Override
public Customer findById(Long id) {
return em.find(Customer.class, id);
}
@Override
public List<Customer> findAll() {
return em.createQuery("select c from Customer c", Customer.class).getResultList();
}
@Override
public List<Customer> findAll(int page, int pageSize) {
TypedQuery query = em.createQuery("select c from Customer c", Customer.class);
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
@Override
@Transactional
public Customer save(Customer customer) {
// Is new?
if (customer.getId() == null) {
em.persist(customer);
return customer;
} else {
return em.merge(customer);
}
}
@Override
public List<Customer> findByLastname(String lastname, int page, int pageSize) {
TypedQuery query = em.createQuery("select c from Customer c where c.lastname = ?1", Customer.class);
query.setParameter(1, lastname);
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
}
Okay, let's create the CustomerRepository and eliminate the CRUD methods first:
@Transactional(readOnly = true)
public interface CustomerRepository extends JpaRepository<Customer, Long> { … }
@Repository
@Transactional(readOnly = true)
public class CustomerServiceImpl implements CustomerService {
@PersistenceContext
private EntityManager em;
@Autowired
private CustomerRepository repository;
@Override
public Customer findById(Long id) {
return repository.findById(id);
}
@Override
public List<Customer> findAll() {
return repository.findAll();
}
@Override
public List<Customer> findAll(int page, int pageSize) {
TypedQuery query = em.createQuery("select c from Customer c", Customer.class);
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
@Override
@Transactional
public Customer save(Customer customer) {
return repository.save(customer);
}
@Override
public List<Customer> findByLastname(String lastname, int page, int pageSize) {
TypedQuery query = em.createQuery("select c from Customer c where c.lastname = ?1", Customer.class);
query.setParameter(1, lastname);
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
}
So far so good. What is left right now are two methods that deal with a common scenario: you don't want to access all entities of a given query but rather only a page of them (e.g. page 1 by a page size of 10). Right now this is addressed with two integers that limit the query appropriately. There are two issues with this. Both integers together actually represent a concept, which is not made explicit here. Beyond that we return a simple List so we lose metadata information about the actual page of data: is it the first page? Is it the last one? How many pages are there in total? Spring Data provides an abstraction consisting of two interfaces: Pageable (to capture pagination request information) as well as Page (to capture the result as well as meta-information). So let's try to add findByLastname(…) to the repository interface and rewrite findAll(…) and findByLastname(…) as follows:
@Transactional(readOnly = true)
public interface CustomerRepository extends JpaRepository<Customer, Long> {
Page<Customer> findByLastname(String lastname, Pageable pageable);
}
@Override
public Page<Customer> findAll(Pageable pageable) {
return repository.findAll(pageable);
}
@Override
public Page<Customer> findByLastname(String lastname, Pageable pageable) {
return repository.findByLastname(lastname, pageable);
}
Make sure you adapt the test cases according to the signature changes but then they should run fine. There are two things this boils down to here: we have CRUD methods supporting pagination and the query execution mechanism is aware of Pageable parameters as well. At this stage our wrapping classes actually become obsolete as a client could have used our repository interfaces directly. We got rid of the entire implementation code.
Summary
In the course of this blog post we have reduced the amount of code to be written for repositories to two interfaces with 3 methods and a single line of XML:
@Transactional(readOnly = true)
public interface CustomerRepository extends JpaRepository<Customer, Long> {
Page<Customer> findByLastname(String lastname, Pageable pageable);
}
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
List<Account> findByCustomer(Customer customer);
}
<jpa:repositories base-package="com.acme.repositories" />
We have type safe CRUD methods, query execution and pagination built right in. The cool thing is that this is not only working for JPA based repositories but also for non-relational databases. The first non-relational database to support this approach will be MongoDB as part of the Spring Data Document release in a few days. You will get the exact same features for Mongo DB and we're working on support for other data bases as well.. There are also additional features to be explored (e.g. entity auditing, integration of custom data access code) which we will walk through in upcoming blog posts.
Similar Posts
- Fine-tuning Spring Data repositories
- Advanced Spring Data JPA – Specifications and Querydsl
- Transactions, Caching and AOP: understanding proxy usage in Spring
- Using JPA in Spring without referencing Spring
- What happened to getConfigLocations()?





Micke says:
Added on February 10th, 2011 at 7:10 pmSorry, but this looks very similar to and equally useless as the existing Hades framework. You can only generate very simple queries from method names and for everything else you are left with writing queries as non-typesafe strings in @Query. If SpringSource really wants to introduce proper type safe queries with full code completion then have a look at http://www.querydsl.com/ (no affiliation).
Andrew Swan says:
Added on February 10th, 2011 at 7:17 pmNice work Oliver. It should save a lot of boilerplate.
Is there much overlap between how Spring Data JPA auto-generates code (CRUD methods and finders) and how Spring Roo does so?
Murilo Rodrigues says:
Added on February 10th, 2011 at 9:34 pmSpring Data JPA seems to have some of overlap with Spring Roo persistence, although the approach is quite different.
Are there any plans to integrate both projects?
Oliver Gierke (blog author) says:
Added on February 11th, 2011 at 1:57 amHi all,
@Micke – you are right, Spring Data JPA M1 is almost equivalent to Hades. That's because I am the project lead of Hades as well. The goal of the first milestone was to move over the majority of the codebase and proceed from there. We're also in contact with the QueryDsl guys to provide integration. There is a JIRA to follow the development [1] and the branch at GitHub [2] already contains a working version.
@Andrew, Murilo – Spring Data JPA is a general, Spring based approach to repositories. So it can be used in plain Java based projects as well. Roo currently uses an ActiveRecord kind of pattern which works with static methods on the entities. While this is a perfectly fine approach there seems to be some demand for rather traditional repository approach [3]. So we have been in close contact with the Roo team for quite a while already and will continue to work on closer integration.
Thanks for the feedback!
[1] https://jira.springsource.org/browse/DATAJPA-8
[2] https://github.com/SpringSource/spring-data-jpa/tree/querydsl
[3] https://jira.springsource.org/browse/ROO-301
Ron Piterman says:
Added on February 11th, 2011 at 3:21 amspann ( http://code.google.com/p/spann/ ) takes a much more generic aproach to annotations.
It does provide some JPA support annotations, which allow much more than the functionality described here:
JPQL, By-Method-Name a la Rails, Named Queries and Query Position support out of the box.
But the strength of spann is that it allows developers to both hook into the existing annotations processing and extend existing "annotations" with new functionality (for example create an annotation to add query hint support), and to create completely new annotations and process them in a simple and consice way.
Cheers, Ron
Jose Noheda says:
Added on February 11th, 2011 at 3:28 amI like both the Roo approach (rich domain models) and this repository (DAO) approach but they seem ortogonal and I don't really like the breach between them. Right now you either choose Roo or Data. May be the DDD approach of Roo can be integrated in Data (somehow) and, vice versa, Roo offers the alternative of choosing more traditional persistence facades based on Data?
Oliver Gierke (blog author) says:
Added on February 11th, 2011 at 3:44 amJose,
thanks for your feedback. What exactly makes you think the active record pattern in Roo is more DDD? A DDD repository is a concept [1], not dictating the way it's implemented. Both ways have their pros and cons of course. But the core goal of Spring Data in the first place is to provide sophisticated data access support for various data stores, *no matter* if they use Roo or not. Beyond that basic statement we're working with the Roo team to integrate a more classical way of approaching repositories into it (see the links I posted in my comment above).
Cheers,
Ollie
[1] http://domaindrivendesign.org/node/123
Axel Knauf says:
Added on February 11th, 2011 at 4:03 amThanks Oliver for the nice introduction. I already thought about asking if there were any plans to integrate Hades with the existing Spring stack – but this question now seems pretty obsolete. Keep up the good work!
Micke says:
Added on February 11th, 2011 at 4:36 amOliver, thanks for the good news about the QueryDsl integration!
Russ Parry says:
Added on February 11th, 2011 at 7:52 pmOliver,
Great to hear that things are coming along with this. I notice from Jira that M2 is currently scheduled for Mar 11th. I was wondering if you had any idea of what the roadmap looks from there on out? Specifically, I just started on a project with lots of boilerplate DAOs and have suggested we take a look at Hades as a way of getting rid of some of that going forward. But I wonder now if we should hold off until Spring Data JPA goes final or if we should move ahead with Hades for the time being? What are your thoughts on the current maturity of Spring Data JPA vs. Hades for production deployments?
Thanks for your thoughts and the great work on Spring Data JPA so far.
Julio says:
Added on February 11th, 2011 at 8:00 pmI just recently discovered Hades and I wanted to learn more to use it in a future project.
Having it 'lifted' to a Spring project is definitively a good thing!
Oliver Gierke says:
Added on February 12th, 2011 at 4:56 amRuss,
the M1 release is pretty much the Hades 2.0.2 codebase. The main changes we did during the move was extracting the core infrastructure for query method parsing, repository creation and the configuration namespace into Spring Data Commons. As Hades has been around for over 2 years already we will have a very short roadmap to GA, might be that M2 is already becoming an RC1, quickly followed by the GA. The main tasks left open is porting the Hades extensions module for integration with Spring MVC and evaluating in how far we can contribute the code for the Hades Eclipse plugin to Spring IDE/STS.
If you are not going to customize Spring Data JPA repositories in the first place I'd recommend to use the milestone already. If you already have Hades in place, and extend the proxy factory or depend on other internals I'd probably rather wait for the GA, as the internals (esp. of the part in Spring Data Commons) might still move a little as we make progress with the implementations for the NoSQL datastores.
Cheers,
Ollie
Chance says:
Added on February 13th, 2011 at 3:47 amLike what I see here a lot. Modern architecture and elimination of boilerplate are both wins.
Mohit Arora says:
Added on February 13th, 2011 at 6:17 pmNice work. I just tried to download it but looks like latest jar is not uploaded in downloads section. I could not find following class in the downloaded jar.
org.springframework.data.jpa.repository.JpaRepository
Chance says:
Added on February 14th, 2011 at 5:31 amWRT design – would you call these repository interfaces from controller code?
Oliver Gierke says:
Added on February 14th, 2011 at 5:51 amYes, that's one of the reasons why the methods of JpaRepositories are transactional already. Given a scenario with a lot of logic implemented in a service layer you will have to make this service layers transactional. But in very simple use cases that are able to actually implement all business code inside the domain classes a simple call to save(…) is sufficient. So no need to artificially introduce an additional layer just because of the need for transactions.
Cheers,
Ollie
LpG says:
Added on February 14th, 2011 at 8:43 amI think you've done a little mistake here (pageSize pageable):
@Override
public Page findByLastname(String lastname, Pageable pageSize) {
return repository.findByLastname(lastname, pageable);
}
Anyway, it's great article !
Cheers,
LpG
Oliver Gierke (blog author) says:
Added on February 14th, 2011 at 9:09 amLpG,good catch, fixed!
Ollie
Colin Sampaleanu says:
Added on February 14th, 2011 at 9:57 amThe refactored AccountServiceImpl is no longer annotated with the original @Transactional annotations that it had. In this specific example, this is ok, as the list and save methods are one liners that simply delegate to the new DAO methods, which _are_ transactional. That said, it would be much more appropriate to leave the service marked at transactional (either at the class or method level), to force the service layer methods to always be transactional units, in the case that somebody starts combining multiple DAO operations in a service layer method. Otherwise a service layer method could be combining work from two (or more) different DAO level transactions. Oliver, I really think you should talk to this aspect in the blog post…
I note that CustomerServiceImpl is properly marked transactional in this fashion…
Jeroen van Schagen says:
Added on February 14th, 2011 at 1:36 pmNice work! Bringing some kind of standardization to repositories was much needed.
P.S. Why do people keep saying that Active Record is more DDD than the traditional repository approach? Active Record is an implementation approach that merges two layers in one. It has nothing specific to do with domain driven design.
wims.tijd says:
Added on February 14th, 2011 at 2:39 pm@BeforeTransactionpublic void setupData() throws Exception {
if (countRowsInTable("User") == 0) {
executeSqlScript("classpath:data.sql", false);
}
logger.info("rows:" countRowsInTable("User"));
}
@Test
public void findsPaged() throws Exception {
Page users = repository.findByLastname("Matthews", new PageRequest(2, 2));
logger.info(users);
logger.info("elements:" users.getTotalElements());
logger.info("pages:" users.getTotalPages());
}
shows :
RepoTest - rows:8
TransactionalTestExecutionListener - Began transaction (1): transactio
user1_.id) as col_0_0_ from User user0_ cross join User user1_
er0_.id as id0_, user0_.lastname as lastname0_, user0_.username as use
RepoTest - Page 2 of 32 containing org.wims.data.model.User instances
RepoTest - elements:64
RepoTest - pages:32
can you think of anything i forgot ? i have 8 rows by count but 32 pages of 2 elements and only 6 of them by lastname 'Matthews'.
Chance says:
Added on February 14th, 2011 at 2:46 pmFor ground up designs – is a separate service layer needed? SDJ contains transactional logic and sits on JPA which is a repository. It's already kind of a service layer, or a combined DAL and service layer, no?
Oliver Gierke (blog author) says:
Added on February 14th, 2011 at 3:50 pm@Colin – good point, I've updated the sample and added a paragraph on transaction details. Thanks for helping out with the wording as well.
@wims.tijd – I think you've discovered a bug there. We accidentally added a second Root to the query causing a cross join to calculate the number of totals which in turn results in invalid results. I've just fixed [1] the bug you should find an updated JAR in the snapshot repository.
[1] https://github.com/SpringSource/spring-data-jpa/commit/cd4013fe1d845cab1ddd4859e8413b09ad589700
Carl Pritchett says:
Added on February 14th, 2011 at 7:14 pmSmall typo in the last example above the summary:
Line 7 reads:
public Page findByLastname(String lastname, Pageable pageSize) { …but it probably should read:
public Page findByLastname(String lastname, Pageable pageable) { …Chuck S says:
Added on February 14th, 2011 at 8:53 pmAlso in the Summary you left out the method
List findByLastname(String lastname);
in the CustomerRepository interface.
Oliver Gierke (blog author) says:
Added on February 14th, 2011 at 11:59 pm@Carl – I fixed this already actually, seems you're still getting a cached version of the blog post. Thanks for spotting it anyway!
@Chuck – I know the method is in the codebase on Github but I deliberately didn't include it here as it would simply double what we do with
AccountService.findByCustomer(Customer customer)already.Chuck S says:
Added on February 15th, 2011 at 1:33 amOK then you probably want to change the text to say "we have reduced the amount of code to be written for repositories to two interfaces with *two* methods".
MA says:
Added on February 15th, 2011 at 9:50 pmI tried the same on GAE. I am getting Cannot resolve the name 'repository:transactional-repository-attributes' to a(n) 'attribute group' component. Do you know the reason?
wims.tijd says:
Added on February 17th, 2011 at 3:01 pm@Oliver Gierke – thank you, indeed it was the count sql : "select top ? count(user1_.id) as col_0_0_ from User user0_ cross join User user1_"
This a great addition.
I am combining this with jax-rs:jboss-resteasy and spring-integration.
Ryosuke says:
Added on February 19th, 2011 at 12:43 pmlook at (http://s2container.seasar.org/2.4/ja/s2jdbc_abstract.html)
Manas Sahu says:
Added on February 21st, 2011 at 1:34 amI tried using both and in my MVC. But it's generating src-resolve: Cannot resolve the name 'repository:transactional-repository-attributes' to a(n) 'attribute group' component. How to resolve this.
Manas Sahu says:
Added on February 21st, 2011 at 1:37 amI tried using both context:component-scan and jpa:repositories for base-package in Spring MVC. It's resulting Exception -> src-resolve: Cannot resolve the name 'repository:transactional-repository-attributes' to a(n) 'attribute group' component.
raymond.mh.ng says:
Added on February 21st, 2011 at 4:03 amGet the following error in tomcat 7.0.6
SEVERE: The web application [/basicWebRef2] registered the JDBC driver [com.mysq
l.jdbc.Driver] but failed to unregister it when the web application was stopped.
To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Hence my application can never start propertly.
Moreover, it seems that it conflict with
http://www.springframework.org/schema/context/spring-context-3.0.xsd
Any idea to solve these two issues?
Oliver Gierke says:
Added on February 21st, 2011 at 7:04 am@Manas, @Raymond – I suggest to ask such questions in the Spring Forums (forum.springsource.org) as you will find more people capable in answering the questions.
For the missing
repositories:transactional-repositoryit seems you are lacking spring-data-commons on the classpath.raymond.mh.ngq says:
Added on February 22nd, 2011 at 1:15 amThank Oliver,
Actually, I found the "spring-data-commons-core-1.0.0.M1.jar" in my \webapps\basicWebRef2\WEB-INF\lib. (Where the basicWebRef2 is my application name.) Is this version of jar correct?
BTW, will try to put this message also to the springsource.org forum as well.
Thanks for your help.
wims.tijd says:
Added on February 22nd, 2011 at 2:15 pmregarding pagerequest :
the count query does not take into account the query itself it merely counts all records
see: http://forum.springsource.org/showthread.php?t=104016
labtrax says:
Added on February 24th, 2011 at 9:19 amchecked out the project and got errors:
Missing artifact javax.persistence:com.springsource.javax.persistence:jar:2.0.0:compile
alex says:
Added on February 28th, 2011 at 8:34 amhow can I get hold of spring-data-jpa? I have no access to maven but that artifact does not seem to be available for download? many thanks
alex says:
Added on February 28th, 2011 at 11:33 amspring-data-jpa and the rest are available here: https://s3browse.springsource.com/browse/maven.springframework.org/milestone/org/springframework/data/ in case someone else is interested.
Mike Macias says:
Added on February 28th, 2011 at 1:21 pmOn the web, there was indication that "Spring Data" would be providing support for MyBatis 3.x at some future point.
Is this still something that will be coming ? If so, is there an estimated timeframe for this ?
Is the MyBatis-Spring-1*.x integration module provided by the MyBatis team still the way to go for now, if we want to integrate MyBatis 3.x with the latest Spring 3.0.5 ?
Thanks,
Mike M.
Ladislav says:
Added on March 2nd, 2011 at 2:35 amHi,
spring is going to be very good framework. What I always missed in such frameworks was those were directly proposed for frontend without any developer friendly mechanism/interfaces for databases. I think Spring is going to enhance data related features more and more.
I totally agree with @Micke and with his first post. To his post I could add one note. I already played with opensource framework OpenXava and even it also has it's holes, it could be also place where to learn some advanced methods.
Anyway, very gut tutorial.
Thank you for your hard work.
Best regards,
Ladislav Jech
Mark Pollack says:
Added on March 4th, 2011 at 10:33 am@Mike
Yes, the MyBatis-Spring integration module provided by the MyBatis team is the way to go now, it supports Spring 3.0.5.
Where were you looking on the Spring Data page regarding support for iBatis. I think it maybe have been listed there a while ago, but it isn't anymore.
Mark Pollack
Martín Caballero says:
Added on April 1st, 2011 at 11:02 amAn entity manager is not thread-safe. How could we prevent this? If we use @PersistenceUnit with an EntityManagerFactory and create entities managers from there we can resolve this? but, we must use UserTransactions instead of the Spring automatically transactions mechanism?
is that right? thanks a lot!!!
Gonzalo Diethelm says:
Added on April 4th, 2011 at 9:41 amGreat blog for a very interesting subject.
I am getting a "Failed to load ApplicationContext" error. The exception eventually boils down to:
Error creating bean with name 'basInstrumentRepository': Post-processing failed of bean type [class org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean] failed; nested exception is java.lang.reflect.MalformedParameterizedTypeException
Any hints? I have made sure to have only the latest versions of everything, and I am not mixing old Spring jars in my classpath.
Thanks in advance and best regards.
Jessie Evangelista says:
Added on April 17th, 2011 at 9:14 amThanks for this article.
I was able to easily make use of Spring Data JPA.
I made a post of my experience:
http://blog.henyo.com/2011/04/setting-up-spring-data-jpa-project.html
I also shared a sample project on github:
https://github.com/henyojess/spring-data-jpa-trial
PVN says:
Added on April 20th, 2011 at 5:20 amHi I am using HQL for selecting all the contents in 'EXCEPTION_CODE_MASTER' table.
findAllEXCEPTION_CODE_MASTERs() method:
return entityManager().createQuery("select o from EXCEPTION_CODE_MASTER o", EXCEPTION_CODE_MASTER.class).getResultList();
This is my controller code:
@RequestMapping(method = RequestMethod.GET)
public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
uiModel.addAttribute("exception_code_masters", EXCEPTION_CODE_MASTER.findAllEXCEPTION_CODE_MASTERs());
return "exception_code_masters/list";
}
Which calls the above declared"findAllEXCEPTION_CODE_MASTERs()' method.
Now in the jsp file when i try to print all data in the object
xxxx.jsp
${Exception}
It is showing the entire object.
[EXCP_CODE: 100, EXCP_TYPE: Null Pointer, EXCP_DESC: It is a Show Stopper, EXCP_CATEGORY: Critical, EXCP_CODE: 50, EXCP_TYPE: Memory, EXCP_DESC: Can be ignored, EXCP_CATEGORY: Medium,
EXCP_CODE: 75, EXCP_TYPE: xxxxxx, EXCP_DESC yyyyyy: , EXCP_CATEGORY: zzzzzzz]
But I want to print the value of EXCP_CODE only.
Can anybody help me?
Thanks and regards.
Oliver Gierke says:
Added on April 20th, 2011 at 5:40 amI guess the Spring Forums is a more suitable place to ask questions like this one: http://forum.springframework.org
Cheers,
Ollie
Mohammad says:
Added on April 26th, 2011 at 9:03 pmThanks Oliver, great post.
Jean-Philippe Dutreve says:
Added on May 11th, 2011 at 10:44 amHi,
I like the boilerplate removed by SDJ. But I don't like that repository interfaces are mixed with implementation details (JPA here). Interfaces should be technology agnostic. And @Transactional at the interface level is not OK for non transactional providers (i.e. filesystem for testing).
I suggest that this useful code move to an abstract class.
Cheers,
Jean-Philippe
Oliver Gierke (blog author) says:
Added on May 11th, 2011 at 11:15 amHi Jean-Philippe,
completely agree in both points. The upcoming RC1 release will include the possibility to simply use Repository or PagingAndSortingRepository directly (and thus not exposing JPA as persistence technology). The reason we require this right now is to be safe in a rare case where someone uses Spring Data JPA and e.g. Mongo in the same project and the base packages for classpath scanning overlap. In that (admittedly rare) case we can now safely distinguish between both the technologies. In the upcoming release we will simply require users to use filter in- or excludes to handle this case if it ever occurs.
Transactionality at the interface is a bit similar here as well. To allow redefining the transaction configuration for CRUD methods in a user's repository interfacewe support a simple redeclaration of e.g. findAll(…). To let that transaction config take effect, the original one has to be at the interface as the transaction configuration discovery semantics would always favour the transaction config at SimpleJpaRepository in the JPA case. We're looking into the options there as well.
Siva says:
Added on July 23rd, 2011 at 7:08 amHi I am getting below error when i started application in tomcat.
12:54:55,978 [ERROR] [main] [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mattSnapshotRepository': Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4205)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4704)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
at org.apache.catalina.core.StandardService.start(StandardService.java:525)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor.(TransactionalRepositoryProxyPostProcessor.java:76)
at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.java:98)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1408)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
… 26 more
23-Jul-2011 12:54:55 org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
MY appcontext.xml file
—————
please help me ….
Alex says:
Added on August 7th, 2011 at 5:39 amI stumbled upon the same exception and can't quite figure out what I've done wrong. Bummer!
Jessie Evangelista says:
Added on August 7th, 2011 at 7:25 amAlex,
check out my experience with spring data jpa:
http://blog.henyo.com/2011/04/setting-up-spring-data-jpa-project.html
Abhishek Chavan says:
Added on August 27th, 2011 at 7:11 amHaving used Spring Data JPA was a great experience. I am currently reading Spring ROO and find that there is a great overlap between the two. I love Spring Data and ROO seems pretty neat too. Is there a way i can have best of both somehow?
Sid Sharma says:
Added on March 12th, 2012 at 3:41 pmHi Oliver,
SpringData for mongoDb will convert all MongoExceptions into DataAccessExceptions.
All repositories in my project implement XYZRepository.
XYZRepository implements JPARepository
Is it possible to write an aspect to catch DataAccessExceptions thrown by all beans of type XYZRepository i.e. directly or indirectly implementing XYZRepository.
In short, I need to wrap all DataAccessException into CustomException thrown by my APIs.
Thanks,
Sid
kg says:
Added on April 26th, 2012 at 12:37 amHi,
Simple question, I'm new to spring wrapping JPA. How can I specify an order by with the repository one liner interface methods that return a list of entities?
Cheers
Oliver Gierke says:
Added on April 26th, 2012 at 2:43 amExtend PagingAndSortingRepository and you get findAll(Sort sort) which you can then hand the appropriate sorting options to.
ew says:
Added on May 26th, 2012 at 4:12 amHi,
can anyone help with this.. ?
Im trying to use the PageableArgumentResolver as specified in the reference docs but it doesnt work, i keep getting this error:
11:10:05,541 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/QL].[Spring MVC Dispatcher Servlet]] (http–127.0.0.1-8080-6) Servlet.service() for servlet Spring MVC Dispatcher Servlet threw exception: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.domain.Pageable]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101) [spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
heres my config…
..my controller method
@RequestMapping(value = "stream/getRealTimeStream", method = RequestMethod.GET)
public ModelAndView getRealTimeStream( Model model, @PageableDefaults (pageNumber=0, value=20) Pageable pageable) {
..my request..
GET /QL/stream/getRealTimeStream?page=0&page.size=20&page.sort=cr eateDate&page.sort.dir=desc
Sébastien H. says:
Added on June 3rd, 2012 at 12:34 pmWith spring 3.1 if you are using you should not use this :
</property
but this instead :
For more information, see :
http://forum.springsource.org/showthread.php?109306-org-springframework-beans-BeanInstantiationExcepti-on
Sébastien H. says:
Added on June 3rd, 2012 at 12:36 pmWith spring 3.1 if you are using you should not use this :
</property
but this instead :
For more information, see :
http://forum.springsource.org/showthread.php?109306-org-springframework-beans-BeanInstantiationExcepti-on
Satya Prasad says:
Added on December 19th, 2012 at 10:53 pmWe are using spring data JPA in our application. But repository.save(entity) is not updating record if it's having Id (Long) instead it's creating new record.
Can you please help me out in this situation.
BW says:
Added on March 30th, 2013 at 3:05 pmCaused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jitScheduleConstraintsRepository': Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:4750)
at com.sun.enterprise.web.WebModule.contextListenerStart(WebModule.java:550)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5366)
… 39 more
Caused by: java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor.(TransactionalRepositoryProxyPostProcessor.java:70)
at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1443)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
… 53 more
BW says:
Added on March 30th, 2013 at 3:06 pmHello I get this error on Glassfish. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name blahRepo: Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:4750)
at com.sun.enterprise.web.WebModule.contextListenerStart(WebModule.java:550)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5366)
… 39 more
Caused by: java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionInterceptor.setTransactionManagerBeanName(Ljava/lang/String;)V
at org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor.(TransactionalRepositoryProxyPostProcessor.java:70)
at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1443)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
… 53 more