Class JpaTransactionManager

java.lang.Object
org.springframework.transaction.support.AbstractPlatformTransactionManager
org.springframework.orm.jpa.JpaTransactionManager
All Implemented Interfaces:
Serializable, org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.InitializingBean, org.springframework.transaction.ConfigurableTransactionManager, org.springframework.transaction.PlatformTransactionManager, org.springframework.transaction.support.ResourceTransactionManager, org.springframework.transaction.TransactionManager

public class JpaTransactionManager extends org.springframework.transaction.support.AbstractPlatformTransactionManager implements org.springframework.transaction.support.ResourceTransactionManager, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.InitializingBean
PlatformTransactionManager implementation for a single JPA EntityManagerFactory. Binds a JPA EntityManager from the specified factory to the thread, potentially allowing for one thread-bound EntityManager per factory. SharedEntityManagerCreator and @PersistenceContext are aware of thread-bound entity managers and participate in such transactions automatically. Using either is required for JPA access code supporting this transaction management mechanism.

This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.

This transaction manager also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access JPA and services which use plain JDBC (without being aware of JPA)! Application code needs to stick to the same simple Connection lookup pattern as with DataSourceTransactionManager (i.e. DataSourceUtils.getConnection(javax.sql.DataSource) or going through a TransactionAwareDataSourceProxy). Note that this requires a vendor-specific JpaDialect to be configured.

Note: To be able to register a DataSource's Connection for plain JDBC code, this instance needs to be aware of the DataSource (setDataSource(javax.sql.DataSource)). The given DataSource should obviously match the one used by the given EntityManagerFactory. This transaction manager will autodetect the DataSource used as the connection factory of the EntityManagerFactory, so you usually don't need to explicitly specify the "dataSource" property.

This transaction manager supports nested transactions via JDBC Savepoints. The "nestedTransactionAllowed" flag defaults to false though, since nested transactions will just apply to the JDBC Connection, not to the JPA EntityManager and its cached entity objects and related context. You can manually set the flag to true if you want to use nested transactions for JDBC access code which participates in JPA transactions (provided that your JDBC driver supports Savepoints). Note that JPA itself does not support nested transactions! Hence, do not expect JPA access code to semantically participate in a nested transaction.

Since:
2.0
Author:
Juergen Hoeller
See Also:
  • Field Summary

    Fields inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager

    logger, SYNCHRONIZATION_ALWAYS, SYNCHRONIZATION_NEVER, SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
  • Constructor Summary

    Constructors
    Constructor
    Description
    Create a new JpaTransactionManager instance.
    Create a new JpaTransactionManager instance.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Eagerly initialize the JPA dialect, creating a default one for the specified EntityManagerFactory if none set.
    protected void
    closeEntityManagerAfterFailedBegin(org.springframework.orm.jpa.JpaTransactionManager.JpaTransactionObject txObject)
    Close the current transaction's EntityManager.
    protected EntityManager
    Create a JPA EntityManager to be used for a transaction.
    protected void
    doBegin(Object transaction, org.springframework.transaction.TransactionDefinition definition)
     
    protected void
     
    protected void
    doCommit(org.springframework.transaction.support.DefaultTransactionStatus status)
     
    protected Object
     
    protected void
    doResume(Object transaction, Object suspendedResources)
     
    protected void
    doRollback(org.springframework.transaction.support.DefaultTransactionStatus status)
     
    protected void
    doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus status)
     
    protected Object
    doSuspend(Object transaction)
     
    Return the JDBC DataSource that this instance manages transactions for.
    Return the EntityManagerFactory that this instance should manage transactions for.
    Return the JPA dialect to use for this transaction manager.
    Allow Map access to the JPA properties to be passed to the persistence provider, with the option to add or override specific entries.
    Return the name of the persistence unit to manage transactions for, if any.
     
    protected boolean
     
    protected final EntityManagerFactory
    Obtain the EntityManagerFactory for actual use.
    void
    setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
    Retrieves an EntityManagerFactory by persistence unit name, if none set explicitly.
    void
    Set the JDBC DataSource that this instance should manage transactions for.
    void
    Set the EntityManagerFactory that this instance should manage transactions for.
    void
    Specify a callback for customizing every EntityManager resource created for a new transaction managed by this JpaTransactionManager.
    void
    Set the JPA dialect to use for this transaction manager.
    void
    Specify JPA properties, to be passed into EntityManagerFactory.createEntityManager(Map) (if any).
    void
    setJpaPropertyMap(Map<String,?> jpaProperties)
    Specify JPA properties as a Map, to be passed into EntityManagerFactory.createEntityManager(Map) (if any).
    void
    setPersistenceUnitName(String persistenceUnitName)
    Set the name of the persistence unit to manage transactions for.
    protected boolean
    This implementation returns "true": a JPA commit will properly handle transactions that have been marked rollback-only at a global level.

    Methods inherited from class org.springframework.transaction.support.AbstractPlatformTransactionManager

    commit, determineTimeout, getDefaultTimeout, getTransaction, getTransactionExecutionListeners, getTransactionSynchronization, invokeAfterCompletion, isFailEarlyOnGlobalRollbackOnly, isGlobalRollbackOnParticipationFailure, isNestedTransactionAllowed, isRollbackOnCommitFailure, isValidateExistingTransaction, prepareForCommit, registerAfterCompletionWithExistingTransaction, resume, rollback, setDefaultTimeout, setFailEarlyOnGlobalRollbackOnly, setGlobalRollbackOnParticipationFailure, setNestedTransactionAllowed, setRollbackOnCommitFailure, setTransactionExecutionListeners, setTransactionSynchronization, setTransactionSynchronizationName, setValidateExistingTransaction, suspend, triggerBeforeCommit, triggerBeforeCompletion, useSavepointForNestedTransaction

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface org.springframework.transaction.ConfigurableTransactionManager

    addListener

    Methods inherited from interface org.springframework.transaction.PlatformTransactionManager

    commit, getTransaction, rollback
  • Constructor Details

    • JpaTransactionManager

      public JpaTransactionManager()
      Create a new JpaTransactionManager instance.

      An EntityManagerFactory has to be set to be able to use it.

      See Also:
    • JpaTransactionManager

      public JpaTransactionManager(EntityManagerFactory emf)
      Create a new JpaTransactionManager instance.
      Parameters:
      emf - the EntityManagerFactory to manage transactions for
  • Method Details

    • setEntityManagerFactory

      public void setEntityManagerFactory(@Nullable EntityManagerFactory emf)
      Set the EntityManagerFactory that this instance should manage transactions for.

      Alternatively, specify the persistence unit name of the target EntityManagerFactory. By default, a default EntityManagerFactory will be retrieved by finding a single unique bean of type EntityManagerFactory in the containing BeanFactory.

      See Also:
    • getEntityManagerFactory

      @Nullable public EntityManagerFactory getEntityManagerFactory()
      Return the EntityManagerFactory that this instance should manage transactions for.
    • obtainEntityManagerFactory

      protected final EntityManagerFactory obtainEntityManagerFactory()
      Obtain the EntityManagerFactory for actual use.
      Returns:
      the EntityManagerFactory (never null)
      Throws:
      IllegalStateException - in case of no EntityManagerFactory set
      Since:
      5.0
    • setPersistenceUnitName

      public void setPersistenceUnitName(@Nullable String persistenceUnitName)
      Set the name of the persistence unit to manage transactions for.

      This is an alternative to specifying the EntityManagerFactory by direct reference, resolving it by its persistence unit name instead. If no EntityManagerFactory and no persistence unit name have been specified, a default EntityManagerFactory will be retrieved by finding a single unique bean of type EntityManagerFactory.

      See Also:
    • getPersistenceUnitName

      @Nullable public String getPersistenceUnitName()
      Return the name of the persistence unit to manage transactions for, if any.
    • setJpaProperties

      public void setJpaProperties(@Nullable Properties jpaProperties)
      Specify JPA properties, to be passed into EntityManagerFactory.createEntityManager(Map) (if any).

      Can be populated with a String "value" (parsed via PropertiesEditor) or a "props" element in XML bean definitions.

      See Also:
    • setJpaPropertyMap

      public void setJpaPropertyMap(@Nullable Map<String,?> jpaProperties)
      Specify JPA properties as a Map, to be passed into EntityManagerFactory.createEntityManager(Map) (if any).

      Can be populated with a "map" or "props" element in XML bean definitions.

      See Also:
    • getJpaPropertyMap

      public Map<String,Object> getJpaPropertyMap()
      Allow Map access to the JPA properties to be passed to the persistence provider, with the option to add or override specific entries.

      Useful for specifying entries directly, for example via jpaPropertyMap[myKey].

    • setDataSource

      public void setDataSource(@Nullable DataSource dataSource)
      Set the JDBC DataSource that this instance should manage transactions for. The DataSource should match the one used by the JPA EntityManagerFactory: for example, you could specify the same JNDI DataSource for both.

      If the EntityManagerFactory uses a known DataSource as its connection factory, the DataSource will be autodetected: You can still explicitly specify the DataSource, but you don't need to in this case.

      A transactional JDBC Connection for this DataSource will be provided to application code accessing this DataSource directly via DataSourceUtils or JdbcTemplate. The Connection will be taken from the JPA EntityManager.

      Note that you need to use a JPA dialect for a specific JPA implementation to allow for exposing JPA transactions as JDBC transactions.

      The DataSource specified here should be the target DataSource to manage transactions for, not a TransactionAwareDataSourceProxy. Only data access code may work with TransactionAwareDataSourceProxy, while the transaction manager needs to work on the underlying target DataSource. If there's nevertheless a TransactionAwareDataSourceProxy passed in, it will be unwrapped to extract its target DataSource.

      See Also:
    • getDataSource

      @Nullable public DataSource getDataSource()
      Return the JDBC DataSource that this instance manages transactions for.
    • setJpaDialect

      public void setJpaDialect(@Nullable JpaDialect jpaDialect)
      Set the JPA dialect to use for this transaction manager. Used for vendor-specific transaction management and JDBC connection exposure.

      If the EntityManagerFactory uses a known JpaDialect, it will be autodetected: You can still explicitly specify the DataSource, but you don't need to in this case.

      The dialect object can be used to retrieve the underlying JDBC connection and thus allows for exposing JPA transactions as JDBC transactions.

      See Also:
    • getJpaDialect

      public JpaDialect getJpaDialect()
      Return the JPA dialect to use for this transaction manager.
    • setEntityManagerInitializer

      public void setEntityManagerInitializer(Consumer<EntityManager> entityManagerInitializer)
      Specify a callback for customizing every EntityManager resource created for a new transaction managed by this JpaTransactionManager.

      This is an alternative to a factory-level EntityManager customizer and to a JpaVendorAdapter-level postProcessEntityManager callback, enabling specific customizations of transactional resources.

      Since:
      5.3
      See Also:
    • setBeanFactory

      public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory) throws org.springframework.beans.BeansException
      Retrieves an EntityManagerFactory by persistence unit name, if none set explicitly. Falls back to a default EntityManagerFactory bean if no persistence unit specified.
      Specified by:
      setBeanFactory in interface org.springframework.beans.factory.BeanFactoryAware
      Throws:
      org.springframework.beans.BeansException
      See Also:
    • afterPropertiesSet

      public void afterPropertiesSet()
      Eagerly initialize the JPA dialect, creating a default one for the specified EntityManagerFactory if none set. Auto-detect the EntityManagerFactory's DataSource, if any.
      Specified by:
      afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
    • getResourceFactory

      public Object getResourceFactory()
      Specified by:
      getResourceFactory in interface org.springframework.transaction.support.ResourceTransactionManager
    • doGetTransaction

      protected Object doGetTransaction()
      Specified by:
      doGetTransaction in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • isExistingTransaction

      protected boolean isExistingTransaction(Object transaction)
      Overrides:
      isExistingTransaction in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doBegin

      protected void doBegin(Object transaction, org.springframework.transaction.TransactionDefinition definition)
      Specified by:
      doBegin in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • createEntityManagerForTransaction

      protected EntityManager createEntityManagerForTransaction()
      Create a JPA EntityManager to be used for a transaction.

      The default implementation checks whether the EntityManagerFactory is a Spring proxy and delegates to EntityManagerFactoryInfo.createNativeEntityManager(java.util.Map<?, ?>) if possible which in turns applies JpaVendorAdapter.postProcessEntityManager(EntityManager).

      See Also:
    • closeEntityManagerAfterFailedBegin

      protected void closeEntityManagerAfterFailedBegin(org.springframework.orm.jpa.JpaTransactionManager.JpaTransactionObject txObject)
      Close the current transaction's EntityManager. Called after a transaction begin attempt failed.
      Parameters:
      txObject - the current transaction
    • doSuspend

      protected Object doSuspend(Object transaction)
      Overrides:
      doSuspend in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doResume

      protected void doResume(@Nullable Object transaction, Object suspendedResources)
      Overrides:
      doResume in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • shouldCommitOnGlobalRollbackOnly

      protected boolean shouldCommitOnGlobalRollbackOnly()
      This implementation returns "true": a JPA commit will properly handle transactions that have been marked rollback-only at a global level.
      Overrides:
      shouldCommitOnGlobalRollbackOnly in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doCommit

      protected void doCommit(org.springframework.transaction.support.DefaultTransactionStatus status)
      Specified by:
      doCommit in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doRollback

      protected void doRollback(org.springframework.transaction.support.DefaultTransactionStatus status)
      Specified by:
      doRollback in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doSetRollbackOnly

      protected void doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus status)
      Overrides:
      doSetRollbackOnly in class org.springframework.transaction.support.AbstractPlatformTransactionManager
    • doCleanupAfterCompletion

      protected void doCleanupAfterCompletion(Object transaction)
      Overrides:
      doCleanupAfterCompletion in class org.springframework.transaction.support.AbstractPlatformTransactionManager