DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.

Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.

Threat Detection: Learn core practices for managing security risks and vulnerabilities in your organization — don't regret those threats!

Managing API integrations: Assess your use case and needs — plus learn patterns for the design, build, and maintenance of your integrations.

Related

  • Spring Boot: How To Use Java Persistence Query Language (JPQL)
  • Getting Started With JPA/Hibernate
  • Minimizing Latency in Kafka Streaming Applications That Use External API or Database Calls
  • Java Bean Validation: Applying Constraints Programmatically

Trending

  • Two-Pass Huffman in Blocks of 2 Symbols: Golang Implementation
  • MuleSoft: Best Practices on Batch Processing
  • Dust: Open-Source Actors for Java
  • Understanding the Differences Between Repository and Data Access Object (DAO)
  1. DZone
  2. Data Engineering
  3. Databases
  4. The Persistence Layer with Spring 3.1 and JPA

The Persistence Layer with Spring 3.1 and JPA

By 
Eugen Paraschiv user avatar
Eugen Paraschiv
·
Jan. 07, 12 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
62.5K Views

Join the DZone community and get the full member experience.

Join For Free

1. Overview

This is the third of a series of articles about Persistence with Spring. This article will focus on the configuration and implementation of Spring with JPA. For a step by step introduction about setting up the Spring context using Java based configuration and the basic Maven pom for the project, see this article.

The Persistence with Spring series:

  • Part 1 – The Persistence Layer with Spring 3.1 and Hibernate
  • Part 2 – Simplifying the Data Access Layer with Spring and Java Generics
  • Part 4 – The Persistence Layer with Spring Data JPA
  • Part 5 – Transaction configuration with JPA and Spring 3.1

2. No More Spring Templates

As of Spring 3.1, the JpaTemplate and the corresponding JpaDaoSupport have been deprecated in favor of using the native Java Persistence API.

Also, both of these classes are only relevant for JPA 1 (from the JpaTemplate javadoc):

Note that this class did not get upgraded to JPA 2.0 and never will.

As a consequence, it is now best practice to use the Java Persistence API directly instead of the JpaTemplate, which will effectively decouple the DAO layer implementation from Spring entirely.

Exception Translation without the template

One of the responsibilities of JpaTemplate is exception translation – translating the low level exceptions – which tie the API to JPA – into higher level, generic Spring exceptions.

Without the template to do that, exception translation can still be enabled by annotating the DAOs with the @Repository annotation. That, coupled with a Spring bean postprocessor will advice all @Repository beans with all the implementations of PersistenceExceptionTranslator found in the Container – to provide exception translation without using the template.

Exception translation is done through proxies; in order for Spring to be able to create proxies around the DAO classes, these must not be declared final.

Injecting the JPA EntityManager with Spring without the template

The EntityManager is the API of the persistence context; this can be injected directly in the DAO. The Spring Container is capable of acting as a JPA container and of injecting the EntityManager by honoring the @PersistenceContext (both as field-level and a method-level annotation).

For this to work, the PersistenceAnnotationBeanPostProcessor bean must exist in the Spring Container. The bean can be either created explicitly by defining it in the configuration, or automatically, by defining context:annotation-config or context:component-scan in the configuration.

3. The Spring Java configuration

The EntityManager is set up in the configuration by creating a Spring factory bean to manage it; this will allow the PersistenceAnnotationBeanPostProcessor to retrieve it from the Container.

There are two options to set this up – either the simpler LocalEntityManagerFactoryBean or the more flexible LocalContainerEntityManagerFactoryBean. The latter option is used here, so that additional properties can be configured on it:

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
      LocalContainerEntityManagerFactoryBean factoryBean
       = new LocalContainerEntityManagerFactoryBean();
      factoryBean.setDataSource( this.restDataSource() );
      factoryBean.setPackagesToScan( new String[ ] { "org.rest" } );

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(){
         {
            // JPA properties ...
         }
      };
      factoryBean.setJpaVendorAdapter( vendorAdapter );
      factoryBean.setJpaProperties( this.additionlProperties() );

      return factoryBean;
   }

   @Bean
   public DataSource restDataSource(){
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName( this.driverClassName );
      dataSource.setUrl( this.url );
      dataSource.setUsername( "restUser" );
      dataSource.setPassword( "restmy5ql" );
      return dataSource;
   }

   @Bean
   public PlatformTransactionManager transactionManager(){
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(
       this.entityManagerFactoryBean().getObject() );

      return transactionManager;
   }

   @Bean
   public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
      return new PersistenceExceptionTranslationPostProcessor();
   }
}

Also, note that cglib must be on the classpath for Java @Configuration classes to work; to better understand the need for cglib as a dependency, see this article.

4. The Spring XML configuration 

The same Spring configuration with XML:

<bean id="myEmf"
 class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="dataSource" ref="dataSource" />
   <property name="packagesToScan" value="org.rest" />
   <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         <property name="showSql" value="${hibernate.show_sql}" />
         <property name="generateDdl" value="${jpa.generateDdl}" />
         <property name="databasePlatform" value="${persistence.dialect}" />
      </bean>
   </property>
</bean>

<bean id="dataSource"
 class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="${driverClassName}" />
   <property name="url" value="${url}" />
   <property name="username" value="restUser" />
   <property name="password" value="restmy5ql" />
</bean>

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

There is a relatively small difference between the way Spring is configured in XML and the new Java based configuration – in XML, a reference to another bean can point to either the bean or a bean factory for that bean. In Java however, since the types are different, the compiler doesn’t allow it, and so the EntityManagerFactory is first retrieved from it’s bean factory and then passed to the transaction manager:

txManager.setEntityManagerFactory( this.entityManagerFactoryBean().getObject() );

5. Going full XML-less

Usually, JPA defines a persistence unit through the META-INF/persistence.xml file. Starting with Spring 3.1, this XML file is no longer necessary – the LocalContainerEntityManagerFactoryBean now supports a ‘packagesToScan’ property where the packages to scan for @Entity classes can be specified.

The persistence.xml file was the last piece of XML to be removed – now, JPA can be fully set up with no XML.

5.1. The JPA Properties

JPA properties would usually be specified in the persistence.xml file; alternatively, the properties can be specified directly to the entity manager factory bean:

factoryBean.setJpaProperties( this.additionlProperties() );

As a side-note, if Hibernate would be the persistence provider, then this would be the way to specify Hibernate specific properties.

5.2. The DAO

Each DAO will be based on an parametrized, abstract DAO class class with support for the common generic operations:

public abstract class AbstractJpaDAO< T extends Serializable > {

   private Class< T > clazz;

   @PersistenceContext
   EntityManager entityManager;

   public void setClazz( Class< T > clazzToSet ){
      this.clazz = clazzToSet;
   }

   public T findOne( Long id ){
      return this.entityManager.find( this.clazz, id );
   }
   public List< T > findAll(){
      return this.entityManager.createQuery( "from " + this.clazz.getName() )
       .getResultList();
   }

   public void save( T entity ){
      this.entityManager.persist( entity );
   }

   public void update( T entity ){
      this.entityManager.merge( entity );
   }

   public void delete( T entity ){
      this.entityManager.remove( entity );
   }
   public void deleteById( Long entityId ){
      T entity = this.getById( entityId );

      this.delete( entity );
   }
}

A few aspects are interesting here – as discussed, the abstract DAO does not extend any Spring template (such as JpaTemplate). Instead, the JPA EntityManager is injected directly in the DAO, and will have the role of the main Persistence API

Also, note that the entity Class is passed in the constructor to be used in the generic operations:

@Repository
public class FooDAO extends AbstractHibernateDAO< Foo > implements IFooDAO{

   public FooDAO(){
      setClazz(Foo.class );
   }

}

6. The Maven configuration

In addition to the Maven configuration defined in a previous article, the following dependencies are addeed: spring-orm (which also has spring-tx as its dependency) and hibernate-entitymanager:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>3.2.2.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>4.2.0.Final</version>
   <scope>runtime</scope>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.24</version>
   <scope>runtime</scope>
</dependency>

Note that the MySQL dependency is included as a reference – a driver is needed to configure the datasource, but any Hibernate supported database will do.

7. Conclusion

This article covered the configuration and implementation of the persistence layer with JPA 2 and Spring 3.1, using both XML and Java based configuration. The reasons to stop relying on templates for the DAO layer was discussed, as well as getting rid of the last piece of XML usually associated with JPA – the persistence.xml. The final result is a lightweight, clean DAO implementation, with almost no compile-time reliance on Spring. You can check out the full implementation in the github project.

OriginalThe Persistence Layer with Spring 3.1 and JPA from the Persistence with Spring series

Spring Framework Persistence (computer science)

Published at DZone with permission of Eugen Paraschiv, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Spring Boot: How To Use Java Persistence Query Language (JPQL)
  • Getting Started With JPA/Hibernate
  • Minimizing Latency in Kafka Streaming Applications That Use External API or Database Calls
  • Java Bean Validation: Applying Constraints Programmatically

Partner Resources


Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: