Using Spring Data JPA To Reduce Data Access Coding

Introduction

On March 24, 2011, springsource released milestone 2 of the Spring Data JPA library. Per the Spring Data project website, Spring Data JPA:

Simplifies the development of creating a JPA-based data access layer and provides 'cross-store' persistence functionality for JPA managed entites [sic].

Since I recently started using JPA 2 in my Spring applications, I decided to learn more about Spring Data JPA. To assist my learning, I took an example project that uses Struts 2, Spring 3, JPA 2 (with Hibernate 3.5 as the JPA provider) and modified it to use Spring Data JPA. This blog article is about what I had to modify so the project could use Spring Data JPA and what I could then get rid of.

Example Application That Uses Spring Data JPA

Download the example application that uses Spring Data JPA. It is a standard Maven project, created using Eclipse 3.6. The application uses an in-memory database (HSQL) that is setup by the Spring applicationContext.xml class. See files schema.sql and test-data.sql in src/main/resources for the schema created during the application's startup and the initial records inserted into the table's database. Using the in-memory database means there is no need to setup and run a separate database server for the example application.

You can import this project into Eclipse by using Eclipse's File - Import feature. In the project's root folder is a README.txt file that explains how to run the application. If you're not using Eclipse with the Maven plugin, you can unzip the archived download and view the source code in any text editor. If you are using a Java IDE that enables importing of Maven projects you should be able to import the unzipped project.

You can also run the application using Maven directly if you have downloaded and installed Maven on your computer. Open a terminal (command) window and navigate to the project's root folder (the folder where pom.xml resides). Then in the terminal window issue these commands:

  1. mvn clean
  2. mvn test (All tests should pass successfully)
  3. mvn jetty:run

When you see [INFO] Started Jetty Server open a web browser and navigate to http://localhost:8080/strutsspringdataexample/index.jsp. Enter 1, 2, or 3 in the employee id text field and click submit.

To stop the Jetty web server type CTRL-C in the terminal window.

How To Enable Spring Data JPA In Your Project

To use the Spring Data JPA library I had to add the Spring milestone repository to the project's pom.xml file.



        <repository>
            <id>org.springframework.maven.milestone</id>
            <name>Spring Maven Milestone Repository</name>
            <url>http://maven.springframework.org/milestone</url>
        </repository>

I also added the dependency node for the Spring Data JPA artifact. Note the version current as of March 25, 2011 is 1.0.0.M2 but that will change as the project moves forward. Consult the Spring Data project website for the current version.



        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.0.0.M2</version>
        </dependency>

To use the Spring Data JPA's namespace in my Spring configuration file I added this namespace declaration and schema location:



xmlns:jpa="http://www.springframework.org/schema/data/jpa"

http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd

To enable Spring to find the Repository bean (more on this in a moment) I also added this node to the Spring configuration file:



<jpa:repositories base-package="name.brucephillips.springjpaexample.repository" />    

The above tells Spring to look in package name.brucephillips.springjpaexample.repository for interfaces annotated with the @Repository annotation or interfaces that extend one of the Spring Data JPA interfaces.

How To Use Spring Data JPA To Reduce Data Repository Code

If you examine the source code for the previous example project that did not use Spring Data JPA, you'll find that I defined a dao package with an interface and implementation class to enable interaction between Person objects and the data repository. The PersonDaoJpa class uses the JPA EntityManager to perform the basic CRUD tasks and to also find a specific Person object using the Person class's emplid instance field.

To convert that project to use Spring Data JPA, I deleted the dao package, the interface, and the implementation class. Those are no longer needed when using Spring Data JPA. In the example application that does use Spring Data JPA, you'll find a repository package, with one interface:



public interface PersonRepository extends JpaRepository<Person, Long> {
    
    /**
     * Get Person with the associated emplid.
     * @param emplid - Employee ID
     * @return Person object if provided emplid is
     * found in the data repository, otherwise return null
     */

    Person findByEmplid(Long emplid);

}

Note that the PersonRepository interface extends interface JpaRepository, which is provided by the Spring Data JPA library. The JpaRepository interface specifies all the standard CRUD methods my project may need to use to manage Person objects with the data repository. Also note the use of <Person, Long>. This tells Spring that this repository is for class Person and that class Person's field annotated with @ID is type Long.

What I did not need to code is an implementation of the PersonRepository interface. Spring will create an implementation of this interface and make a PersonRepository bean available to be autowired into my Service class. The PersonRepository bean will have all the standard CRUD methods (which will be transactional) and return Person objects or collection of Person objects. So by using Spring Data JPA, I've saved writing my own implementation class.

The only code I needed to write in interface PersonRepository were method declarations for any non-standard CRUD methods I want to use. In this example, I want to find a Person by using his emplid value. Note that emplid is defined as an instance field in class Person. How I named this method is important. Spring Data JPA will translate the method name into a JPA criteria query. See the Spring Data JPA documentation for more information about how Spring Data JPA translates method names into queries. Spring Data JPA does allow you to override its query translation from method name and specify your own query.

Modify The Service Class To Use The Spring Created Repository Bean

In my Service class (see PersonServiceImpl) I just needed to add an instance field for the PersonRepository object. An instance of that type will automatically be provided to the class by Spring because of the @Autowired annotation.


    
@Autowired
private PersonRepository personRepository;
    

Then I just replaced using the personDao object with using the personRepository object in the PersonServiceImpl class.

All my JUnit tests passed and the application runs fine.

Summary

Spring Data JPA seems very useful in reducing the amount of data access code you'll need to write. If you're already using Spring 3 and JPA 2 then adding Spring Data JPA may be a good idea and should save development time.

There is more Spring Data JPA can do including built-in support for paging and sorting objects returned. Consult the references below for additional information.

References

  1. Spring Data
  2. Spring Data JPA - Reference Documentation
  3. Spring Data JPA API
  4. Getting Started with Spring Data JPA, February 10, 2011

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Thanks to this article of yours, I was able to easily make use of Spring Data JPA.

I wrote a blog post about it here:
http://blog.henyo.com/2011/04/setting-up-spring-da...

I also uploaded a sample project on github:
https://github.com/henyojess/spring-data-jpa-trial...
# Posted By Jessie Evangelista | 4/17/11 9:12 AM
I imported the application in my eclipse workspace . Am stuck at a certain nasty configuration error. It does not load applicationcontext.xml flashing an error :
refrenced file contain error http://www.springframework.org/schema/context/spri...
The errors below were detected when validating the file "spring-context-3.0.xsd" via the file "applicationContext.xml". In most cases these errors can be detected by validating "spring-context-3.0.xsd" directly. However it is possible that errors will only occur when spring-context-3.0.xsd is validated in the context of applicationContext.xml.
Did you see these too ?
# Posted By pryd | 7/20/11 12:33 AM
pryd - I don't get the error you reference. Following the instructions in the readme I'm able to run the tests and build/run the web application (using Jetty).

Let us know if you figure out a solution to your problem.
# Posted By Bruce | 7/20/11 7:06 AM
Hi Bruce, great article. I have started working with Spring-Data and i think it is amazing. But i looked at the example application using Struts i saw that the domain model is visible for the view layer. Would you say that the example is a bit simplified. Or would you in a real world scenario use some sort of data transfer object to hide the real domain object? are tools like dozer applicable for spring-data. My guess is not.
# Posted By Johannes | 8/5/11 7:57 AM
Johannes - yes the example is very simplified. In a more complicated project DTO's are useful to provide object state to the views. I've not used Dozer.
# Posted By Bruce | 8/5/11 8:06 AM
encountered the same xsd namespace error in applicationContext.xml that pryd commented on, removed context from the xsi:schemalocation section to eliminate it based on the comments at: http://forum.springsource.org/showthread.php?11864...
Thanks for the article, this was helpful!
# Posted By todd | 12/17/11 3:11 PM
We have application that uses Hibernate and the entities are mapped in the *.hbm.xml file.
How Spring Data JPA can be used to utilize our Hibernate mapping? We don't need use annotation in entity and convert *.hbm.xml into orm.xml.
# Posted By supra | 3/8/12 6:27 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner