Split files

This commit is contained in:
Rob Winch
2023-04-19 10:26:16 -05:00
committed by rstoyanchev
parent ac69a5dac3
commit 9f49d24833
391 changed files with 62477 additions and 62392 deletions

View File

@@ -0,0 +1,108 @@
[[orm-general]]
= General ORM Integration Considerations
This section highlights considerations that apply to all ORM technologies.
The <<orm-hibernate>> section provides more details and also show these features and
configurations in a concrete context.
The major goal of Spring's ORM integration is clear application layering (with any data
access and transaction technology) and for loose coupling of application objects -- no
more business service dependencies on the data access or transaction strategy, no more
hard-coded resource lookups, no more hard-to-replace singletons, no more custom service
registries. The goal is to have one simple and consistent approach to wiring up application objects, keeping
them as reusable and free from container dependencies as possible. All the individual
data access features are usable on their own but integrate nicely with Spring's
application context concept, providing XML-based configuration and cross-referencing of
plain 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 transaction
managers, web view resolvers, web controllers that use the business services, and so on.
[[orm-resource-mngmnt]]
== Resource and Transaction Management
Typical business applications are cluttered with repetitive resource management code.
Many projects try to invent their own solutions, sometimes sacrificing proper handling
of failures for programming convenience. Spring advocates simple solutions for proper
resource handling, namely IoC through templating in the case of JDBC and applying AOP
interceptors for the ORM technologies.
The infrastructure provides proper resource handling and appropriate conversion of
specific API exceptions to an unchecked infrastructure exception hierarchy. Spring
introduces a DAO exception hierarchy, applicable to any data access strategy. For direct
JDBC, the `JdbcTemplate` class mentioned in a <<jdbc-JdbcTemplate, previous section>>
provides connection handling and proper conversion of `SQLException` to the
`DataAccessException` hierarchy, including translation of database-specific SQL error
codes to meaningful exception classes. For ORM technologies, see the
<<orm-exception-translation, next section>> for how to get the same exception
translation benefits.
When it comes to transaction management, the `JdbcTemplate` class hooks in to the Spring
transaction support and supports both JTA and JDBC transactions, through respective
Spring transaction managers. For the supported ORM technologies, Spring offers Hibernate
and JPA support through the Hibernate and JPA transaction managers as well as JTA support.
For details on transaction support, see the <<transaction>> chapter.
[[orm-exception-translation]]
== Exception Translation
When you use Hibernate or JPA in a DAO, you must decide how to handle the persistence
technology's native exception classes. The DAO throws a subclass of a `HibernateException`
or `PersistenceException`, depending on the technology. These exceptions are all runtime
exceptions and do not have to be declared or caught. You may also have to deal with
`IllegalArgumentException` and `IllegalStateException`. This means that callers can only
treat exceptions as being generally fatal, unless they want to depend on the persistence
technology's own exception structure. Catching specific causes (such as an optimistic
locking failure) is not possible without tying the caller to the implementation strategy.
This trade-off might be acceptable to applications that are strongly ORM-based or
do not need any special exception treatment (or both). However, Spring lets exception
translation be applied transparently through the `@Repository` annotation. The following
examples (one for Java configuration and one for XML configuration) show how to do so:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Repository
public class ProductDaoImpl implements ProductDao {
// class body here...
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@Repository
class ProductDaoImpl : ProductDao {
// class body here...
}
----
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<!-- Exception translation bean post processor -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
----
The postprocessor automatically looks for all exception translators (implementations of
the `PersistenceExceptionTranslator` interface) and advises all beans marked with the
`@Repository` annotation so that the discovered translators can intercept and apply the
appropriate translation on the thrown exceptions.
In summary, you can implement DAOs based on the plain persistence technology's API and
annotations while still benefiting from Spring-managed transactions, dependency
injection, and transparent exception conversion (if desired) to Spring's custom
exception hierarchies.

View File

@@ -0,0 +1,490 @@
[[orm-hibernate]]
= Hibernate
We start with a coverage of https://hibernate.org/[Hibernate 5] in a Spring environment,
using it to demonstrate the approach that Spring takes towards integrating OR mappers.
This section covers many issues in detail and shows different variations of DAO
implementations and transaction demarcation. Most of these patterns can be directly
translated to all other supported ORM tools. The later sections in this chapter then
cover the other ORM technologies and show brief examples.
NOTE: As of Spring Framework 5.3, Spring requires Hibernate ORM 5.2+ for Spring's
`HibernateJpaVendorAdapter` as well as for a native Hibernate `SessionFactory` setup.
It is strongly recommended to go with Hibernate ORM 5.4 for a newly started application.
For use with `HibernateJpaVendorAdapter`, Hibernate Search needs to be upgraded to 5.11.6.
[[orm-session-factory-setup]]
== `SessionFactory` Setup in a Spring Container
To avoid tying application objects to hard-coded resource lookups, you can define
resources (such as a JDBC `DataSource` or a Hibernate `SessionFactory`) as beans in the
Spring container. Application objects that need to access resources receive references
to such predefined instances through bean references, as illustrated in the DAO
definition in the <<orm-hibernate-straight, next section>>.
The following excerpt from an XML application context definition shows how to set up a
JDBC `DataSource` and a Hibernate `SessionFactory` on top of it:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
----
Switching from a local Jakarta Commons DBCP `BasicDataSource` to a JNDI-located
`DataSource` (usually managed by an application server) is only a matter of
configuration, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/>
</beans>
----
You can also access a JNDI-located `SessionFactory`, using Spring's
`JndiObjectFactoryBean` / `<jee:jndi-lookup>` to retrieve and expose it.
However, that is typically not common outside of an EJB context.
[NOTE]
====
Spring also provides a `LocalSessionFactoryBuilder` variant, seamlessly integrating
with `@Bean` style configuration and programmatic setup (no `FactoryBean` involved).
Both `LocalSessionFactoryBean` and `LocalSessionFactoryBuilder` support background
bootstrapping, with Hibernate initialization running in parallel to the application
bootstrap thread on a given bootstrap executor (such as a `SimpleAsyncTaskExecutor`).
On `LocalSessionFactoryBean`, this is available through the `bootstrapExecutor`
property. On the programmatic `LocalSessionFactoryBuilder`, there is an overloaded
`buildSessionFactory` method that takes a bootstrap executor argument.
As of Spring Framework 5.1, such a native Hibernate setup can also expose a JPA
`EntityManagerFactory` for standard JPA interaction next to native Hibernate access.
See <<orm-jpa-hibernate, Native Hibernate Setup for JPA>> for details.
====
[[orm-hibernate-straight]]
== Implementing DAOs Based on the Plain Hibernate API
Hibernate has a feature called contextual sessions, wherein Hibernate itself manages
one current `Session` per transaction. This is roughly equivalent to Spring's
synchronization of one Hibernate `Session` per transaction. A corresponding DAO
implementation resembles the following example, based on the plain Hibernate API:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
public class ProductDaoImpl implements ProductDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Collection loadProductsByCategory(String category) {
return this.sessionFactory.getCurrentSession()
.createQuery("from test.Product product where product.category=?")
.setParameter(0, category)
.list();
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class ProductDaoImpl(private val sessionFactory: SessionFactory) : ProductDao {
fun loadProductsByCategory(category: String): Collection<*> {
return sessionFactory.currentSession
.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 the `SessionFactory` in an instance variable. We strongly recommend
such an instance-based setup over the old-school `static` `HibernateUtil` class from
Hibernate's CaveatEmptor sample application. (In general, do not keep any resources in
`static` variables unless absolutely necessary.)
The preceding DAO example follows the dependency injection pattern. It fits nicely into a Spring IoC
container, as it would if coded against Spring's `HibernateTemplate`.
You can also set up such a DAO in plain Java (for example, in unit tests). To do so,
instantiate it and call `setSessionFactory(..)` with the desired factory reference. As a
Spring bean definition, the DAO would resemble the following:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
</beans>
----
The main advantage of this DAO style is that it depends on Hibernate API only. No import
of any Spring class is required. This is appealing from a non-invasiveness
perspective and may feel more natural to Hibernate developers.
However, the DAO throws plain `HibernateException` (which is unchecked, so it does not have
to be declared or caught), which means that callers can treat exceptions only as being
generally fatal -- unless they want to depend on Hibernate's own exception hierarchy.
Catching specific causes (such as an optimistic locking failure) is not possible without
tying the caller to the implementation strategy. This trade off might be acceptable to
applications that are strongly Hibernate-based, do not need any special exception
treatment, or both.
Fortunately, Spring's `LocalSessionFactoryBean` supports Hibernate's
`SessionFactory.getCurrentSession()` method for any Spring transaction strategy,
returning the current Spring-managed transactional `Session`, even with
`HibernateTransactionManager`. The standard behavior of that method remains
to return the current `Session` associated with the ongoing JTA transaction, if any.
This behavior applies regardless of whether you use Spring's
`JtaTransactionManager`, EJB container managed transactions (CMTs), or JTA.
In summary, you can implement DAOs based on the plain Hibernate API, while still being
able to participate in Spring-managed transactions.
[[orm-hibernate-tx-declarative]]
== Declarative Transaction Demarcation
We recommend that you use Spring's declarative transaction support, which lets you
replace explicit transaction demarcation API calls in your Java code with an AOP
transaction interceptor. You can configure this transaction interceptor in a Spring
container by using either Java annotations or XML. This declarative transaction capability
lets you keep business services free of repetitive transaction demarcation code and
focus on adding business logic, which is the real value of your application.
NOTE: Before you continue, we are strongly encourage you to read <<transaction-declarative>>
if you have not already done so.
You can annotate the service layer with `@Transactional` annotations and instruct the
Spring container to find these annotations and provide transactional semantics for
these annotated methods. The following example shows how to do so:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
public class ProductServiceImpl implements ProductService {
private ProductDao productDao;
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
@Transactional
public void increasePriceOfAllProductsInCategory(final String category) {
List productsToChange = this.productDao.loadProductsByCategory(category);
// ...
}
@Transactional(readOnly = true)
public List<Product> findAllProducts() {
return this.productDao.findAllProducts();
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class ProductServiceImpl(private val productDao: ProductDao) : ProductService {
@Transactional
fun increasePriceOfAllProductsInCategory(category: String) {
val productsToChange = productDao.loadProductsByCategory(category)
// ...
}
@Transactional(readOnly = true)
fun findAllProducts() = productDao.findAllProducts()
}
----
In the container, you need to set up the `PlatformTransactionManager` implementation
(as a bean) and a `<tx:annotation-driven/>` entry, opting into `@Transactional`
processing at runtime. The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- SessionFactory, DataSource, etc. omitted -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>
<bean id="myProductService" class="product.SimpleProductService">
<property name="productDao" ref="myProductDao"/>
</bean>
</beans>
----
[[orm-hibernate-tx-programmatic]]
== Programmatic Transaction Demarcation
You can demarcate transactions in a higher level of the application, on top of
lower-level data access services that span any number of operations. Nor do restrictions
exist on the implementation of the surrounding business service. It needs only a Spring
`PlatformTransactionManager`. Again, the latter can come from anywhere, but preferably
as a bean reference through a `setTransactionManager(..)` method. Also, the
`productDAO` should be set by a `setProductDao(..)` method. The following pair of snippets show
a transaction manager and a business service definition in a Spring application context
and an example for a business method implementation:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<bean id="myTxManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="myProductService" class="product.ProductServiceImpl">
<property name="transactionManager" ref="myTxManager"/>
<property name="productDao" ref="myProductDao"/>
</bean>
</beans>
----
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
public class ProductServiceImpl implements ProductService {
private TransactionTemplate transactionTemplate;
private ProductDao productDao;
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
public void increasePriceOfAllProductsInCategory(final String category) {
this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
List productsToChange = this.productDao.loadProductsByCategory(category);
// do the price increase...
}
});
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class ProductServiceImpl(transactionManager: PlatformTransactionManager,
private val productDao: ProductDao) : ProductService {
private val transactionTemplate = TransactionTemplate(transactionManager)
fun increasePriceOfAllProductsInCategory(category: String) {
transactionTemplate.execute {
val productsToChange = productDao.loadProductsByCategory(category)
// do the price increase...
}
}
}
----
Spring's `TransactionInterceptor` lets any checked application exception be thrown
with the callback code, while `TransactionTemplate` is restricted to unchecked
exceptions within the callback. `TransactionTemplate` triggers a rollback in case of
an unchecked application exception or if the transaction is marked rollback-only by
the application (by setting `TransactionStatus`). By default, `TransactionInterceptor`
behaves the same way but allows configurable rollback policies per method.
[[orm-hibernate-tx-strategies]]
== Transaction Management Strategies
Both `TransactionTemplate` and `TransactionInterceptor` delegate the actual transaction
handling to a `PlatformTransactionManager` instance (which can be a
`HibernateTransactionManager` (for a single Hibernate `SessionFactory`) by using a
`ThreadLocal` `Session` under the hood) or a `JtaTransactionManager` (delegating to the
JTA subsystem of the container) for Hibernate applications. You can even use a custom
`PlatformTransactionManager` implementation. Switching from native Hibernate transaction
management to JTA (such as when facing distributed transaction requirements for certain
deployments of your application) is only a matter of configuration. You can replace
the Hibernate transaction manager with Spring's JTA transaction implementation. Both
transaction demarcation and data access code work without changes, because they
use the generic transaction management APIs.
For distributed transactions across multiple Hibernate session factories, you can combine
`JtaTransactionManager` as a transaction strategy with multiple
`LocalSessionFactoryBean` definitions. Each DAO then gets one specific `SessionFactory`
reference passed into its corresponding bean property. If all underlying JDBC data
sources are transactional container ones, a business service can demarcate transactions
across any number of DAOs and any number of session factories without special regard, as
long as it uses `JtaTransactionManager` as the strategy.
Both `HibernateTransactionManager` and `JtaTransactionManager` allow for proper
JVM-level cache handling with Hibernate, without container-specific transaction manager
lookup or a JCA connector (if you do not use EJB to initiate transactions).
`HibernateTransactionManager` can export the Hibernate JDBC `Connection` to plain JDBC
access code for a specific `DataSource`. This ability allows for high-level
transaction demarcation with mixed Hibernate and JDBC data access completely without
JTA, provided you access only one database. `HibernateTransactionManager` automatically
exposes the Hibernate transaction as a JDBC transaction if you have set up the passed-in
`SessionFactory` with a `DataSource` through the `dataSource` property of the
`LocalSessionFactoryBean` class. Alternatively, you can specify explicitly the
`DataSource` for which the transactions are supposed to be exposed through the
`dataSource` property of the `HibernateTransactionManager` class.
[[orm-hibernate-resources]]
== Comparing Container-managed and Locally Defined Resources
You can switch between a container-managed JNDI `SessionFactory` and a locally defined
one without having to change a single line of application code. Whether to keep
resource definitions in the container or locally within the application is mainly a
matter of the transaction strategy that you use. Compared to a Spring-defined local
`SessionFactory`, a manually registered JNDI `SessionFactory` does not provide any
benefits. Deploying a `SessionFactory` through Hibernate's JCA connector provides the
added value of participating in the Jakarta EE server's management infrastructure, but does
not add actual value beyond that.
Spring's transaction support is not bound to a container. When configured with any strategy
other 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-resource
local transaction support is a lightweight and powerful alternative to JTA. When you use
local EJB stateless session beans to drive transactions, you depend both on an EJB
container and on JTA, even if you access only a single database and use only stateless
session beans to provide declarative transactions through container-managed
transactions. Direct use of JTA programmatically also requires a Jakarta EE environment.
Spring-driven transactions can work as well with a locally defined Hibernate
`SessionFactory` as they do with a local JDBC `DataSource`, provided they access a
single database. Thus, you need only use Spring's JTA transaction strategy when you
have distributed transaction requirements. A JCA connector requires container-specific
deployment steps, and (obviously) JCA support in the first place. This configuration
requires more work than deploying a simple web application with local resource
definitions and Spring-driven transactions.
All things considered, if you do not use EJBs, stick with local `SessionFactory` setup
and Spring's `HibernateTransactionManager` or `JtaTransactionManager`. You get all of
the benefits, including proper transactional JVM-level caching and distributed
transactions, without the inconvenience of container deployment. JNDI registration of a
Hibernate `SessionFactory` through the JCA connector adds value only when used in
conjunction with EJBs.
[[orm-hibernate-invalid-jdbc-access-error]]
== Spurious Application Server Warnings with Hibernate
In some JTA environments with very strict `XADataSource` implementations (currently
some WebLogic Server and WebSphere versions), when Hibernate is configured without
regard to the JTA transaction manager for that environment, spurious warnings or
exceptions can show up in the application server log. These warnings or exceptions
indicate that the connection being accessed is no longer valid or JDBC access is no
longer valid, possibly because the transaction is no longer active. As an example,
here is an actual exception from WebLogic:
[literal]
[subs="verbatim,quotes"]
----
java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No
further JDBC access is allowed within this transaction.
----
Another common problem is a connection leak after JTA transactions, with Hibernate
sessions (and potentially underlying JDBC connections) not getting closed properly.
You can resolve such issues by making Hibernate aware of the JTA transaction manager,
to which it synchronizes (along with Spring). You have two options for doing this:
* Pass your Spring `JtaTransactionManager` bean to your Hibernate setup. The easiest
way is a bean reference into the `jtaTransactionManager` property for your
`LocalSessionFactoryBean` bean (see <<transaction-strategies-hibernate>>).
Spring then makes the corresponding JTA strategies available to Hibernate.
* You may also configure Hibernate's JTA-related properties explicitly, in particular
"hibernate.transaction.coordinator_class", "hibernate.connection.handling_mode"
and potentially "hibernate.transaction.jta.platform" in your "hibernateProperties"
on `LocalSessionFactoryBean` (see Hibernate's manual for details on those properties).
The remainder of this section describes the sequence of events that occur with and
without Hibernate's awareness of the JTA `PlatformTransactionManager`.
When Hibernate is not configured with any awareness of the JTA transaction manager,
the following events occur when a JTA transaction commits:
* The JTA transaction commits.
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is
called back through an `afterCompletion` callback by the JTA transaction manager.
* Among other activities, this synchronization can trigger a callback by Spring to
Hibernate, through Hibernate's `afterTransactionCompletion` callback (used to clear
the Hibernate cache), followed by an explicit `close()` call on the Hibernate session,
which causes Hibernate to attempt to `close()` the JDBC Connection.
* In some environments, this `Connection.close()` call then triggers the warning or
error, as the application server no longer considers the `Connection` to be usable,
because the transaction has already been committed.
When Hibernate is configured with awareness of the JTA transaction manager,
the following events occur when a JTA transaction commits:
* The JTA transaction is ready to commit.
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the
transaction is called back through a `beforeCompletion` callback by the JTA
transaction manager.
* Spring is aware that Hibernate itself is synchronized to the JTA transaction and
behaves differently than in the previous scenario. In particular, it aligns with
Hibernate's transactional resource management.
* The JTA transaction commits.
* Hibernate is synchronized to the JTA transaction, so the transaction is called back
through an `afterCompletion` callback by the JTA transaction manager and can
properly clear its cache.

View File

@@ -0,0 +1,66 @@
[[orm-introduction]]
= Introduction to ORM with Spring
The Spring Framework supports integration with the Java Persistence API (JPA) and
supports native Hibernate for resource management, data access object (DAO) implementations,
and transaction strategies. For example, for Hibernate, there is first-class support with
several convenient IoC features that address many typical Hibernate integration issues.
You can configure all of the supported features for OR (object relational) mapping
tools through Dependency Injection. They can participate in Spring's resource and
transaction management, and they comply with Spring's generic transaction and DAO
exception hierarchies. The recommended integration style is to code DAOs against plain
Hibernate or JPA APIs.
Spring adds significant enhancements to the ORM layer of your choice when you create
data access applications. You can leverage as much of the integration support as you
wish, and you should compare this integration effort with the cost and risk of building
a similar infrastructure in-house. You can use much of the ORM support as you would a
library, regardless of technology, because everything is designed as a set of reusable
JavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thus,
most examples in this section show configuration inside a Spring container.
The benefits of using the Spring Framework to create your ORM DAOs include:
* *Easier testing.* Spring's IoC approach makes it easy to swap the implementations
and configuration locations of Hibernate `SessionFactory` instances, JDBC `DataSource`
instances, transaction managers, and mapped object implementations (if needed). This
in turn makes it much easier to test each piece of persistence-related code in
isolation.
* *Common data access exceptions.* Spring can wrap exceptions from your ORM tool,
converting them from proprietary (potentially checked) exceptions to a common runtime
`DataAccessException` hierarchy. This feature lets you handle most persistence
exceptions, which are non-recoverable, only in the appropriate layers, without
annoying boilerplate catches, throws, and exception declarations. You can still trap
and handle exceptions as necessary. Remember that JDBC exceptions (including
DB-specific dialects) are also converted to the same hierarchy, meaning that you can
perform some operations with JDBC within a consistent programming model.
* *General resource management.* Spring application contexts can handle the location
and configuration of Hibernate `SessionFactory` instances, JPA `EntityManagerFactory`
instances, JDBC `DataSource` instances, and other related resources. This makes these
values easy to manage and change. Spring offers efficient, easy, and safe handling of
persistence resources. For example, related code that uses Hibernate generally needs to
use the same Hibernate `Session` to ensure efficiency and proper transaction handling.
Spring makes it easy to create and bind a `Session` to the current thread transparently,
by exposing a current `Session` through the Hibernate `SessionFactory`. Thus, Spring
solves many chronic problems of typical Hibernate usage, for any local or JTA
transaction environment.
* *Integrated transaction management.* You can wrap your ORM code with a declarative,
aspect-oriented programming (AOP) style method interceptor either through the
`@Transactional` annotation or by explicitly configuring the transaction AOP advice in
an XML configuration file. In both cases, transaction semantics and exception handling
(rollback and so on) are handled for you. As discussed in <<orm-resource-mngmnt>>,
you can also swap various transaction managers, without affecting your ORM-related code.
For example, you can swap between local transactions and JTA, with the same full services
(such as declarative transactions) available in both scenarios. Additionally,
JDBC-related code can fully integrate transactionally with the code you use to do ORM.
This is useful for data access that is not suitable for ORM (such as batch processing and
BLOB streaming) but that still needs to share common transactions with ORM operations.
TIP: For more comprehensive ORM support, including support for alternative database
technologies such as MongoDB, you might want to check out the
https://projects.spring.io/spring-data/[Spring Data] suite of projects. If you are
a JPA user, the https://spring.io/guides/gs/accessing-data-jpa/[Getting Started Accessing
Data with JPA] guide from https://spring.io provides a great introduction.

View File

@@ -0,0 +1,577 @@
[[orm-jpa]]
= JPA
The Spring JPA, available under the `org.springframework.orm.jpa` package, offers
comprehensive support for the
https://www.oracle.com/technetwork/articles/javaee/jpa-137156.html[Java Persistence
API] in a manner similar to the integration with Hibernate while being aware of
the underlying implementation in order to provide additional features.
[[orm-jpa-setup]]
== Three Options for JPA Setup in a Spring Environment
The Spring JPA support offers three ways of setting up the JPA `EntityManagerFactory`
that is used by the application to obtain an entity manager.
* <<orm-jpa-setup-lemfb>>
* <<orm-jpa-setup-jndi>>
* <<orm-jpa-setup-lcemfb>>
[[orm-jpa-setup-lemfb]]
=== Using `LocalEntityManagerFactoryBean`
You can use this option only in simple deployment environments such as stand-alone
applications and integration tests.
The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for
simple deployment environments where the application uses only JPA for data access.
The factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (according
to JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the
persistence unit name. The following XML example configures such a bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myPersistenceUnit"/>
</bean>
</beans>
----
This form of JPA deployment is the simplest and the most limited. You cannot refer to an
existing JDBC `DataSource` bean definition, and no support for global transactions
exists. Furthermore, weaving (byte-code transformation) of persistent classes is
provider-specific, often requiring a specific JVM agent to be specified on startup. This
option is sufficient only for stand-alone applications and test environments, for which
the JPA specification is designed.
[[orm-jpa-setup-jndi]]
=== Obtaining an EntityManagerFactory from JNDI
You can use this option when deploying to a Jakarta EE server. Check your server's documentation
on how to deploy a custom JPA provider into your server, allowing for a different
provider than the server's default.
Obtaining an `EntityManagerFactory` from JNDI (for example in a Jakarta EE environment),
is a matter of changing the XML configuration, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>
----
This action assumes standard Jakarta EE bootstrapping. The Jakarta EE server auto-detects
persistence units (in effect, `META-INF/persistence.xml` files in application jars) and
`persistence-unit-ref` entries in the Jakarta 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 Jakarta EE server. The JDBC
`DataSource` is defined through a JNDI location in the `META-INF/persistence.xml` file.
`EntityManager` transactions are integrated with the server's JTA subsystem. Spring merely
uses the obtained `EntityManagerFactory`, passing it on to application objects through
dependency injection and managing transactions for the persistence unit (typically
through `JtaTransactionManager`).
If you use multiple persistence units in the same application, the bean names of such
JNDI-retrieved persistence units should match the persistence unit names that the
application uses to refer to them (for example, in `@PersistenceUnit` and
`@PersistenceContext` annotations).
[[orm-jpa-setup-lcemfb]]
=== Using `LocalContainerEntityManagerFactoryBean`
You can use this option for full JPA capabilities in a Spring-based application environment.
This includes web containers such as Tomcat, stand-alone applications, and
integration tests with sophisticated persistence requirements.
NOTE: If you want to specifically configure a Hibernate setup, an immediate alternative
is to set up a native Hibernate `LocalSessionFactoryBean` instead of a plain JPA
`LocalContainerEntityManagerFactoryBean`, letting it interact with JPA access code
as well as native Hibernate access code.
See <<orm-jpa-hibernate, Native Hibernate setup for JPA interaction>> for details.
The `LocalContainerEntityManagerFactoryBean` gives full control over
`EntityManagerFactory` configuration and is appropriate for environments where
fine-grained customization is required. The `LocalContainerEntityManagerFactoryBean`
creates a `PersistenceUnitInfo` instance based on the `persistence.xml` file, the
supplied `dataSourceLookup` strategy, and the specified `loadTimeWeaver`. It is, thus,
possible to work with custom data sources outside of JNDI and to control the weaving
process. The following example shows a typical bean definition for a
`LocalContainerEntityManagerFactoryBean`:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="someDataSource"/>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
</beans>
----
The following example shows a typical `persistence.xml` file:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
<mapping-file>META-INF/orm.xml</mapping-file>
<exclude-unlisted-classes/>
</persistence-unit>
</persistence>
----
NOTE: The `<exclude-unlisted-classes/>` shortcut indicates that no scanning for
annotated entity classes is supposed to occur. An explicit 'true' value
(`<exclude-unlisted-classes>true</exclude-unlisted-classes/>`) also means no scan.
`<exclude-unlisted-classes>false</exclude-unlisted-classes/>` does trigger a scan.
However, we recommend omitting the `exclude-unlisted-classes` element
if you want entity class scanning to occur.
Using the `LocalContainerEntityManagerFactoryBean` is the most powerful JPA setup
option, allowing for flexible local configuration within the application. It supports
links to an existing JDBC `DataSource`, supports both local and global transactions, and
so on. However, it also imposes requirements on the runtime environment, such as the
availability of a weaving-capable class loader if the persistence provider demands
byte-code transformation.
This option may conflict with the built-in JPA capabilities of a Jakarta EE server. In a
full Jakarta EE environment, consider obtaining your `EntityManagerFactory` from JNDI.
Alternatively, specify a custom `persistenceXmlLocation` on your
`LocalContainerEntityManagerFactoryBean` definition (for example,
META-INF/my-persistence.xml) and include only a descriptor with that name in your
application jar files. Because the Jakarta EE server looks only for default
`META-INF/persistence.xml` files, it ignores such custom persistence units and, hence,
avoids conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, for
example.)
.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 as
applying enhancements at build time through a custom compiler or an Ant task, you should not use the
load-time weaver.
****
The `LoadTimeWeaver` interface is a Spring-provided class that lets JPA
`ClassTransformer` instances be plugged in a specific manner, depending on whether the
environment is a web container or application server. Hooking `ClassTransformers`
through an
https://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agent]
is typically not efficient. The agents work against the entire virtual machine and
inspect every class that is loaded, which is usually undesirable in a production
server environment.
Spring provides a number of `LoadTimeWeaver` implementations for various environments,
letting `ClassTransformer` instances be applied only for each class loader and not
for each VM.
See the <<core.adoc#aop-aj-ltw-spring, Spring configuration>> in the AOP chapter for
more insight regarding the `LoadTimeWeaver` implementations and their setup, either
generic or customized to various platforms (such as Tomcat, JBoss and WebSphere).
As described in <<core.adoc#aop-aj-ltw-spring, Spring configuration>>, you can configure
a context-wide `LoadTimeWeaver` by using the `@EnableLoadTimeWeaving` annotation or the
`context:load-time-weaver` XML element. Such a global weaver is automatically picked up
by all JPA `LocalContainerEntityManagerFactoryBean` instances. The following example
shows the preferred way of setting up a load-time weaver, delivering auto-detection
of the platform (e.g. Tomcat's weaving-capable class loader or Spring's JVM agent)
and automatic propagation of the weaver to all weaver-aware beans:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<context:load-time-weaver/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>
----
However, you can, if needed, manually specify a dedicated weaver through the
`loadTimeWeaver` property, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</property>
</bean>
----
No matter how the LTW is configured, by using this technique, JPA applications relying on
instrumentation can run in the target platform (for example, Tomcat) without needing an agent.
This is especially important when the hosting applications rely on different JPA
implementations, because the JPA transformers are applied only at the class-loader level and
are, thus, isolated from each other.
[[orm-jpa-setup-multiple]]
=== Dealing with Multiple Persistence Units
For applications that rely on multiple persistence units locations (stored in various
JARS in the classpath, for example), Spring offers the `PersistenceUnitManager` to act as
a central repository and to avoid the persistence units discovery process, which can be
expensive. The default implementation lets multiple locations be specified. These locations are
parsed and later retrieved through the persistence unit name. (By default, the classpath
is searched for `META-INF/persistence.xml` files.) The following example configures
multiple locations:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="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>
<property name="dataSources">
<map>
<entry key="localDataSource" value-ref="local-db"/>
<entry key="remoteDataSource" value-ref="remote-db"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum"/>
<property name="persistenceUnitName" value="myCustomUnit"/>
</bean>
----
The default implementation allows customization of the `PersistenceUnitInfo` instances
(before they are fed to the JPA provider) either declaratively (through its properties, which
affect all hosted units) or programmatically (through the
`PersistenceUnitPostProcessor`, which allows persistence unit selection). If no
`PersistenceUnitManager` is specified, one is created and used internally by
`LocalContainerEntityManagerFactoryBean`.
[[orm-jpa-setup-background]]
=== Background Bootstrapping
`LocalContainerEntityManagerFactoryBean` supports background bootstrapping through
the `bootstrapExecutor` property, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="bootstrapExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
</property>
</bean>
----
The actual JPA provider bootstrapping is handed off to the specified executor and then,
running in parallel, to the application bootstrap thread. The exposed `EntityManagerFactory`
proxy can be injected into other application components and is even able to respond to
`EntityManagerFactoryInfo` configuration inspection. However, once the actual JPA provider
is being accessed by other components (for example, calling `createEntityManager`), those calls
block until the background bootstrapping has completed. In particular, when you use
Spring Data JPA, make sure to set up deferred bootstrapping for its repositories as well.
[[orm-jpa-dao]]
== Implementing DAOs Based on JPA: `EntityManagerFactory` and `EntityManager`
NOTE: Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances are
not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an
application server's JNDI environment, as defined by the JPA specification. It delegates
all calls to the current transactional `EntityManager`, if any. Otherwise, it falls back
to a newly created `EntityManager` per operation, in effect making its usage thread-safe.
It is possible to write code against the plain JPA without any Spring dependencies, by
using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand the
`@PersistenceUnit` and `@PersistenceContext` annotations both at the field and the method level
if a `PersistenceAnnotationBeanPostProcessor` is enabled. The following example shows a plain JPA DAO implementation
that uses the `@PersistenceUnit` annotation:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
public class ProductDaoImpl implements ProductDao {
private EntityManagerFactory emf;
@PersistenceUnit
public void 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();
}
}
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class ProductDaoImpl : ProductDao {
private lateinit var emf: EntityManagerFactory
@PersistenceUnit
fun setEntityManagerFactory(emf: EntityManagerFactory) {
this.emf = emf
}
fun loadProductsByCategory(category: String): Collection<*> {
val em = this.emf.createEntityManager()
val query = em.createQuery("from Product as p where p.category = ?1");
query.setParameter(1, category);
return query.resultList;
}
}
----
The preceding DAO has no dependency on Spring and still fits nicely into a Spring
application context. Moreover, the DAO takes advantage of annotations to require the
injection of the default `EntityManagerFactory`, as the following example bean definition shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<!-- bean post-processor for JPA annotations -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
----
As an alternative to explicitly defining a `PersistenceAnnotationBeanPostProcessor`,
consider using the Spring `context:annotation-config` XML element in your application
context configuration. Doing so automatically registers all Spring standard
post-processors for annotation-based configuration, including
`CommonAnnotationBeanPostProcessor` and so on.
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<!-- post-processors for all standard config annotations -->
<context:annotation-config/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
----
The main problem with such a DAO is that it always creates a new `EntityManager` through
the factory. You can avoid this by requesting a transactional `EntityManager` (also
called a "`shared EntityManager`" because it is a shared, thread-safe proxy for the actual
transactional EntityManager) to be injected instead of the factory. The following example shows how to do so:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
public class ProductDaoImpl implements ProductDao {
@PersistenceContext
private 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();
}
}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class ProductDaoImpl : ProductDao {
@PersistenceContext
private lateinit var em: EntityManager
fun loadProductsByCategory(category: String): Collection<*> {
val query = em.createQuery("from Product as p where p.category = :category")
query.setParameter("category", category)
return query.resultList
}
}
----
The `@PersistenceContext` annotation has an optional attribute called `type`, which defaults to
`PersistenceContextType.TRANSACTION`. You can use this default to receive a shared
`EntityManager` proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely
different affair. This results in a so-called extended `EntityManager`, which is not
thread-safe and, hence, must not be used in a concurrently accessed component, such as a
Spring-managed singleton bean. Extended `EntityManager` instances are only supposed to be used in
stateful components that, for example, reside in a session, with the lifecycle of the
`EntityManager` not tied to a current transaction but rather being completely up to the
application.
.Method- and field-level Injection
****
You can apply annotations that indicate dependency injections (such as `@PersistenceUnit` and
`@PersistenceContext`) on field or methods inside a class -- hence the
expressions "`method-level injection`" and "`field-level injection`". Field-level
annotations are concise and easier to use while method-level annotations allow for further
processing of the injected dependency. In both cases, the member visibility (public,
protected, or private) does not matter.
What about class-level annotations?
On the Jakarta EE platform, they are used for dependency declaration and not for resource
injection.
****
The injected `EntityManager` is Spring-managed (aware of the ongoing transaction).
Even though the new DAO implementation uses method-level
injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is
required in the application context XML, due to annotation usage.
The main advantage of this DAO style is that it depends only on the Java Persistence API.
No import 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 from
a non-invasiveness perspective and can feel more natural to JPA developers.
[[orm-jpa-tx]]
== Spring-driven JPA transactions
NOTE: We strongly encourage you to read <<transaction-declarative>>, if you have not
already done so, to get more detailed coverage of Spring's declarative transaction support.
The recommended strategy for JPA is local transactions through JPA's native transaction
support. Spring's `JpaTransactionManager` provides many capabilities known from local
JDBC transactions (such as transaction-specific isolation levels and resource-level
read-only optimizations) against any regular JDBC connection pool (no XA requirement).
Spring JPA also lets a configured `JpaTransactionManager` expose a JPA transaction
to JDBC access code that accesses the same `DataSource`, provided that the registered
`JpaDialect` supports retrieval of the underlying JDBC `Connection`.
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
See the <<orm-jpa-dialect, next section>> for details on the `JpaDialect` mechanism.
NOTE: As an immediate alternative, Spring's native `HibernateTransactionManager` is capable
of interacting with JPA access code, adapting to several Hibernate specifics and providing
JDBC interaction. This makes particular sense in combination with `LocalSessionFactoryBean`
setup. See <<orm-jpa-hibernate, Native Hibernate Setup for JPA Interaction>> for details.
[[orm-jpa-dialect]]
== Understanding `JpaDialect` and `JpaVendorAdapter`
As an advanced feature, `JpaTransactionManager` and subclasses of
`AbstractEntityManagerFactoryBean` allow a custom `JpaDialect` to be passed into the
`jpaDialect` bean property. A `JpaDialect` implementation can enable the following advanced
features supported by Spring, usually in a vendor-specific manner:
* Applying specific transaction semantics (such as custom isolation level or transaction
timeout)
* Retrieving the transactional JDBC `Connection` (for exposure to JDBC-based DAOs)
* Advanced translation of `PersistenceExceptions` to Spring `DataAccessExceptions`
This is particularly valuable for special transaction semantics and for advanced
translation of exception. The default implementation (`DefaultJpaDialect`) does
not provide any special abilities and, if the features listed earlier are required, you have
to specify the appropriate dialect.
TIP: As an even broader provider adaptation facility primarily for Spring's full-featured
`LocalContainerEntityManagerFactoryBean` setup, `JpaVendorAdapter` combines the
capabilities of `JpaDialect` with other provider-specific defaults. Specifying a
`HibernateJpaVendorAdapter` or `EclipseLinkJpaVendorAdapter` is the most convenient
way of auto-configuring an `EntityManagerFactory` setup for Hibernate or EclipseLink,
respectively. Note that those provider adapters are primarily designed for use with
Spring-driven transaction management (that is, for use with `JpaTransactionManager`).
See the {api-spring-framework}/orm/jpa/JpaDialect.html[`JpaDialect`] and
{api-spring-framework}/orm/jpa/JpaVendorAdapter.html[`JpaVendorAdapter`] javadoc for
more details of its operations and how they are used within Spring's JPA support.
[[orm-jpa-jta]]
== Setting up JPA with JTA Transaction Management
As an alternative to `JpaTransactionManager`, Spring also allows for multi-resource
transaction coordination through JTA, either in a Jakarta EE environment or with a
stand-alone transaction coordinator, such as Atomikos. Aside from choosing Spring's
`JtaTransactionManager` instead of `JpaTransactionManager`, you need to take few further
steps:
* The underlying JDBC connection pools need to be XA-capable and be integrated with
your transaction coordinator. This is usually straightforward in a Jakarta EE environment,
exposing a different kind of `DataSource` through JNDI. See your application server
documentation for details. Analogously, a standalone transaction coordinator usually
comes with special XA-integrated `DataSource` variants. Again, check its documentation.
* The JPA `EntityManagerFactory` setup needs to be configured for JTA. This is
provider-specific, typically through special properties to be specified as `jpaProperties`
on `LocalContainerEntityManagerFactoryBean`. In the case of Hibernate, these properties
are even version-specific. See your Hibernate documentation for details.
* Spring's `HibernateJpaVendorAdapter` enforces certain Spring-oriented defaults, such
as the connection release mode, `on-close`, which matches Hibernate's own default in
Hibernate 5.0 but not any more in Hibernate 5.1+. For a JTA setup, make sure to declare
your persistence unit transaction type as "JTA". Alternatively, set Hibernate 5.2's
`hibernate.connection.handling_mode` property to
`DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT` to restore Hibernate's own default.
See <<orm-hibernate-invalid-jdbc-access-error>> for related notes.
* Alternatively, consider obtaining the `EntityManagerFactory` from your application
server itself (that is, through a JNDI lookup instead of a locally declared
`LocalContainerEntityManagerFactoryBean`). A server-provided `EntityManagerFactory`
might require special definitions in your server configuration (making the deployment
less portable) but is set up for the server's JTA environment.
[[orm-jpa-hibernate]]
== Native Hibernate Setup and Native Hibernate Transactions for JPA Interaction
A native `LocalSessionFactoryBean` setup in combination with `HibernateTransactionManager`
allows for interaction with `@PersistenceContext` and other JPA access code. A Hibernate
`SessionFactory` natively implements JPA's `EntityManagerFactory` interface now
and a Hibernate `Session` handle natively is a JPA `EntityManager`.
Spring's JPA support facilities automatically detect native Hibernate sessions.
Such native Hibernate setup can, therefore, serve as a replacement for a standard JPA
`LocalContainerEntityManagerFactoryBean` and `JpaTransactionManager` combination
in many scenarios, allowing for interaction with `SessionFactory.getCurrentSession()`
(and also `HibernateTemplate`) next to `@PersistenceContext EntityManager` within
the same local transaction. Such a setup also provides stronger Hibernate integration
and more configuration flexibility, because it is not constrained by JPA bootstrap contracts.
You do not need `HibernateJpaVendorAdapter` configuration in such a scenario,
since Spring's native Hibernate setup provides even more features
(for example, custom Hibernate Integrator setup, Hibernate 5.3 bean container integration,
and stronger optimizations for read-only transactions). Last but not least, you can also
express native Hibernate setup through `LocalSessionFactoryBuilder`,
seamlessly integrating with `@Bean` style configuration (no `FactoryBean` involved).
[NOTE]
====
`LocalSessionFactoryBean` and `LocalSessionFactoryBuilder` support background
bootstrapping, just as the JPA `LocalContainerEntityManagerFactoryBean` does.
See <<orm-jpa-setup-background, Background Bootstrapping>> for an introduction.
On `LocalSessionFactoryBean`, this is available through the `bootstrapExecutor`
property. On the programmatic `LocalSessionFactoryBuilder`, an overloaded
`buildSessionFactory` method takes a bootstrap executor argument.
====