The Spring Framework supports integration with Hibernate, Java Persistence API (JPA)and Java Data Objects (JDO) for resource management, data access object(DAO) implementations, and transaction strategies. For example, for Hibernate there isfirst-class support with several convenient IoC features that address many typicalHibernate integration issues. You can configure all of the supported features for O/R(object relational) mapping tools through Dependency Injection. They can participate inSpring’s resource and transaction management, and they comply with Spring’s generictransaction and DAO exception hierarchies. The recommended integration style is to codeDAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Spring’s DAOtemplates is no longer recommended; however, coverage of this style can be found in theSection 39.1, “Classic ORM usage” in the appendices.
Spring adds significant enhancements to the ORM layer of your choice when you createdata access applications. You can leverage as much of the integration support as youwish, and you should compare this integration effort with the cost and risk of buildinga similar infrastructure in-house. You can use much of the ORM support as you would alibrary, regardless of technology, because everything is designed as a set of reusableJavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thusmost examples in this section show configuration inside a Spring container.
Benefits of using the Spring Framework to create your ORM DAOs include:
SessionFactory instances, JDBCDataSourceinstances, transaction managers, and mapped object implementations (if needed). Thisin turn makes it much easier to test each piece of persistence-related code inisolation.SessionFactory instances, JPAEntityManagerFactoryinstances, JDBCDataSource instances, and other related resources. This makes thesevalues easy to manage and change. Spring offers efficient, easy, and safe handling ofpersistence resources. For example, related code that uses Hibernate generally needs touse the same HibernateSession to ensure efficiency and proper transaction handling.Spring makes it easy to create and bind aSession to the current thread transparently,by exposing a currentSession through the HibernateSessionFactory. Thus Springsolves many chronic problems of typical Hibernate usage, for any local or JTAtransaction environment.@Transactional annotation or by explicitly configuring the transaction AOP advice inan XML configuration file. In both cases, transaction semantics and exception handling(rollback, and so on) are handled for you. As discussed below, inResource and transaction management, you can also swap varioustransaction managers, without affecting your ORM-related code. For example, you canswap between local transactions and JTA, with the same full services (such asdeclarative transactions) available in both scenarios. Additionally, JDBC-related codecan fully integrate transactionally with the code you use to do ORM. This is usefulfor data access that is not suitable for ORM, such as batch processing and BLOBstreaming, which still need to share common transactions with ORM operations.![]() | Tip |
|---|---|
For more comprehensive ORM support, including support for alternative databasetechnologies such as MongoDB, you might want to check out theSpring Data suite of projects. If you area JPA user, theGetting Started AccessingData with JPA guide fromhttps://spring.io provides a great introduction. |
This section highlights considerations that apply to all ORM technologies. TheSection 20.3, “Hibernate” section provides more details and also show these features andconfigurations in a concrete context.
The major goal of Spring’s ORM integration is clear application layering, with any dataaccess and transaction technology, and for loose coupling of application objects. Nomore business service dependencies on the data access or transaction strategy, no morehard-coded resource lookups, no more hard-to-replace singletons, no more custom serviceregistries. One simple and consistent approach to wiring up application objects, keepingthem as reusable and free from container dependencies as possible. All the individualdata access features are usable on their own but integrate nicely with Spring’sapplication context concept, providing XML-based configuration and cross-referencing ofplain JavaBean instances that need not be Spring-aware. In a typical Spring application,many important objects are JavaBeans: data access templates, data access objects,transaction managers, business services that use the data access objects and transactionmanagers, web view resolvers, web controllers that use the business services,and so on.
Typical business applications are cluttered with repetitive resource management code.Many projects try to invent their own solutions, sometimes sacrificing proper handlingof failures for programming convenience. Spring advocates simple solutions for properresource handling, namely IoC through templating in the case of JDBC and applying AOPinterceptors for the ORM technologies.
The infrastructure provides proper resource handling and appropriate conversion ofspecific API exceptions to an unchecked infrastructure exception hierarchy. Springintroduces a DAO exception hierarchy, applicable to any data access strategy. For directJDBC, theJdbcTemplate class mentioned in a previous section provides connectionhandling and proper conversion ofSQLException to theDataAccessException hierarchy,including translation of database-specific SQL error codes to meaningful exceptionclasses. For ORM technologies, see the next section for how to get the same exceptiontranslation benefits.
When it comes to transaction management, theJdbcTemplate class hooks in to the Springtransaction support and supports both JTA and JDBC transactions, through respectiveSpring transaction managers. For the supported ORM technologies Spring offers Hibernate,JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well asJTA support. For details on transaction support, see theChapter 17,Transaction Management chapter.
When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle thepersistence technology’s native exception classes. The DAO throws a subclass of aHibernateException,PersistenceException orJDOException depending on thetechnology. These exceptions are all run-time exceptions and do not have to be declaredor caught. You may also have to deal withIllegalArgumentException andIllegalStateException. This means that callers can only treat exceptions as generallyfatal, unless they want to depend on the persistence technology’s own exceptionstructure. Catching specific causes such as an optimistic locking failure is notpossible without tying the caller to the implementation strategy. This trade off mightbe acceptable to applications that are strongly ORM-based and/or do not need any specialexception treatment. However, Spring enables exception translation to be appliedtransparently through the@Repository annotation:
@Repositorypublicclass ProductDaoImplimplements ProductDao {// class body here...}
<beans><!-- Exception translation bean post processor --><beanclass="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/><beanid="myProductDao"class="product.ProductDaoImpl"/></beans>
The postprocessor automatically looks for all exception translators (implementations ofthePersistenceExceptionTranslator interface) and advises all beans marked with the@Repository annotation so that the discovered translators can intercept and apply theappropriate translation on the thrown exceptions.
In summary: you can implement DAOs based on the plain persistence technology’s API andannotations, while still benefiting from Spring-managed transactions, dependencyinjection, and transparent exception conversion (if desired) to Spring’s customexception hierarchies.
We will start with a coverage ofHibernate 5 in a Springenvironment, using it to demonstrate the approach that Spring takes towards integratingO/R mappers. This section will cover many issues in detail and show different variationsof DAO implementations and transaction demarcation. Most of these patterns can bedirectly translated to all other supported ORM tools. The following sections in thischapter will then cover the other ORM technologies, showing briefer examples there.
![]() | Note |
|---|---|
As of Spring 4.0, Spring requires Hibernate 3.6 or later. Note that the Hibernate teamstopped supporting Hibernate 3 years ago and even phased out support for Hibernate 4.xin late 2015. We therefore recommend Hibernate 5.0 and higher from a 2016+ perspective. |
To avoid tying application objects to hard-coded resource lookups, you can defineresources such as a JDBCDataSource or a HibernateSessionFactory as beans in theSpring container. Application objects that need to access resources receive referencesto such predefined instances through bean references, as illustrated in the DAOdefinition in the next section.
The following excerpt from an XML application context definition shows how to set up aJDBCDataSource and a HibernateSessionFactory on top of it:
<beans><beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"value="org.hsqldb.jdbcDriver"/><propertyname="url"value="jdbc:hsqldb:hsql://localhost:9001"/><propertyname="username"value="sa"/><propertyname="password"value=""/></bean><beanid="mySessionFactory"class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"><propertyname="dataSource"ref="myDataSource"/><propertyname="mappingResources"><list><value>product.hbm.xml</value></list></property><propertyname="hibernateProperties"><value> hibernate.dialect=org.hibernate.dialect.HSQLDialect</value></property></bean></beans>
Switching from a local Jakarta Commons DBCPBasicDataSource to a JNDI-locatedDataSource (usually managed by an application server) is just a matter ofconfiguration:
<beans><jee:jndi-lookupid="myDataSource"jndi-name="java:comp/env/jdbc/myds"/></beans>
You can also access a JNDI-locatedSessionFactory, using Spring’sJndiObjectFactoryBean /<jee:jndi-lookup> to retrieve and expose it. However, thatis typically not common outside of an EJB context.
Hibernate has a feature called contextual sessions, wherein Hibernate itself managesone currentSession per transaction. This is roughly equivalent to Spring’ssynchronization of one HibernateSession per transaction. A corresponding DAOimplementation resembles the following example, based on the plain Hibernate API:
publicclass ProductDaoImplimplements ProductDao {private SessionFactory sessionFactory;publicvoid setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory; }public Collection loadProductsByCategory(String category) {returnthis.sessionFactory.getCurrentSession() .createQuery("from test.Product product where product.category=?") .setParameter(0, category) .list(); }}
This style is similar to that of the Hibernate reference documentation and examples,except for holding theSessionFactory in an instance variable. We strongly recommendsuch an instance-based setup over the old-schoolstaticHibernateUtil class fromHibernate’s CaveatEmptor sample application. (In general, do not keep any resources instatic variables unlessabsolutely necessary.)
The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoCcontainer, just as it would if coded against Spring’sHibernateTemplate. Of course,such a DAO can also be set up in plain Java (for example, in unit tests). Simplyinstantiate it and callsetSessionFactory(..) with the desired factory reference. As aSpring bean definition, the DAO would resemble the following:
<beans><beanid="myProductDao"class="product.ProductDaoImpl"><propertyname="sessionFactory"ref="mySessionFactory"/></bean></beans>
The main advantage of this DAO style is that it depends on Hibernate API only; no importof any Spring class is required. This is of course appealing from a non-invasivenessperspective, and will no doubt feel more natural to Hibernate developers.
However, the DAO throws plainHibernateException (which is unchecked, so does not haveto be declared or caught), which means that callers can only treat exceptions asgenerally fatal - unless they want to depend on Hibernate’s own exception hierarchy.Catching specific causes such as an optimistic locking failure is not possible withouttying the caller to the implementation strategy. This trade off might be acceptable toapplications that are strongly Hibernate-based and/or do not need any special exceptiontreatment.
Fortunately, Spring’sLocalSessionFactoryBean supports Hibernate’sSessionFactory.getCurrentSession() method for any Spring transaction strategy,returning the current Spring-managed transactionalSession even withHibernateTransactionManager. Of course, the standard behavior of that method remainsthe return of the currentSession associated with the ongoing JTA transaction, if any.This behavior applies regardless of whether you are using Spring’sJtaTransactionManager, EJB container managed transactions (CMTs), or JTA.
In summary: you can implement DAOs based on the plain Hibernate API, while still beingable to participate in Spring-managed transactions.
We recommend that you use Spring’s declarative transaction support, which enables you toreplace explicit transaction demarcation API calls in your Java code with an AOPtransaction interceptor. This transaction interceptor can be configured in a Springcontainer using either Java annotations or XML. This declarative transaction capabilityallows you to keep business services free of repetitive transaction demarcation code andto focus on adding business logic, which is the real value of your application.
![]() | Note |
|---|---|
Prior to continuing, you arestrongly encouraged to readSection 17.5, “Declarative transaction management”if you have not done so. |
You may annotate the service layer with@Transactional annotations and instruct theSpring container to find these annotations and provide transactional semantics forthese annotated methods.
publicclass ProductServiceImplimplements ProductService {private ProductDao productDao;publicvoid setProductDao(ProductDao productDao) {this.productDao = productDao; }@Transactionalpublicvoid increasePriceOfAllProductsInCategory(final String category) { List productsToChange =this.productDao.loadProductsByCategory(category);// ... }@Transactional(readOnly = true)public List<Product> findAllProducts() {returnthis.productDao.findAllProducts(); }}
All you need to set up in the container is thePlatformTransactionManagerimplementation as a bean as well as a "<tx:annotation-driven/>" entry,opting into@Transactional processing at runtime.
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- SessionFactory, DataSource, etc. omitted --><beanid="transactionManager"class="org.springframework.orm.hibernate5.HibernateTransactionManager"><propertyname="sessionFactory"ref="sessionFactory"/></bean><tx:annotation-driven/><beanid="myProductService"class="product.SimpleProductService"><propertyname="productDao"ref="myProductDao"/></bean></beans>
You can demarcate transactions in a higher level of the application, on top of suchlower-level data access services spanning any number of operations. Nor do restrictionsexist on the implementation of the surrounding business service; it just needs a SpringPlatformTransactionManager. Again, the latter can come from anywhere, but preferablyas a bean reference through asetTransactionManager(..) method, just as theproductDAO should be set by asetProductDao(..) method. The following snippets showa transaction manager and a business service definition in a Spring application context,and an example for a business method implementation:
<beans><beanid="myTxManager"class="org.springframework.orm.hibernate5.HibernateTransactionManager"><propertyname="sessionFactory"ref="mySessionFactory"/></bean><beanid="myProductService"class="product.ProductServiceImpl"><propertyname="transactionManager"ref="myTxManager"/><propertyname="productDao"ref="myProductDao"/></bean></beans>
publicclass ProductServiceImplimplements ProductService {private TransactionTemplate transactionTemplate;private ProductDao productDao;publicvoid setTransactionManager(PlatformTransactionManager transactionManager) {this.transactionTemplate =new TransactionTemplate(transactionManager); }publicvoid setProductDao(ProductDao productDao) {this.productDao = productDao; }publicvoid increasePriceOfAllProductsInCategory(final String category) {this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {publicvoid doInTransactionWithoutResult(TransactionStatus status) { List productsToChange =this.productDao.loadProductsByCategory(category);// do the price increase... } }); }}
Spring’sTransactionInterceptor allows any checked application exception to be thrownwith the callback code, whileTransactionTemplate is restricted to uncheckedexceptions within the callback.TransactionTemplate triggers a rollback in case of anunchecked application exception, or if the transaction is marked rollback-only by theapplication (viaTransactionStatus).TransactionInterceptor behaves the same way bydefault but allows configurable rollback policies per method.
BothTransactionTemplate andTransactionInterceptor delegate the actual transactionhandling to aPlatformTransactionManager instance, which can be aHibernateTransactionManager (for a single HibernateSessionFactory, using aThreadLocalSession under the hood) or aJtaTransactionManager (delegating to theJTA subsystem of the container) for Hibernate applications. You can even use a customPlatformTransactionManager implementation. Switching from native Hibernate transactionmanagement to JTA, such as when facing distributed transaction requirements for certaindeployments of your application, is just a matter of configuration. Simply replacethe Hibernate transaction manager with Spring’s JTA transaction implementation. Bothtransaction demarcation and data access code will work without changes, because theyjust use the generic transaction management APIs.
For distributed transactions across multiple Hibernate session factories, simply combineJtaTransactionManager as a transaction strategy with multipleLocalSessionFactoryBean definitions. Each DAO then gets one specificSessionFactoryreference passed into its corresponding bean property. If all underlying JDBC datasources are transactional container ones, a business service can demarcate transactionsacross any number of DAOs and any number of session factories without special regard, aslong as it is usingJtaTransactionManager as the strategy.
BothHibernateTransactionManager andJtaTransactionManager allow for properJVM-level cache handling with Hibernate, without container-specific transaction managerlookup or a JCA connector (if you are not using EJB to initiate transactions).
HibernateTransactionManager can export the Hibernate JDBCConnection to plain JDBCaccess code, for a specificDataSource. This capability allows for high-leveltransaction demarcation with mixed Hibernate and JDBC data access completely withoutJTA, if you are accessing only one database.HibernateTransactionManager automaticallyexposes the Hibernate transaction as a JDBC transaction if you have set up the passed-inSessionFactory with aDataSource through thedataSource property of theLocalSessionFactoryBean class. Alternatively, you can specify explicitly theDataSource for which the transactions are supposed to be exposed through thedataSource property of theHibernateTransactionManager class.
You can switch between a container-managed JNDISessionFactory and a locally definedone, without having to change a single line of application code. Whether to keepresource definitions in the container or locally within the application is mainly amatter of the transaction strategy that you use. Compared to a Spring-defined localSessionFactory, a manually registered JNDISessionFactory does not provide anybenefits. Deploying aSessionFactory through Hibernate’s JCA connector provides theadded value of participating in the Java EE server’s management infrastructure, but doesnot add actual value beyond that.
Spring’s transaction support is not bound to a container. Configured with any strategyother than JTA, transaction support also works in a stand-alone or test environment.Especially in the typical case of single-database transactions, Spring’s single-resourcelocal transaction support is a lightweight and powerful alternative to JTA. When you uselocal EJB stateless session beans to drive transactions, you depend both on an EJBcontainer and JTA, even if you access only a single database, and only use statelesssession beans to provide declarative transactions through container-managedtransactions. Also, direct use of JTA programmatically requires a Java EE environment aswell. JTA does not involve only container dependencies in terms of JTA itself and ofJNDIDataSource instances. For non-Spring, JTA-driven Hibernate transactions, you haveto use the Hibernate JCA connector, or extra Hibernate transaction code with theTransactionManagerLookup configured for proper JVM-level caching.
Spring-driven transactions can work as well with a locally defined HibernateSessionFactory as they do with a local JDBCDataSource if they are accessing asingle database. Thus you only have to use Spring’s JTA transaction strategy when youhave distributed transaction requirements. A JCA connector requires container-specificdeployment steps, and obviously JCA support in the first place. This configurationrequires more work than deploying a simple web application with local resourcedefinitions and Spring-driven transactions. Also, you often need the Enterprise Editionof your container if you are using, for example, WebLogic Express, which does notprovide JCA. A Spring application with local resources and transactions spanning onesingle database works in any Java EE web container (without JTA, JCA, or EJB) such asTomcat, Resin, or even plain Jetty. Additionally, you can easily reuse such a middletier in desktop applications or test suites.
All things considered, if you do not use EJBs, stick with localSessionFactory setupand Spring’sHibernateTransactionManager orJtaTransactionManager. You get all ofthe benefits, including proper transactional JVM-level caching and distributedtransactions, without the inconvenience of container deployment. JNDI registration of aHibernateSessionFactory through the JCA connector only adds value when used inconjunction with EJBs.
In some JTA environments with very strictXADataSource implementations — currentlyonly some WebLogic Server and WebSphere versions — when Hibernate is configured withoutregard to the JTAPlatformTransactionManager object for that environment, it ispossible for spurious warning or exceptions to show up in the application server log.These warnings or exceptions indicate that the connection being accessed is no longervalid, or JDBC access is no longer valid, possibly because the transaction is no longeractive. As an example, here is an actual exception from WebLogic:
java.sql.SQLException: The transaction is no longer active - status: 'Committed'. Nofurther JDBC access is allowed within this transaction.
You resolve this warning by simply making Hibernate aware of the JTAPlatformTransactionManager instance, to which it will synchronize (along with Spring).You have two options for doing this:
PlatformTransactionManager object (presumably from JNDI throughJndiObjectFactoryBean or<jee:jndi-lookup>) and feeding it, for example, toSpring’sJtaTransactionManager, then the easiest way is to specify a reference tothe bean defining this JTAPlatformTransactionManager instance as the value of thejtaTransactionManager property forLocalSessionFactoryBean. Spring then makes theobject available to Hibernate.PlatformTransactionManager instance,because Spring’sJtaTransactionManager can find it itself. Thus you need toconfigure Hibernate to look up JTAPlatformTransactionManager directly. You do thisby configuring an application server- specificTransactionManagerLookup class in theHibernate configuration, as described in the Hibernate manual.The remainder of this section describes the sequence of events that occur with andwithout Hibernate’s awareness of the JTAPlatformTransactionManager.
When Hibernate is not configured with any awareness of the JTAPlatformTransactionManager, the following events occur when a JTA transaction commits:
JtaTransactionManager is synchronized to the JTA transaction, so it iscalled back through anafterCompletion callback by the JTA transaction manager.afterTransactionCompletion callback (used to clearthe Hibernate cache), followed by an explicitclose() call on the Hibernate Session,which causes Hibernate to attempt toclose() the JDBC Connection.Connection.close() call then triggers the warning orerror, as the application server no longer considers theConnection usable at all,because the transaction has already been committed.When Hibernate is configured with awareness of the JTAPlatformTransactionManager, thefollowing events occur when a JTA transaction commits:
JtaTransactionManager is synchronized to the JTA transaction, so thetransaction is called back through abeforeCompletion callback by the JTAtransaction manager.Sessionneeds to be closed at all, Spring will close it now.Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following thesame style as the Hibernate support. The corresponding integration classes reside in theorg.springframework.orm.jdo package.
Spring provides aLocalPersistenceManagerFactoryBean class that allows you to define alocal JDOPersistenceManagerFactory within a Spring application context:
<beans><beanid="myPmf"class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean"><propertyname="configLocation"value="classpath:kodo.properties"/></bean></beans>
Alternatively, you can set up aPersistenceManagerFactory through direct instantiationof aPersistenceManagerFactory implementation class. A JDOPersistenceManagerFactoryimplementation class follows the JavaBeans pattern, just like a JDBCDataSourceimplementation class, which is a natural fit for a configuration that uses Spring. Thissetup style usually supports a Spring-defined JDBCDataSource, passed into theconnectionFactory property. For example, for the open source JDO implementationDataNucleus (formerly JPOX) (http://www.datanucleus.org/),this is the XML configuration of thePersistenceManagerFactory implementation:
<beans><beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"value="${jdbc.driverClassName}"/><propertyname="url"value="${jdbc.url}"/><propertyname="username"value="${jdbc.username}"/><propertyname="password"value="${jdbc.password}"/></bean><beanid="myPmf"class="org.datanucleus.jdo.JDOPersistenceManagerFactory"destroy-method="close"><propertyname="connectionFactory"ref="dataSource"/><propertyname="nontransactionalRead"value="true"/></bean></beans>
You can also set up JDOPersistenceManagerFactory in the JNDI environment of a Java EEapplication server, usually through the JCA connector provided by the particular JDOimplementation. Spring’s standardJndiObjectFactoryBean or<jee:jndi-lookup> can beused to retrieve and expose such aPersistenceManagerFactory. However, outside an EJBcontext, no real benefit exists in holding thePersistenceManagerFactory in JNDI: onlychoose such a setup for a good reason. SeeSection 20.3.6, “Comparing container-managed and locally defined resources” for a discussion;the arguments there apply to JDO as well.
DAOs can also be written directly against plain JDO API, without any Springdependencies, by using an injectedPersistenceManagerFactory. The following is anexample of a corresponding DAO implementation:
publicclass ProductDaoImplimplements ProductDao {private PersistenceManagerFactory persistenceManagerFactory;publicvoid setPersistenceManagerFactory(PersistenceManagerFactory pmf) {this.persistenceManagerFactory = pmf; }public Collection loadProductsByCategory(String category) { PersistenceManager pm =this.persistenceManagerFactory.getPersistenceManager();try { Query query = pm.newQuery(Product.class,"category = pCategory"); query.declareParameters("String pCategory");return query.execute(category); }finally { pm.close(); } }}
<beans><beanid="myProductDao"class="product.ProductDaoImpl"><propertyname="persistenceManagerFactory"ref="myPmf"/></bean></beans>
The main problem with such DAOs is that they always get a newPersistenceManager fromthe factory. To access a Spring-managed transactionalPersistenceManager, define aTransactionAwarePersistenceManagerFactoryProxy (as included in Spring) in front ofyour targetPersistenceManagerFactory, then passing a reference to that proxy intoyour DAOs as in the following example:
<beans><beanid="myPmfProxy"class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"><propertyname="targetPersistenceManagerFactory"ref="myPmf"/></bean><beanid="myProductDao"class="product.ProductDaoImpl"><propertyname="persistenceManagerFactory"ref="myPmfProxy"/></bean></beans>
Your data access code will receive a transactionalPersistenceManager (if any) fromthePersistenceManagerFactory.getPersistenceManager() method that it calls. The lattermethod call goes through the proxy, which first checks for a current transactionalPersistenceManager before getting a new one from the factory. Anyclose() calls onthePersistenceManager are ignored in case of a transactionalPersistenceManager.
If your data access code always runs within an active transaction (or at least withinactive transaction synchronization), it is safe to omit thePersistenceManager.close()call and thus the entirefinally block, which you might do to keep your DAOimplementations concise:
publicclass ProductDaoImplimplements ProductDao {private PersistenceManagerFactory persistenceManagerFactory;publicvoid setPersistenceManagerFactory(PersistenceManagerFactory pmf) {this.persistenceManagerFactory = pmf; }public Collection loadProductsByCategory(String category) { PersistenceManager pm =this.persistenceManagerFactory.getPersistenceManager(); Query query = pm.newQuery(Product.class,"category = pCategory"); query.declareParameters("String pCategory");return query.execute(category); }}
With such DAOs that rely on active transactions, it is recommended that you enforceactive transactions through turning offTransactionAwarePersistenceManagerFactoryProxy’s `allowCreate flag:
<beans><beanid="myPmfProxy"class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"><propertyname="targetPersistenceManagerFactory"ref="myPmf"/><propertyname="allowCreate"value="false"/></bean><beanid="myProductDao"class="product.ProductDaoImpl"><propertyname="persistenceManagerFactory"ref="myPmfProxy"/></bean></beans>
The main advantage of this DAO style is that it depends on JDO API only; no import ofany Spring class is required. This is of course appealing from a non-invasivenessperspective, and might feel more natural to JDO developers.
However, the DAO throws plainJDOException (which is unchecked, so does not have to bedeclared or caught), which means that callers can only treat exceptions as fatal, unlessyou want to depend on JDO’s own exception structure. Catching specific causes such as anoptimistic locking failure is not possible without tying the caller to theimplementation strategy. This trade off might be acceptable to applications that arestrongly JDO-based and/or do not need any special exception treatment.
In summary, you can DAOs based on the plain JDO API, and they can still participate inSpring-managed transactions. This strategy might appeal to you if you are alreadyfamiliar with JDO. However, such DAOs throw plainJDOException, and you would have toconvert explicitly to Spring’sDataAccessException (if desired).
![]() | Note |
|---|---|
You arestrongly encouraged to readSection 17.5, “Declarative transaction management” if you have not doneso, to get a more detailed coverage of Spring’s declarative transaction support. |
To execute service operations within transactions, you can use Spring’s commondeclarative transaction facilities. For example:
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><beanid="myTxManager"class="org.springframework.orm.jdo.JdoTransactionManager"><propertyname="persistenceManagerFactory"ref="myPmf"/></bean><beanid="myProductService"class="product.ProductServiceImpl"><propertyname="productDao"ref="myProductDao"/></bean><tx:adviceid="txAdvice"transaction-manager="txManager"><tx:attributes><tx:methodname="increasePrice*"propagation="REQUIRED"/><tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/><tx:methodname="*"propagation="SUPPORTS"read-only="true"/></tx:attributes></tx:advice><aop:config><aop:pointcutid="productServiceMethods"expression="execution(* product.ProductService.*(..))"/><aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/></aop:config></beans>
JDO requires an active transaction to modify a persistent object. The non-transactionalflush concept does not exist in JDO, in contrast to Hibernate. For this reason, you needto set up the chosen JDO implementation for a specific environment. Specifically, youneed to set it up explicitly for JTA synchronization, to detect an active JTAtransaction itself. This is not necessary for local transactions as performed bySpring’sJdoTransactionManager, but it is necessary to participate in JTAtransactions, whether driven by Spring’sJtaTransactionManager or by EJB CMT and plainJTA.
JdoTransactionManager is capable of exposing a JDO transaction to JDBC access codethat accesses the same JDBCDataSource, provided that the registeredJdoDialectsupports retrieval of the underlying JDBCConnection. This is the case for JDBC-basedJDO 2.0 implementations by default.
As an advanced feature, bothLocalPersistenceManagerFactoryBean andJdoTransactionManagersupport a customJdoDialect that can be passed into thejdoDialect bean property.Using aJdoDialect implementation, you can enable advanced features supported by Spring,usually in a vendor-specific manner:
Connection for exposure to JDBC-based DAOsPersistenceManager, to make transactional changes visible toJDBC-based data access codeJDOExceptions to SpringDataAccessExceptionsSee theJdoDialect javadocs for more details on its operations and how to use themwithin Spring’s JDO support.
The Spring JPA, available under theorg.springframework.orm.jpa package, offerscomprehensive support for theJava PersistenceAPI in a similar manner to the integration with Hibernate or JDO, while being aware ofthe underlying implementation in order to provide additional features.
The Spring JPA support offers three ways of setting up the JPAEntityManagerFactorythat will be used by the application to obtain an entity manager.
![]() | Note |
|---|---|
Only use this option in simple deployment environments such as stand-alone applicationsand integration tests. |
TheLocalEntityManagerFactoryBean creates anEntityManagerFactory suitable forsimple deployment environments where the application uses only JPA for data access. Thefactory bean uses the JPAPersistenceProvider autodetection mechanism (according toJPA’s Java SE bootstrapping) and, in most cases, requires you to specify only thepersistence unit name:
<beans><beanid="myEmf"class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"><propertyname="persistenceUnitName"value="myPersistenceUnit"/></bean></beans>
This form of JPA deployment is the simplest and the most limited. You cannot refer to anexisting JDBCDataSource bean definition and no support for global transactionsexists. Furthermore, weaving (byte-code transformation) of persistent classes isprovider-specific, often requiring a specific JVM agent to specified on startup. Thisoption is sufficient only for stand-alone applications and test environments, for whichthe JPA specification is designed.
![]() | Note |
|---|---|
Use this option when deploying to a Java EE server. Check your server’s documentationon how to deploy a custom JPA provider into your server, allowing for a differentprovider than the server’s default. |
Obtaining anEntityManagerFactory from JNDI (for example in a Java EE environment),is simply a matter of changing the XML configuration:
<beans><jee:jndi-lookupid="myEmf"jndi-name="persistence/myPersistenceUnit"/></beans>
This action assumes standard Java EE bootstrapping: the Java EE server autodetectspersistence units (in effect,META-INF/persistence.xml files in application jars) andpersistence-unit-ref entries in the Java EE deployment descriptor (for example,web.xml) and defines environment naming context locations for those persistence units.
In such a scenario, the entire persistence unit deployment, including the weaving(byte-code transformation) of persistent classes, is up to the Java EE server. The JDBCDataSource is defined through a JNDI location in theMETA-INF/persistence.xml file;EntityManager transactions are integrated with the server’s JTA subsystem. Spring merelyuses the obtainedEntityManagerFactory, passing it on to application objects throughdependency injection, and managing transactions for the persistence unit, typicallythroughJtaTransactionManager.
If multiple persistence units are used in the same application, the bean names of suchJNDI-retrieved persistence units should match the persistence unit names that theapplication uses to refer to them, for example, in@PersistenceUnit and@PersistenceContext annotations.
![]() | Note |
|---|---|
Use this option for full JPA capabilities in a Spring-based application environment.This includes web containers such as Tomcat as well as stand-alone applications andintegration tests with sophisticated persistence requirements. |
TheLocalContainerEntityManagerFactoryBean gives full control overEntityManagerFactory configuration and is appropriate for environments wherefine-grained customization is required. TheLocalContainerEntityManagerFactoryBeancreates aPersistenceUnitInfo instance based on thepersistence.xml file, thesupplieddataSourceLookup strategy, and the specifiedloadTimeWeaver. It is thuspossible to work with custom data sources outside of JNDI and to control the weavingprocess. The following example shows a typical bean definition for aLocalContainerEntityManagerFactoryBean:
<beans><beanid="myEmf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="dataSource"ref="someDataSource"/><propertyname="loadTimeWeaver"><beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/></property></bean></beans>
The following example shows a typicalpersistence.xml file:
<persistencexmlns="http://java.sun.com/xml/ns/persistence"version="1.0"><persistence-unitname="myUnit"transaction-type="RESOURCE_LOCAL"><mapping-file>META-INF/orm.xml</mapping-file><exclude-unlisted-classes/></persistence-unit></persistence>
![]() | Note |
|---|---|
The |
Using theLocalContainerEntityManagerFactoryBean is the most powerful JPA setupoption, allowing for flexible local configuration within the application. It supportslinks to an existing JDBCDataSource, supports both local and global transactions, andso on. However, it also imposes requirements on the runtime environment, such as theavailability of a weaving-capable class loader if the persistence provider demandsbyte-code transformation.
This option may conflict with the built-in JPA capabilities of a Java EE server. In afull Java EE environment, consider obtaining yourEntityManagerFactory from JNDI.Alternatively, specify a custompersistenceXmlLocation on yourLocalContainerEntityManagerFactoryBean definition, for example,META-INF/my-persistence.xml, and only include a descriptor with that name in yourapplication jar files. Because the Java EE server only looks for defaultMETA-INF/persistence.xml files, it ignores such custom persistence units and henceavoid conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, forexample.)
When is load-time weaving required?
Not all JPA providers require a JVM agent. Hibernate is an example of one that does not.If your provider does not require an agent or you have other alternatives, such asapplying enhancements at build time through a custom compiler or an ant task, theload-time weavershould not be used.
TheLoadTimeWeaver interface is a Spring-provided class that allows JPAClassTransformer instances to be plugged in a specific manner, depending whether theenvironment is a web container or application server. HookingClassTransformersthrough anagenttypically is not efficient. The agents work against theentire virtual machine andinspectevery class that is loaded, which is usually undesirable in a productionserver environment.
Spring provides a number ofLoadTimeWeaver implementations for various environments,allowingClassTransformer instances to be applied onlyper class loader and notper VM.
Refer tothe section called “Spring configuration” in the AOP chapter for more insight regarding theLoadTimeWeaver implementations and their setup, either generic or customized tovarious platforms (such as Tomcat, WebLogic, GlassFish, Resin and JBoss).
As described in the aforementioned section, you can configure a context-wideLoadTimeWeaver using the@EnableLoadTimeWeaving annotation ofcontext:load-time-weaver XML element. Such a global weaver is picked up by all JPALocalContainerEntityManagerFactoryBeans automatically. This is the preferred way ofsetting up a load-time weaver, delivering autodetection of the platform (WebLogic,GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver toall weaver-aware beans:
<context:load-time-weaver/><beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> ...</bean>
However, if needed, one can manually specify a dedicated weaver through theloadTimeWeaver property:
<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="loadTimeWeaver"><beanclass="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/></property></bean>
No matter how the LTW is configured, using this technique, JPA applications relying oninstrumentation can run in the target platform (ex: Tomcat) without needing an agent.This is important especially when the hosting applications rely on different JPAimplementations because the JPA transformers are applied only at class loader level andthus are isolated from each other.
For applications that rely on multiple persistence units locations, stored in variousJARS in the classpath, for example, Spring offers thePersistenceUnitManager to act asa central repository and to avoid the persistence units discovery process, which can beexpensive. The default implementation allows multiple locations to be specified that areparsed and later retrieved through the persistence unit name. (By default, the classpathis searched forMETA-INF/persistence.xml files.)
<beanid="pum"class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"><propertyname="persistenceXmlLocations"><list><value>org/springframework/orm/jpa/domain/persistence-multi.xml</value><value>classpath:/my/package/**/custom-persistence.xml</value><value>classpath*:META-INF/persistence.xml</value></list></property><propertyname="dataSources"><map><entrykey="localDataSource"value-ref="local-db"/><entrykey="remoteDataSource"value-ref="remote-db"/></map></property><!-- if no datasource is specified, use this one --><propertyname="defaultDataSource"ref="remoteDataSource"/></bean><beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="persistenceUnitManager"ref="pum"/><propertyname="persistenceUnitName"value="myCustomUnit"/></bean>
The default implementation allows customization of thePersistenceUnitInfo instances,before they are fed to the JPA provider, declaratively through its properties, whichaffectall hosted units, or programmatically, through thePersistenceUnitPostProcessor, which allows persistence unit selection. If noPersistenceUnitManager is specified, one is created and used internally byLocalContainerEntityManagerFactoryBean.
![]() | Note |
|---|---|
Although |
It is possible to write code against the plain JPA without any Spring dependencies, byusing an injectedEntityManagerFactory orEntityManager. Spring can understand@PersistenceUnit and@PersistenceContext annotations both at field and method levelif aPersistenceAnnotationBeanPostProcessor is enabled. A plain JPA DAO implementationusing the@PersistenceUnit annotation might look like this:
publicclass ProductDaoImplimplements ProductDao {private EntityManagerFactory emf;@PersistenceUnitpublicvoid setEntityManagerFactory(EntityManagerFactory emf) {this.emf = emf; }public Collection loadProductsByCategory(String category) { EntityManager em =this.emf.createEntityManager();try { Query query = em.createQuery("from Product as p where p.category = ?1"); query.setParameter(1, category);return query.getResultList(); }finally {if (em != null) { em.close(); } } }}
The DAO above has no dependency on Spring and still fits nicely into a Springapplication context. Moreover, the DAO takes advantage of annotations to require theinjection of the defaultEntityManagerFactory:
<beans><!-- bean post-processor for JPA annotations --><beanclass="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/><beanid="myProductDao"class="product.ProductDaoImpl"/></beans>
As an alternative to defining aPersistenceAnnotationBeanPostProcessor explicitly,consider using the Springcontext:annotation-config XML element in your applicationcontext configuration. Doing so automatically registers all Spring standardpost-processors for annotation-based configuration, includingCommonAnnotationBeanPostProcessor and so on.
<beans><!-- post-processors for all standard config annotations --><context:annotation-config/><beanid="myProductDao"class="product.ProductDaoImpl"/></beans>
The main problem with such a DAO is that it always creates a newEntityManager throughthe factory. You can avoid this by requesting a transactionalEntityManager (alsocalled "shared EntityManager" because it is a shared, thread-safe proxy for the actualtransactional EntityManager) to be injected instead of the factory:
publicclass ProductDaoImplimplements ProductDao {@PersistenceContextprivate EntityManager em;public Collection loadProductsByCategory(String category) { Query query = em.createQuery("from Product as p where p.category = :category"); query.setParameter("category", category);return query.getResultList(); }}
The@PersistenceContext annotation has an optional attributetype, which defaults toPersistenceContextType.TRANSACTION. This default is what you need to receive a sharedEntityManager proxy. The alternative,PersistenceContextType.EXTENDED, is a completelydifferent affair: This results in a so-called extended EntityManager, which isnotthread-safe and hence must not be used in a concurrently accessed component such as aSpring-managed singleton bean. Extended EntityManagers are only supposed to be used instateful components that, for example, reside in a session, with the lifecycle of theEntityManager not tied to a current transaction but rather being completely up to theapplication.
Method- and field-level Injection
Annotations that indicate dependency injections (such as@PersistenceUnit and@PersistenceContext) can be applied on field or methods inside a class, hence theexpressionsmethod-level injection andfield-level injection. Field-levelannotations are concise and easier to use while method-level allows for furtherprocessing of the injected dependency. In both cases the member visibility (public,protected, private) does not matter.
What about class-level annotations?
On the Java EE platform, they are used for dependency declaration and not for resourceinjection.
The injectedEntityManager is Spring-managed (aware of the ongoing transaction). It isimportant to note that even though the new DAO implementation uses method levelinjection of anEntityManager instead of anEntityManagerFactory, no change isrequired in the application context XML due to annotation usage.
The main advantage of this DAO style is that it only depends on Java Persistence API; noimport of any Spring class is required. Moreover, as the JPA annotations are understood,the injections are applied automatically by the Spring container. This is appealing froma non-invasiveness perspective, and might feel more natural to JPA developers.
![]() | Note |
|---|---|
You arestrongly encouraged to readSection 17.5, “Declarative transaction management” if you have not doneso, to get a more detailed coverage of Spring’s declarative transaction support. |
The recommended strategy for JPA is local transactions via JPA’s native transactionsupport. Spring’sJpaTransactionManager provides many capabilities known from localJDBC transactions, such as transaction-specific isolation levels and resource-levelread-only optimizations, against any regular JDBC connection pool (no XA requirement).
Spring JPA also allows a configuredJpaTransactionManager to expose a JPA transactionto JDBC access code that accesses the sameDataSource, provided that the registeredJpaDialect supports retrieval of the underlying JDBCConnection. Out of the box,Spring provides dialects for the EclipseLink, Hibernate and OpenJPA JPA implementations.See the next section for details on theJpaDialect mechanism.
As an advanced featureJpaTransactionManager and subclasses ofAbstractEntityManagerFactoryBean support a customJpaDialect, to be passed into thejpaDialect bean property. AJpaDialect implementation can enable some advancedfeatures supported by Spring, usually in a vendor-specific manner:
Connection for exposure to JDBC-based DAOs)PersistenceExceptions to SpringDataAccessExceptionsThis is particularly valuable for special transaction semantics and for advancedtranslation of exception. The default implementation used (DefaultJpaDialect) doesnot provide any special capabilities and if the above features are required, you haveto specify the appropriate dialect.
![]() | Tip |
|---|---|
As an even broader provider adaptation facility primarily for Spring’s full-featured |
See theJpaDialect andJpaVendorAdapter javadocs for more details of its operationsand how they are used within Spring’s JPA support.
As an alternative toJpaTransactionManager, Spring also allows for multi-resourcetransaction coordination via JTA, either in a Java EE environment or with astandalone transaction coordinator such as Atomikos. Aside from choosing Spring’sJtaTransactionManager instead ofJpaTransactionManager, there are a few furthersteps to take:
DataSource via JNDI. Check your application serverdocumentation for details. Analogously, a standalone transaction coordinator usuallycomes with special XA-integratedDataSource implementations; again, check its docs.EntityManagerFactory setup needs to be configured for JTA. This isprovider-specific, typically via special properties to be specified as "jpaProperties"onLocalContainerEntityManagerFactoryBean. In the case of Hibernate, these propertiesare even version-specific; please check your Hibernate documentation for details.HibernateJpaVendorAdapter enforces certain Spring-oriented defaults suchas the connection release mode "on-close" which matches Hibernate’s own default inHibernate 5.0 but not anymore in 5.1/5.2. For a JTA setup, either do not declareHibernateJpaVendorAdapter to begin with, or turn off itsprepareConnection flag.Alternatively, set Hibernate 5.2’s "hibernate.connection.handling_mode" property to"DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT" to restore Hibernate’s own default.SeeSection 20.3.7, “Spurious application server warnings with Hibernate” for a related note about WebLogic.EntityManagerFactory from your applicationserver itself, i.e. via a JNDI lookup instead of a locally declaredLocalContainerEntityManagerFactoryBean. A server-providedEntityManagerFactorymight require special definitions in your server configuration, making the deploymentless portable, but will be set up for the server’s JTA environment out of the box.