persistence with spring ebook
TRANSCRIPT
-
8/10/2019 Persistence With Spring eBook
1/45
1
PERSISTENCE WITH SPRING
TABLE OF CONTENTS
1. Spring with Maven
2. Hibernate 3 with Spring
3. Hibernate 4 with Spring
4. Spring 3 and JPA with Hibernate
5. The Persistence Layer with Spring Data JPA
6. The DAO with Spring 3 and Hibernate
7. The DAO with JPA and Spring
8. Simplify the DAO with Spring and Java Generics
9. Transactions with Spring 3 and JPA
-
8/10/2019 Persistence With Spring eBook
2/45
2
Spring with Maven
1. Overview
2. Basic Maven Spring Dependencies
3. Spring Persistence with Maven
4. Spring MVC with Maven
5. Spring Security with Maven
6. Spring Test
7. Using Milestones
8. Using Snapshots
9. Conclusion
Hibernate 3 with Spring
1. Overview
2. Java Spring Configuration for Hibernate 3
3. XML Spring Configuration for Hibernate 3
4. Spring, Hibernate and MySQL
5. Usage
6. Maven
7. Conclusion
Hibernate 4 with Spring
1. Overview
2. Maven
3. Java Spring Configuration for Hibernate 4
4. XML Spring Configuration for Hibernate 4
5. Spring, Hibernate and MySQL
-
8/10/2019 Persistence With Spring eBook
3/45
3
6. Usage
7. Conclusion
Spring 3 and JPA with Hibernate
1. Overview
2. The JPA Spring Configuration with Java
3. The JPA Spring Configuration with XML
4. Going full XML-less
5. The Maven configuration
6. Conclusion
The Persistence Layer with Spring Data JPA
1. Overview
2. No More DAO implementations
3. The Spring Data managed DAO
4. Defining custom access method and queries
5. Spring Data transaction configuration
6. Spring Data Configuration
7. The Spring Java or XML configuration
8. The Maven configuration
9. Conclusion
The DAO with Spring 3 and Hibernate
1. Overview
2. No More Spring Templates
3. The DAO
-
8/10/2019 Persistence With Spring eBook
4/45
4
4. Conclusion
The DAO with JPA and Spring
1. Overview
2. No More Spring Templates
3. The DAO
4. Conclusion
Simplify the DAO with Spring and Java Generics
1. Overview
2. The Hibernate and JPA DAOs
3. Injecting this DAO
4. Conclusion
Transactions with Spring 3 and JPA
1. Overview
2. Configure Transactions without XML
3. Configure Transactions with XML
4. The @TransactionalAnnotation
5. Potential Pitfalls
6. Conclusion
-
8/10/2019 Persistence With Spring eBook
5/45
5
Spring with Maven
1. Overview
This sectionwill discuss how to setup Spring with Mavenand will go over specificusecases of using Spring dependencies. The latest Spring releases can be foundonMaven Central.
2. Basic Maven Spring Dependencies
Spring was designed to be modular and flexible the basic Spring container can beused in a variety of scenarios, without including any of the more advanced functionalitythat the framework has to offer. A very basic Maven setup will only have to use thespring-contextdependency:
3.2.5.RELEASE
org.springframework
spring-context${org.springframework.version}
runme
This dependency spring-context defines the actual Spring Injection Container andhas a small number of dependencies: spring-core, spring-expression, spring-aopandspring-beans. These augment the container by enabling support for some of the coreSpring technologies: the Core Spring utilities, the Spring Expression Language(SpEL), theAspect Oriented Programmingsupport and the JavaBeans mechanism.
Note the runtimescopeis used when defining the spring-contextdependency thiswill make sure that there are no compile time dependencies on any Spring specific APIs.For more advanced usecases the runtimescope may be removed from some selectedSpring dependencies, but for simpler projects, there is no need to compile againstSpringto make full use of the framework.
Also note that, starting with Spring 3.2, the CGLIB dependnecy(now upgraded toCGLIB 3.0) has been repackaged (the all net.sf.cglib package is now
http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.springframework%22http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.springframework%22http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.springframework%22http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/expressions.htmlhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-introductionhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-definitionhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-definitionhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-introductionhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/expressions.htmlhttp://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.springframework%22http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.springframework%22 -
8/10/2019 Persistence With Spring eBook
6/45
6
org.springframework.cglib) and inlined directly within the spring-core JAR (see the JIRAfor additional details), so there is no need to define it explicitly.
3. Spring Persistence with Maven
In addition to the core Spring dependencies shown above, the principal Springpersistence dependency is spring-orm:
org.springframework
spring-orm
${org.springframework.version}
This brings in Hibernate and JPA support such as HibernateTemplateand JpaTemplate as well as the a few additional, persistence related dependencies: spring-jdbcandspring-tx. The JDBC Data Access library defines the Spring JDBC supportas well as theJdbcTemplate, and spring-txrepresents the extremely flexible Transaction Management
Abstractionin Spring.
4. Spring MVC with Maven
To use the Spring Web and Servlet support, there are two dependencies that need to beincluded in the pom, again in addition to the core dependencies from above:
org.springframework
spring-web
${org.springframework.version}
org.springframework
spring-webmvc
${org.springframework.version}
The spring-webdependency contains common web specific utilities for both Servlet andPortlet environments, while spring-webmvcenables the MVC supportfor Servletenvironments. Since spring-webmvchas spring-webas a dependency, explicitly definingspring-webis not required when using spring-webmvc.
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.htmlhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.htmlhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/jdbc.htmlhttps://jira.springsource.org/browse/SPR-9669 -
8/10/2019 Persistence With Spring eBook
7/45
7
5. Spring Security with Maven
Security Maven dependenciesare discussed in depth in the Spring Security withMavenarticle.
6. Spring Test
The Spring Test Framework can be included in the project via the followingdependency:
org.springframework
spring-test
${spring.version}
test
As of Spring 3.2, the Spring MVC Test project, which started as a standalone projectavailable on github, has been included into the core Test Framework; this means thatSpring 3.2 applications should simply use the spring-testdependency.
For applications still using Spring 3.1 and below, the older standalone Mavendependency still exists and can be usedfor almost identical results. The dependency isnot on Maven Central however, so using it will require adding a custom repository to thepom of the project.
7. Using Milestones
The release version of Spring are hosted on Maven Central. However, if a project needsto use milestone versions, then a custom Spring repository needs to be added to thepom:
repository.springframework.maven.milestone
Spring Framework Maven Milestone Repository
hp://maven.springframework.org/milestone
http://maven.springframework.org/milestonehttps://github.com/SpringSource/spring-test-mvc#readmehttps://github.com/SpringSource/spring-test-mvchttp://www.baeldung.com/spring-security-with-mavenhttp://www.baeldung.com/spring-security-with-maven -
8/10/2019 Persistence With Spring eBook
8/45
8
One this repository has been defined, the project can define dependencies such as:
org.springframework
spring-core
3.2.0.RC2
8. Using Snapshots
Similar to milestons, snapshots are hosted in a custom repository:
repository.springframework.maven.snapshot
Spring Framework Maven Snapshot Repository hp://maven.springframework.org/snapshot
Once the SNAPSHOT repository is enabled in the pom, the following dependencies canbe referenced:
org.springframework
spring-core
3.3.0.BUILD-SNAPSHOT
And even:
org.springframework
spring-core
4.4.0.BUILD-SNAPSHOT
9. Conclusion
This section discusses the practical details of using Spring with Maven. The Mavendependencies presented here are of course some of the major ones, and there areseveral others that may be worth mentioning and have not yet made the cut.Nevertheless this should be a good starting point for using Spring in a project.
http://maven.springframework.org/snapshot -
8/10/2019 Persistence With Spring eBook
9/45
9
Hibernate 3 with Spring
1. Overview
Lets jump straight into our first practical usecase - for this section, well focus onsetting up Hibernate 3 with Spring. Well look at how to use both XML and Javaconfiguration to set up Spring 3 with Hibernate 3 and MySQL.
2. Java Spring Configuration for Hibernate 3
Setting up Hibernate 3 with Spring and Java config is straightforward:
import java.ul.Properes;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotaon.Autowired;
import org.springframework.context.annotaon.Bean;
import org.springframework.context.annotaon.ComponentScan;
import org.springframework.context.annotaon.Configuraon;
import org.springframework.context.annotaon.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotaon.PersistenceExceponTranslaonPostProcessor;
import org.springframework.orm.hibernate3.HibernateTransaconManager;
import org.springframework.orm.hibernate3.annotaon.AnnotaonSessionFactoryBean;
import org.springframework.transacon.annotaon.EnableTransaconManagement;
import com.google.common.base.Precondions;
@Configuraon
@EnableTransaconManagement
@PropertySource({ "classpath:persistence-mysql.properes" })
@ComponentScan({ "org.baeldung.spring.persistence" })
public classPersistenceConfig {
@Autowired
privateEnvironment env;
@Bean
publicAnnotaonSessionFactoryBean sessionFactory() {
AnnotaonSessionFactoryBean sessionFactory = new AnnotaonSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
-
8/10/2019 Persistence With Spring eBook
10/45
10
sessionFactory.setPackagesToScan(newString[] { "org.baeldung.spring.persistence.model"
});
sessionFactory.setHibernateProperes(hibernateProperes());
returnsessionFactory;
}
@Bean
public DataSource restDataSource() {
BasicDataSource dataSource = newBasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
returndataSource;
}
@Bean
@Autowired
publicHibernateTransaconManager transaconManager(SessionFactory sessionFactory) {
HibernateTransaconManager txManager = newHibernateTransaconManager();
txManager.setSessionFactory(sessionFactory);
returntxManager;
}
@Bean
publicPersistenceExceponTranslaonPostProcessor exceponTranslaon() { return newPersistenceExceponTranslaonPostProcessor();
}
Properes hibernateProperes() {
return newProperes() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
}
};
}
}
Compared to the XML Configuration described next there is a small difference in theway one bean in the configuration access another. In XML there is no differencebetween pointing to a bean or pointing to a bean factory capable of creatingthat bean. Since the Java configuration is type-safe pointing directly to the bean
-
8/10/2019 Persistence With Spring eBook
11/45
11
factory is no longer an option we need to retrieve the bean from the bean factorymanually:
txManager.setSessionFactory(sessionFactory().getObject());
3. XML Spring Configuration for Hibernate 3
Similarly, we can set upHibernate 3 with XML configas well:
${hibernate.hbm2ddl.auto}
${hibernate.dialect}
http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/contexthttp://www.w3.org/2001/XMLSchema-instancehttp://www.springframework.org/schema/beans -
8/10/2019 Persistence With Spring eBook
12/45
12
Then, this XML file is bootstrapped into the Spring context using a @Configurationclass:
@Configuraon
@EnableTransaconManagement
@ImportResource({ "classpath:persistenceConfig.xml" })
public classPersistenceXmlConfig {
//
}
For both types of configuration, the JDBC and Hibernate specific properties are stored ina properties file:
# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate_dev?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
4. Spring, Hibernate and MySQL
The example above uses MySQL 5 as the underlying database configured withHibernate however, Hibernate supports several underlying SQL Databases.
4.1. The DriverThe Driver class name is configured via the jdbc.driverClassNamepropertyprovided to the DataSource.
In the example above, it is set to com.mysql.jdbc.Driverfrom the mysql-connector-javadependency we defined in the pom, at the start of the section.
https://community.jboss.org/wiki/SupportedDatabases2 -
8/10/2019 Persistence With Spring eBook
13/45
13
4.2. The Dialect
The Dialect is configured via the hibernate.dialectpropertyprovided to the
Hibernate SessionFactory.
In the example above, this is set to org.hibernate.dialect.MySQL5Dialectas we areusing MySQL 5 as the underlying Database. There are several other dialectssupporting MySQL:
org.hibernate.dialect.MySQL5InnoDBDialect for MySQL 5.x with theInnoDB storage engine
org.hibernate.dialect.MySQLDialect for MySQL prior to 5.x org.hibernate.dialect.MySQLInnoDBDialect for MySQL prior to 5.x with
the InnoDB storage engine
org.hibernate.dialect.MySQLMyISAMDialect for all MySQL versions withthe ISAM storage engine
Hibernate supports SQL Dialectsfor every supported Database.
5. Usage
At this point, Hibernate 3 is fully configured with Spring and we caninject the rawHibernateSessionFactorydirectly whenever we need to:
public abstract classFooHibernateDAO{
@Autowired
SessionFactory sessionFactory;
...
protectedSession getCurrentSession(){
returnsessionFactory.getCurrentSession();
}
}
6. Maven
To add the Spring Persistence dependencies to the pom, please see the >> Spring withMaven example well need to define both spring-contextand spring-orm.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/session-configuration.html#configuration-optional-dialects -
8/10/2019 Persistence With Spring eBook
14/45
14
Continuing to Hibernate 3, the Maven dependencies are simple:
org.hibernate
hibernate-core
3.6.10.Final
Then, to enable Hibernate to use its proxy model, we needjavassistas well:
org.javassist
javassist
3.18.1-GA
Were going to use MySQL as our DB for this section, so well also need:
mysql
mysql-connector-java
5.1.28
runme
And finally, we will not be using the Spring datasource implementation theDriverManagerDataSource; instead well use a production ready connection poolsolution Tomcat JDBC Connection Pool:
org.apache.tomcat
tomcat-dbcp
7.0.47
7. Conclusion
In this example, we configured Hibernate 3 with Spring both with Java and XMLconfiguration. The implementation of this simple project can be found in the githubproject this is an Eclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-hibernate3#readmehttps://github.com/eugenp/tutorials/tree/master/spring-hibernate3#readmehttps://github.com/eugenp/tutorials/tree/master/spring-hibernate3#readmehttps://github.com/eugenp/tutorials/tree/master/spring-hibernate3#readme -
8/10/2019 Persistence With Spring eBook
15/45
15
Hibernate 4 with Spring
1. Overview
Now that we have seen how to set up the older Hibernate 3 with Spring, lets see howto do the same with Hibernate 4. Well look at how to configure Spring 3 withHibernate 4 using both Java and XML Configuration. Parts of this process are of coursecommon to the previous section.
2. MavenTo add the Spring Persistence dependencies to the project pom.xml, feel free to jumpback to the first section of this eBook:>> Spring with Maven
Continuing with Hibernate 4, the Maven dependencies are simple:
org.hibernate
hibernate-core
4.3.0.Final
Then, to enable Hibernate to use its proxy model, we need javassist as well:
org.javassist
javassist
3.18.1-GA
And since were going to use MySQL for thissection, well also need:
mysql
mysql-connector-java
5.1.28
runme
-
8/10/2019 Persistence With Spring eBook
16/45
16
And finally, we are using a proper connection poolinstead of the dev-only Springimplementation the DriverManagerDataSource. Were using here the Tomcat JDBCConnection Pool:
org.apache.tomcat tomcat-dbcp
7.0.47
3. Java Spring Configuration for Hibernate 4
To use Hibernate 4 in a project, a few things have changed on the configuration sidewhen moving from a Hibernate 3 setup.
The main aspect that is different when upgrading from Hibernate 3 is the way to createthe SessionFactorywith Hibernate 4.
This is now done by using the LocalSessionFactoryBeanfrom the hibernate4package which replaces the older AnnotationSessionFactoryBeanfrom the hibernate3package. The new FactoryBeanhas the same responsibility it bootstraps theSessionFactoryfrom annotation scanning. This is neccessary because, starting withHibernate 3.6, the oldAnnotationConfigurationwas mergedinto Configurationand sothe new Hibernate 4 LocalSessionFactoryBeanis using this new Configurationmechanism.
It is also worth noting that, in Hibernate 4, the Configuration.buildSessionFactorymethod and mechanism have also been deprecatedin favourofConfiguration.buildSessionFactory(ServiceRegistry) which theSpring LocalSessionFactoryBeanis not yet using.
The Spring Java Configuration for Hibernate 4:
importjava.ul.Properes;
importjavax.sql.DataSource;
importorg.hibernate.SessionFactory;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
importorg.springframework.beans.factory.annotaon.Autowired; importorg.springframework.context.annotaon.Bean;
importorg.springframework.context.annotaon.ComponentScan;
importorg.springframework.context.annotaon.Configuraon;
importorg.springframework.context.annotaon.PropertySource;
importorg.springframework.core.env.Environment;
importorg.springframework.dao.annotaon.PersistenceExceponTranslaonPostProcessor;
importorg.springframework.orm.hibernate4.HibernateTransaconManager;
http://stackoverflow.com/questions/8621906/is-buildsessionfactory-deprecated-in-hibernate-4https://hibernate.atlassian.net/browse/HHH-5991https://hibernate.atlassian.net/browse/HHH-5375http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.htmlhttp://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html -
8/10/2019 Persistence With Spring eBook
17/45
17
importorg.springframework.orm.hibernate4.LocalSessionFactoryBean;
importorg.springframework.transacon.annotaon.EnableTransaconManagement;
importcom.google.common.base.Precondions;
@Configuraon
@EnableTransaconManagement
@PropertySource({ "classpath:persistence-mysql.properes" })
@ComponentScan({ "org.baeldung.spring.persistence" })
public classPersistenceConfig {
@Autowired
privateEnvironment env;
@Bean
publicLocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory =new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(newString[] {"org.baeldung.spring.persistence.model"});
sessionFactory.setHibernateProperes(hibernateProperes());
returnsessionFactory;
}
@Bean
publicDataSource restDataSource() {
BasicDataSource dataSource =newBasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url")); dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
returndataSource;
}
@Bean
@Autowired
public HibernateTransaconManager transaconManager(SessionFactory sessionFactory) {
HibernateTransaconManager txManager = newHibernateTransaconManager();
txManager.setSessionFactory(sessionFactory);
returntxManager;
}
@Bean
publicPersistenceExceponTranslaonPostProcessor exceponTranslaon() {
return new PersistenceExceponTranslaonPostProcessor();
}
-
8/10/2019 Persistence With Spring eBook
18/45
18
Properes hibernateProperes() {
return newProperes() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_idenfiers", "true");
}
};
}
}
4. XML Spring Configuration for Hibernate 4
Simillary, Hibernate 4 can be configured with XMLas well:
${hibernate.hbm2ddl.auto}
${hibernate.dialect}
http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/contexthttp://www.w3.org/2001/XMLSchema-instancehttp://www.springframework.org/schema/beans -
8/10/2019 Persistence With Spring eBook
19/45
19
To bootstrap the XML into the Spring Context, we can use a simple Java Configurationfile if the application is configured with Java configuration:
@Configuraon
@EnableTransaconManagement
@ImportResource({ "classpath:hibernate4Config.xml" })
public class HibernateXmlConfig{
//
}
Alternatively we can simply provide the XML file to the Spring Context, if the overallconfiguration is purely XML.
For both types of configuration, the JDBC and Hibernate specific properties are stored in
a properties file:
# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate_dev?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
5. Spring, Hibernate and MySQL
The Drivers and Dialects supported by Hibernate >> have been extensively discussedfor Hibernate 3 and everything still applies for Hibernate 4 as well.
-
8/10/2019 Persistence With Spring eBook
20/45
20
6. Usage
At this point, Hibernate 4 is fully configured with Spring and we can inject the rawHibernate SessionFactorydirectly whenever we need to:
public abstract classBarHibernateDAO{
@Autowired
SessionFactory sessionFactory;
...
protectedSession getCurrentSession(){
returnsessionFactory.getCurrentSession();
} }
An important note here is that this is now the recommended way to use the HibernateAPI the older HibernateTemplateis no longer included in the neworg.springframework.orm.hibernate4package as it shouldnt be used with Hibernate 4.
7. Conclusion
In this example, we configured Spring with Hiberate 4 both with Java and XMLconfiguration.
The implementation of this simple project can be found in the github project this is anEclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-hibernate4#readme -
8/10/2019 Persistence With Spring eBook
21/45
21
Spring 3 and JPA with Hibernate
1. Overview
This sectionshows how to set up Spring with JPA, using Hibernate as a persistenceprovider.
For a step by step introduction about setting up the Spring context using Java basedconfiguration and the basic Maven pom for the project, see this article.
2. The JPA Spring Configuration with Java
To use JPA in a Spring project, the EntityManagerneeds to be set up.
This is the main part of the configuration and it is done via a Spring factory bean either the simpler LocalEntityManagerFactoryBeanor the more flexibleLocalContainerEntityManagerFactoryBean. The latter option is used here, so thatadditional properties can be configured on it:
@Configuraon
@EnableTransaconManagementpublic classPersistenceJPAConfig{
@Bean
publicLocalContainerEntyManagerFactoryBean entyManagerFactoryBean() {
LocalContainerEntyManagerFactoryBean em = new
LocalContainerEntyManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(newString[] { "org.baeldung.persistence.model" });
JpaVendorAdapter vendorAdapter = newHibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperes(addionalProperes());
returnem;
}
@Bean
publicDataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/ -
8/10/2019 Persistence With Spring eBook
22/45
22
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
dataSource.setUsername( "tutorialuser" );
dataSource.setPassword( "tutorialmy5ql" );
returndataSource;
}
@Bean
publicPlaormTransaconManager transaconManager(EntyManagerFactory emf){
JpaTransaconManager transaconManager = new JpaTransaconManager();
transaconManager.setEntyManagerFactory(emf);
returntransaconManager;
}
@Bean
publicPersistenceExceponTranslaonPostProcessor exceponTranslaon(){
return newPersistenceExceponTranslaonPostProcessor();}
Properes addionalProperes() {
return new Properes() {
{ // Hibernate Specific:
setProperty("hibernate.hbm2ddl.auto", "create-drop");
setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
}
};
}
}
Also, note that, before Spring 3.2, cglibhad to be on the classpath for Java@Configurationclasses to work; to better understand the need for cglibas adependency, see this discussion about the cglib artifact in Spring.
3. The JPA Spring Configuration with XML
The same Spring Configuration with XML:
-
8/10/2019 Persistence With Spring eBook
23/45
23
hp://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
create-drop
org.hibernate.dialect.MySQL5Dialect
There is a relatively small difference between the way Spring is configured in XML andthe 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 aredifferent, the compiler doesnt allow it, and so the EntityManagerFactory is firstretrieved from its bean factory and then passed to the transaction manager:
txManager.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
http://www.springframework.org/schema/tx/spring-tx-3.2.xsdhttp://mysql//localhost:3306/spring_jpahttp://mysql//localhost:3306/spring_jpahttp://www.springframework.org/schema/tx/spring-tx-3.2.xsd -
8/10/2019 Persistence With Spring eBook
24/45
24
4. Going full XML-less
Usually JPA defines a persistence unit through the META-INF/persistence.xmlfile.Starting with Spring 3.1, the persistence.xmlis no longer necessary theLocalContainerEntityManagerFactoryBeannow supports a packagesToScanproperty
where the packages to scan for @Entityclasses can be specified.
This file was the last piece of XML to be removed now, JPA can be fully set up withno XML.
4.1. The JPA Properties
JPA properties would usually be specified in the persistence.xmlfile; alternatively, theproperties can be specified directly to the entity manager factory bean:
factoryBean.setJpaProperties( this.additionalProperties() );
As a side-note, if Hibernate would be the persistence provider, then this would be theway to specify Hibernate specific properties.
5. The Maven configuration
In addition to Spring Core and persistence dependencies show in detail in the>>
Spring with Maven section we also need to define JPA and Hibernate in the project,
as well as a MySQL connector:
org.hibernate
hibernate-entymanager
4.2.8.Final
runme
mysql
mysql-connector-java
5.1.27
runme
Note that the MySQL dependency is included as a reference a driver is needed toconfigure the datasource, but any Hibernate supported databasewill do.
http://community.jboss.org/wiki/SupportedDatabases2http://community.jboss.org/wiki/SupportedDatabases2 -
8/10/2019 Persistence With Spring eBook
25/45
25
6. Conclusion
This sectionillustrated how to configure JPA with Hibernate in Springusing bothXML and Java configuration.
We also discussed how to get rid of the last piece of XML usually associated with JPA the persistence.xml. The final result is a lightweight, clean DAO implementation, withalmost no compile-time reliance on Spring.
The implementation of this Spring JPA Sectioncan be found in the github project thisis an Eclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-jpa#readmehttps://github.com/eugenp/tutorials/tree/master/spring-jpa#readme -
8/10/2019 Persistence With Spring eBook
26/45
26
The Persistence Layer with SpringData JPA
1. Overview
This section will focus on the configuration and implementation of the persistence layerwith Spring 3.1, JPA and Spring Data. For a step by step introduction about settingup the Spring context using Java based configuration and the basic Maven pom for theproject, see this article.
2. No More DAO implementations
As we will discuss in a later section, >> the DAO layer usually consists of a lot ofboilerplate code that can and should be simplified. The advantages of such asimplification are many fold: a decrease in the number of artifacts that need to bedefined and maintained, simplification and consistency of data access patterns andconsistency of configuration.
Spring Data takes this simplification one step forward and makes it possible to remove
the DAO implementations entirely the interface of the DAO is now the onlyartifact that need to be explicitly defined.
3. The Spring Data managed DAO
In order to start leveraging the Spring Data programming model with JPA, a DAOinterface needs to extend the JPA specific Repositoryinterface - JpaRepository inSprings interface hierarchy. This will enable Spring Data to find this interface and
automatically create an implementation for it.
Also, by extending the interface we get most if not all relevant CRUD generic methodsfor standard data access available in the DAO.
http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/ -
8/10/2019 Persistence With Spring eBook
27/45
27
4. Defining custom access method and queries
As discussed, by implementing one of the Repositoryinterfaces, the DAO will alreadyhave some basic CRUD methods (and queries) defined and implemented. To definemore specific access methods, Spring JPA supports quite a few options you can either
simplydefine a new methodin the interface, or you can provide the actual JPQqueryby using the @Queryannotation.
A third option to define custom queries is to make use of JPA Named Queries, but thishas the disadvantage that it either involves XML or burdening the domain class with thequeries.
In addition to these, Spring Data introducesa more flexible and convenient API, similarto the JPA Criteria API, only more readable and reusable. The advantages of this APIwill become more pronounced when dealing with a large number of fixed queries thatcould potentially be more concisely expressed through a smaller number of reusableblocks that keep occurring in different combinations.
4.1. Automatic Custom Queries
When Spring Data creates a new Repositoryimplementation, it analyses all themethods defined by the interfaces and tries to automatically generate queries from themethod name. While this has limitations, it is a very powerful and elegant way ofdefining new custom access methods with very little effort.
For example, if the managed entity has a name field (and the Java Bean standardgetter and setter for that field), defining the findByNamemethodin the DAOinterface will automatically generate the correct query:
publicinterface IFooDAO extendsJpaRepository< Foo, Long >{
Foo findByName( final Stringname );
}
This is a relatively simple example; a much larger set of keywordsis supported byquery creation mechanism.
In the case that the parser cannot match the property with the domain object field, thefollowing exception is thrown:
Java.lang.IllegalArgumentException: No property namfound for type classorg.rest.model.Foo
http://static.springsource.org/spring-data/data-jpa/docs/1.1.x/reference/html/#jpa.query-methods.query-creationhttp://blog.springsource.org/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/ -
8/10/2019 Persistence With Spring eBook
28/45
28
4.2. Manual Custom Queries
In addition to deriving the query from the method name, a custom query can be
manually specified with the method level @Queryannotation.
For even more fine grained control over the creation of queries, such as using namedparameters or modifying existing queries, the referenceis a good place to start.
5. Spring Data transaction configuration
The actual implementation of the Spring Data managed DAO SimpleJpaRepositoryuses annotations to define and configure transactions. A read only @Transactionalannotation is used at the class level, which is then overridden for the non read-onlymethods. The rest of the transaction semantics are default, but these can be easilyoverridden manually per method.
5.1. Exception Translation without the template
One of the responsibilities of Spring ORM templates (JpaTemplate, HibernateTemplate)is exception translation translating JPA exceptions which tie the API to JPA to
Springs DataAccessExceptionhierarchy.
Without the template to do that, exception translation can still be enabled byannotating the DAOs with the @Repositoryannotation. That, coupled with a Springbean postprocessor will advice all @Repositorybeans with all the implementations ofPersistenceExceptionTranslatorfound in the Container to provide exception translationwithout using the template.
The fact that exception translation is indeed active can easily be verified with anintegration test:
@Test( expected = DataAccessExcepon.class )
public void whenAUniqueConstraintIsBroken_thenSpringSpecificExceponIsThrown(){
String name = "randomName";
service.save( newFoo( name ) );
service.save( newFoo( name ) );
}
Exception translation is done through proxies; in order for Spring to be able to create
http://static.springsource.org/spring-data/data-jpa/docs/1.1.x/reference/html/#jpa.named-parameters -
8/10/2019 Persistence With Spring eBook
29/45
29
proxies around the DAO classes, these must not be declared final.
6. Spring Data Configuration
To activate the Spring JPA repository support, the jpanamespaceis defined and usedto specify the package where to DAO interfaces are located:
At this point, there is no equivalent Java based configuration support for it is howeverin the works.
7. The Spring Java or XML configuration
The previous section of the series already discussed in great detail how to >> configureJPA in Spring 3. Spring Data also takes advantage of the Spring support for the JPA@PersistenceContextannotation which it uses to wire the EntityManagerinto the Springfactory bean responsible with creating the actual DAO implementations JpaRepositoryFactoryBean.
In addition to the already discussed configuration, there is one last missing piece
including the Spring Data XML configuration in the overall persistence configuration:
@Configuraon
@EnableTransaconManagement
@ImportResource( "classpath*:*springDataConfig.xml" )
public classPersistenceJPAConfig{
...
}
https://jira.springsource.org/browse/DATAJPA-69http://www.springframework.org/schema/data/jpa/spring-jpa.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/data/jpahttp://www.w3.org/2001/XMLSchema-instancehttp://www.springframework.org/schema/beans -
8/10/2019 Persistence With Spring eBook
30/45
30
8. The Maven configuration
In addition to the Maven configuration for JPA defined in a >> previous section thespring-data-jpadependency is added:
org.springframework.data
spring-data-jpa
1.4.3.RELEASE
9. Conclusion
This section covered the configuration and implementation of the persistence layer withSpring 3.1, JPA 2 and Spring JPA (part of the Spring Data umbrella project), using bothXML and Java based configuration. The various method of defining more advancedcustom queriesare discussed, as well as configuration with the new jpanamespaceand transactional semantics. The final result is a new and elegant take ondata access with Spring, with almost no actual implementation work.
You can check out the full implementation in the github project.
https://github.com/eugenp/REST#readme -
8/10/2019 Persistence With Spring eBook
31/45
31
The DAO with Spring 3 and Hibernate
1. Overview
This section will show how to implement the DAO with Spring and Hibernate. Forthe core Hibernate configuration, see the sections about >> Hibernate 3 and >>Hibernate 4 with Spring.
2. No More Spring Templates
Starting Spring 3.0 and Hibernate 3.0.1, the Spring HibernateTemplateis nolonger necessaryto manage the Hibernate Session. It is now possible to make use ofcontextual sessions sessions managed directly by Hibernateand activethroughout the scope of a transaction.
As a consequence, it is now best practice to use the Hibernate API directly instead ofthe HibernateTemplate, which will effectively decouple the DAO layer implementationfrom Spring entirely.
2.1. Exception Translation without the HibernateTemplate aliveand well
Exception Translation was one of the responsibilities of HibernateTemplate translatingthe low level Hibernate exceptions to higher level, generic Spring exceptions.
Without the template, this mechanism is still enabled and activefor all the DAOsannotated with the @Repositoryannotation. Under the hood, this uses a Spring beanpostprocessor that will advice all @Repositorybeans with all thePersistenceExceptionTranslatorfound in the Spring context.
One thing to remember is that exception translation is done through proxies; in orderfor Spring to be able to create proxies around the DAO classes, these must not bedeclared final.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/architecture.html#architecture-current-session -
8/10/2019 Persistence With Spring eBook
32/45
32
2.2. Hibernate Session management without the Template
When Hibernate support for contextual sessions came out, the HibernateTemplateessentially became obsolete; in fact, the javadoc of the class has been updated withthis advice (bold from the original):
NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can also be codedin plain Hibernate style. Hence, for newly started projects, consider adopting thestandard Hibernate3 style of coding data access objects instead, based on {@linkorg.hibernate.SessionFactory#getCurrentSession()}.
3. The DAO
Well start with the base DAO -an abstract, parametrized DAOwhich supports the
common generic operations and is meant to be extended for each entity:
public abstract classAbstractHibernateDAO< T extendsSerializable >{
privateClass< T > clazz;
@Autowired
privateSessionFactory sessionFactory;
public voidsetClazz( finalClass< T > clazzToSet ){
clazz = clazzToSet;
}
publicT findOne( final long id ){ return (T) getCurrentSession().get( clazz, id );
}
public List< T > findAll(){
returngetCurrentSession()
.createQuery( "from " + clazz.getName() ).list();
}
public voidsave( finalT enty ){
getCurrentSession().persist( enty );
}
publicT update( finalT enty ){
return(T) getCurrentSession().merge( enty );
}
public voiddelete( finalT enty ){
getCurrentSession().delete( enty );
}
-
8/10/2019 Persistence With Spring eBook
33/45
33
public voiddeleteById( final longid ){
finalT enty = findOne( id);
delete( enty );
}
protected final Session getCurrentSession(){
returnsessionFactory.getCurrentSession();
}
}
A few aspects are interesting here as discussed, the abstract DAO does not extendany Spring template (such as HibernateTemplate). Instead, the HibernateSessionFactory is injected directly in the DAO, and will have the role of the mainHibernate API, through the contextual Sessionit exposes:
this.sessionFactory.getCurrentSession();
Also, note that the Classof the entity is passed in the constructor to be used in thegeneric operations.
Now, lets look at an example implementation of this DAO, for a Fooentity:
@Repository
public classFooDAO extendsAbstractHibernateDAO< Foo >implementsIFooDAO{
publicFooDAO(){
setClazz(Foo.class );
}
}
4. Conclusion
This section covered the configuration and implementation of the persistence layer withHibernate 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 aspossible pitfalls of configuring Spring to manage transactions and the HibernateSession. The final result is a lightweight, clean DAO implementation, with almost nocompile-time reliance on Spring.
The implementation of this simple project can be found in the github project this is anEclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-hibernate4#readme -
8/10/2019 Persistence With Spring eBook
34/45
34
The DAO with JPA and Spring
1. Overview
This section will show how to implement the DAO with Spring and JPA. For thecore JPA configuration, see >> the article about JPA with Spring.
2. No More Spring Templates
Starting with Spring 3.1, the JpaTemplateand the corresponding JpaDaoSupporthavebeendeprecated in favor of using the native Java Persistence API.
Also, both of these classes are only relevant for JPA 1 (from the JpaTemplatejavadoc):
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 directlyinstead of the JpaTemplate.
2.1. Exception Translation without the Template
One of the responsibilities of JpaTemplatewas exception translation translatingthe low level exceptions into higher level, generic Spring exceptions.
Without the template, exception translation is still enabled and fully functionalfor all DAOs annotated with @Repository. Spring implements this with a beanpostprocessor which will advice all @Repositorybeans with all thePersistenceExceptionTranslatorfound in the Container.
It is also important to note that the exception translation mechanism usesproxies in order for Spring to be able to create proxies around the DAO classes,these must not be declared final.
3. The DAO
-
8/10/2019 Persistence With Spring eBook
35/45
35
First, well implement the base layer for all the DAOs an abstract class using genericsand designed to be extended:
public abstract classAbstractJpaDAO< T extendsSerializable > {
private Class< T > clazz;
@PersistenceContext
EntyManager entyManager;
public final voidsetClazz( Class< T > clazzToSet ){
this.clazz = clazzToSet;
}
publicT findOne( longid ){
return entyManager.find( clazz, id );
}
public List< T > findAll(){
returnentyManager.createQuery( "from " + clazz.getName() )
.getResultList();
}
public voidcreate( T enty ){
entyManager.persist( enty );
}
publicT update( T enty ){
returnentyManager.merge( enty );
}
public voiddelete( T enty ){
entyManager.remove( enty );
}
public voiddeleteById( longentyId ){
T enty = findOne( entyId );
delete( enty );
}
}
The main interesting aspect here is the way the EntityManageris injected usingthe standard @PersistenceContextannotation. Under the hood, this is handled by thePersistenceAnnotationBeanPostProcessor which processes the annotation, retrievesthe JPA entity manager from the contains and injects it.
The persistence post processor is either created explicitly by defining it in theconfiguration, or automatically, by defining context:annotation-configorcontext:component-scanin the namespace config.
-
8/10/2019 Persistence With Spring eBook
36/45
36
Also, note that the entity Classis passed in the constructor to be used in the genericoperations:
@Repository
public classFooDAO extends AbstractJPADAO< Foo > implementsIFooDAO{
publicFooDAO(){
setClazz(Foo.class);
}
}
4. Conclusion
This sectionillustrated how to set up a DAO layer with Spring and JPA, using bothXML and Java based configuration. We also discussed why not to use the JpaTemplateand how to replace it with the EntityManager. The final result is a lightweight, clean
DAO implementation, with almost no compile-time reliance on Spring.
The implementation of this simple project can be found in the github project this is anEclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-jpa#readmehttps://github.com/eugenp/tutorials/tree/master/spring-jpa#readme -
8/10/2019 Persistence With Spring eBook
37/45
37
Simplify the DAO with Spring and JavaGenerics
1. Overview
This section will focus on simplifying the DAO layerby using a single, generifiedData Access Object for all entities in the system, which will result in elegant dataaccess, with no unnecessary clutter or verbosity.
2. The Hibernate and JPA DAOs
Most production codebases have some kind of DAO layer. Usually the implementationranges from multiple classes with no abstract base class to some kind of generifiedclass. However, one thing is consistent there is always more then one most likely,there is a one to one relation between the DAOs and the entities in the system.
Also, depending on the level of generics involved, the actual implementations can varyfrom heavily duplicated code to almost empty, with the bulk of the logic grouped in abase abstract class.
These multiple implementations can usually be replaced by a single parametrizedDAOused in such no functionality is lost by taking full advantage of the type safetyprovided by Java Generics.
Two implementationsof this concept are presented next, one for a Hibernatecentric persistence layer and the other focusing on JPA. These implementation are byno means complete only some data access methods are included, but they can beeasily be made more thorough.
2.1. The Abstract Hibernate DAO
public abstract classAbstractHibernateDao< T extendsSerializable > {
privateClass< T > clazz;
@Autowired
-
8/10/2019 Persistence With Spring eBook
38/45
38
SessionFactory sessionFactory;
public final voidsetClazz( Class< T > clazzToSet ){
this.clazz = clazzToSet;
}
public T findOne(longid ){
return(T) getCurrentSession().get( clazz, id );
}
publicList< T > findAll(){
returngetCurrentSession().createQuery( "from " + clazz.getName() ).list();
}
public voidcreate( T enty ){
getCurrentSession().persist( enty );
}
public voidupdate( T enty ){getCurrentSession().merge( enty );
}
public voiddelete( T enty ){
getCurrentSession().delete( enty );
}
public voiddeleteById( longentyId ){
T enty = findOne( entyId );
delete( enty );
}
protected finalSession getCurrentSession(){
returnsessionFactory.getCurrentSession();
}
}
The DAO uses the Hibernate API directly, without relying on any Spring templates (such as HibernateTemplate). Using of templates, as well as management of theSessionFactorywhich is autowired in the DAO were covered in the>> Hibernate DAOsection.
2.2. The Generic Hibernate DAO
Now that the abstract DAO is done, we can implement it just once the generic DAOimplementation will become the only implementationneeded:
@Repository
-
8/10/2019 Persistence With Spring eBook
39/45
39
@Scope( BeanDefinion.SCOPE_PROTOTYPE )
public classGenericHibernateDao< T extendsSerializable >
extendsAbstractHibernateDao< T >implementsIGenericDao< T >{
//
}
First, note that the generic implementation is itself parametrized allowing the clientto choose the correct parameter in a case by case basis. This will mean that the clientsgets all the benefits of type safety without needing to create multiple artifacts for eachentity.
Second, notice the prototype scopeof these generic DAO implementation. Using thisscope means that the Spring container will create a new instance of the DAO each timeit is requested (including on autowiring). That will allow a service to use multiple DAOswith different parameters for different entities, as needed.
The reason this scope is so important is due to the way Spring initializes beans in thecontainer. Leaving the generic DAO without a scope would mean using the defaultsingleton scope, which would lead to a single instance of the DAO living in thecontainer. That would obviously be majorly restrictive for any kind of more complexscenario.
The IGenericDaois simply an interface for all the DAO methods, so that we can injectour implementation with Spring in (or in whatever is needed):
public interfaceIGenericDao {
T findOne(final longid);
List findAll();
void create(final T enty);
T update(final T enty);
voiddelete(finalT enty);
voiddeleteById(final longentyId);
}
2.3. The Abstract JPA DAO
public abstract classAbstractJpaDao< TextendsSerializable > {
privateClass< T > clazz;
-
8/10/2019 Persistence With Spring eBook
40/45
40
@PersistenceContext
EntyManager entyManager;
public voidsetClazz( Class< T > clazzToSet ){
this.clazz = clazzToSet;
}
publicT findOne( Long id ){
returnentyManager.find( clazz, id );
}
public List< T > findAll(){
returnentyManager.createQuery( "from " + clazz.getName() )
.getResultList();
}
public voidsave( T enty ){
entyManager.persist( enty ); }
public voidupdate( T enty ){
entyManager.merge( enty );
}
public void delete( T enty ){
entyManager.remove( enty );
}
public voiddeleteById( Long entyId ){
T enty = getById( entyId ); delete( enty );
}
}
Similar to the Hibernate DAO implementation, the Java Persistence API is used heredirectly, again not relying on the now deprecatedSpring JpaTemplate.
2.4. The Generic JPA DAO
Similar to the the Hibernate implementation, the JPA Data Access Object isstraighforward as well:
@Repository
@Scope( BeanDefinion.SCOPE_PROTOTYPE )
public classGenericJpaDao< T extendsSerializable >
extendsAbstractJpaDao< T > implementsIGenericDao< T >{
-
8/10/2019 Persistence With Spring eBook
41/45
41
//
}
3. Injecting this DAO
There is now a single DAOto be injected by Spring; also, the Classneeds to bespecified:
@Service
class FooServiceimplementsIFooService{
IGenericDao< Foo > dao;
@Autowired
public voidsetDao( IGenericDao< Foo > daoToSet ){
dao = daoToSet;
dao.setClazz( Foo.class );
}
// ...
}
Spring autowires the new DAO insteince using setter injectionso that theimplementation can be customized with the Classobject. After this point, the DAO isfully parametrized and ready to be used by the service.
There are of course other ways that the class can be specified for the DAO viareflection, or even in XML. My preference is towards this simpler solution because of theimproved readability and transparency compared to using reflection.
4. Conclusion
This section discussed the simplification of the Data Access Layerby providing asingle, reusable implementation of a generic DAO. This implementation was presented
in both a Hibernate and a JPA based environment. The result is a streamlinedpersistence layer, with no unnecessary clutter.
For a step by step introduction about setting up the Spring context using Java basedconfiguration and the basic Maven pom for the project, see this article.
http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/ -
8/10/2019 Persistence With Spring eBook
42/45
42
Transactions with Spring 3 and JPA
1. Overview
This sectionwill discuss the right way to configure Spring Transactions , how touse the @Transactionalannotation and common pitfalls.
For a more in depth discussion on the core persistence configuration, check out the>>Spring with JPA section.
There are two distinct ways to configure Transactions annotations and AOP eachwith their own advantages were going to discuss the more common annotationconfighere.
2. Configure Transactions without XML
Spring 3.1 introduces the @EnableTransactionManagementannotationto beused in on @Configurationclasses and enable transactional support:
@Configuraon
@EnableTransaconManagementpublic classPersistenceJPAConfig{
@Bean
public LocalContainerEntyManagerFactoryBean entyManagerFactoryBean(){
...
}
@Bean
publicPlaormTransaconManager transaconManager(){
JpaTransaconManager transaconManager = newJpaTransaconManager();
transaconManager.setEntyManagerFactory(entyManagerFactoryBean().getObject() );
return transaconManager;
}
}
3. Configure Transactions with XML
-
8/10/2019 Persistence With Spring eBook
43/45
43
Before 3.1 or if Java is not an option, here is the XML configuration,using annotation-drivenand the namespace support:
4. The @TransactionalAnnotation
With transactions configured, a bean can now be annotated with @Transactional eitherat the class or method level:
@Service
@Transaconal
public classFooService { ...
}
The annotation supports further configurationas well:
the Propagation Typeof the transaction the Isolation Levelof the transaction a Timeoutfor the operation wrapped by the transaction a readOnlyflag a hint for the persistence provider that the transaction should
be read only
detailed Rollbackconfiguration
5. Potential Pitfalls
5.1. Transactions and Proxies
At a high level, Spring creates proxies for all the classes annotated with@Transactional either on the class or on any of the methods. The proxy allows theframework to inject transactional logic before and after the method being invoked mainly for starting and committing the transaction.
What is important to keep in mind is that, if the transactional bean is implementing aninterface, by default the proxy will be a Java Dynamic Proxy. This means that onlyexternal method calls that come in through the proxy will be intercepted any self-
-
8/10/2019 Persistence With Spring eBook
44/45
44
invocation calls will not start any transaction even if the method is annotatedwith @Transactional.
Another caveat of using proxies is that only public methods should be annotatedwith @Transactional methods of any other visibilities will simply ignore the
annotation silently as these are not proxied.
This article discusses further proxying pitfalsin great detail here.
5.2. Changing the Isolation level
One of the major pitfalls when configuring Spring to work with JPA is that changing theisolation of the transaction semantics will not work JPA does not support customisolation levels. This is a limitation of JPA, not Spring; nevertheless changing the
@Transactionalisolationproperty will result in:
org.springframework.transaction.InvalidIsolationLevelException: Standard JPA doesnot support custom isolation levels use a special JpaDialect for your JPAimplementation
5.3. Read Only Transactions
The readOnlyflagusually generates confusion, especially when working with JPA;
from the javadoc:
This just serves as a hint for the actual transaction subsystem; it will not necessarilycause failure of write access attempts. A transaction manager which cannot interpretthe read-only hint will notthrow an exception when asked for a read-only transaction.
The fact is that it cannot be guaranteedthat an insert or update will not occur whenthe readOnlyflag is set its behavior is vendor dependentwhereas JPA is vendoragnostic.
It is also important to understand that the readOnlyflag is only relevant inside a
transaction; if an operation occurs outside of a transactional context, the flag issimply ignored. A simple example of that would calling a method annotated with:
1 @Transaconal( propagaon = Propagaon.SUPPORTS,readOnly = true)
from a non-transactional context a transaction will not be created and the readOnlyflag will be ignored.
https://jira.springsource.org/browse/SPR-5012http://nurkiewicz.blogspot.ro/2011/10/spring-pitfalls-proxying.html -
8/10/2019 Persistence With Spring eBook
45/45
5.4. Transaction Logging
Transactional related issues can also be better understood by fine-tuning logginginthe transactional packages; the relevant package in Spring is
org.springframework.transaction, which should be configured with a logging level of
TRACE.
6. Conclusion
We covered the basic configuration of transactional semantics using both java and XML,how to use @Transactionaland best practices of a Transactional Strategy. The Springsupport for transactional testingas well as some common JPA pitfallswere alsodiscussed.
The implementation of this simple project can be found in the github project this is anEclipse based project, so it should be easy to import and run as it is.
https://github.com/eugenp/tutorials/tree/master/spring-jpa#readme