Transanction
https://stackoverflow.com/questions/23984968/jpa-without-transaction
I know that even when you don´t use @Transaction annotation, the DB creates a transaction for every operation (even SELECT queries).
https://stackoverflow.com/questions/26327274/do-you-need-a-database-transaction-for-reading-data/26327536
org.springframework.data.domain.Page<T>
int getTotalPages();
long getTotalElements();
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
The general concensus seems to be that while EntityManager is not thread safe per JPA specs, the EntityManager injected by Spring through its EntityManager proxy may be
https://stackoverflow.com/questions/23984968/jpa-without-transaction
I know that even when you don´t use @Transaction annotation, the DB creates a transaction for every operation (even SELECT queries).
https://stackoverflow.com/questions/26327274/do-you-need-a-database-transaction-for-reading-data/26327536
All database statements are executed within the context of a physical transaction, even when we don’t explicitly declare transaction boundaries (BEGIN/COMMIT/ROLLBACK).
If you don't declare transaction boundaries, then each statement will have to be executed in a separate transaction (
autocommit
mode). This may even lead to opening and closing one connection per statement unless your environment can deal with connection-per-thread binding.
Declaring a service as
@Transactional
will give you one connection for the whole transaction duration, and all statements will use that single isolation connection. This is way better than not using explicit transactions in the first place.
On large applications, you may have many concurrent requests, and reducing database connection acquisition request rate will definitely improve your overall application performance.
JPA doesn't enforce transactions on read operations. Only writes end up throwing a transaction required exception in case you forget to start a transactional context. Nevertheless, it's always better to declare transaction boundaries even for read-only transactions (in Spring
@Transactional
allows you to mark read-only transactions, which has a great performance benefit).
Now, if you use declarative transaction boundaries (e.g.
@Transactional
), you need to make sure that the database connection acquisition is delayed until there is a JDBC statement to be executed. In JTA, this is the default behavior. When using RESOURCE_LOCAL, you need to set the hibernate.connection.provider_disables_autocommit
configuration property and make sure that the underlying connection pool is set to disable the auto-commit mode.org.springframework.data.domain.Page<T>
int getTotalPages();
long getTotalElements();
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
However, you can also define constraints by traversing nested properties. Assume a
Person
has an Address
with a ZipCode
. In that case a method name ofList<Person> findByAddressZipCode(ZipCode zipCode);
creates the property traversal
x.address.zipCode
. The resolution algorithm starts with interpreting the entire part (AddressZipCode
) as the property and checks the domain class for a property with that name (uncapitalized). If the algorithm succeeds it uses that property. If not, the algorithm splits up the source at the camel case parts from the right side into a head and a tail and tries to find the corresponding property, in our example, AddressZip
and Code
. If the algorithm finds a property with that head it takes the tail and continue building the tree down from there, splitting the tail up in the way just described. If the first split does not match, the algorithm move the split point to the left (Address
, ZipCode
) and continues.
Although this should work for most cases, it is possible for the algorithm to select the wrong property. Suppose the
Person
class has an addressZip
property as well. The algorithm would match in the first split round already and essentially choose the wrong property and finally fail (as the type of addressZip
probably has no code
property).
To resolve this ambiguity you can use
_
inside your method name to manually define traversal points. So our method name would end up like so:List<Person> findByAddress_ZipCode(ZipCode zipCode);
As we treat underscore as a reserved character we strongly advise to follow standard Java naming conventions (i.e. notusing underscores in property names but camel case instead).
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
http://stackoverflow.com/questions/11063567/java-cdi-persistencecontext-and-thread-safety
To my great surprise (after years of using jpa in spring)
EntityManager
is not thread safe. This is actually understandable if you think about it deeper: EntityManager
is just a wrapper around native JPA implementation, e.g. session in Hibernate, which in turns is a wrapper around jdbcconnection. That being said EntityManager
can't be thread safe as it represents one database connection/transaction.
So why does it work in Spring? Because it wraps target
EntityManager
in a proxy, in principle using ThreadLocal
to keep local reference per each thread. This is required as Spring applications are built on top of singletons while EJB uses object pool.
However injecting
http://stackoverflow.com/questions/5113716/spring-persistencecontext-and-autowired-thread-safetyEntityManager
to servlets and singleton beans is not safe as possibly several threads can access them at the same time, messing up with the same JDBC connection.The general concensus seems to be that while EntityManager is not thread safe per JPA specs, the EntityManager injected by Spring through its EntityManager proxy may be
Hibernate: An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded. An EntityManager will not obtain a JDBC Connection (or a Datasource) unless it is needed, so you may safely open and close an EntityManager even if you are not sure that data access will be needed to serve a particular request.
EntityManager
is not thread-safe by definition. Servlets specs says that in non-distributed environment and without implementing SingleThreadModel
, there is only one servlet instance per definition.
Therefore, in Java EE when you inject an
EntityManager
through the @PersistenceContext
into Servlet's field - it's not thread safe:public class MyServlet extends HttpServlet {
// Not thread-safe, should be using EMF instead.
@PersistenceContext
private EntityManager em;
}
- Is this correct to say that even though the default scope of Spring beans is singleton, the
EntityManager
is thread-safe as the Spring usesThreadLocal
to bind its transaction andEntityManager
to it?
One way to fix this is to inject EntityManagerFactory instead. EntityManagerFactory is guaranteed to be thread-safe. For example:
Continuing container-managed EntityManager vs application-managed EntityManager.
There are important differences between the injected EntityManager, and the EntityManager created from an injected EntityManagerFactory. Basically, injected EntityManager is container-managed, meaning all of its lifecycle is controlled by the container (web container or EJB container). Application code cannot close it, or otherwise interfere with its life.
In addition, for a container-managed EntityManager, its associated PersistenceContext is automatically propagated along with the underlying JTA, from servlet A to servlet B, from servlet to EJB, from EJB a to EJB B, and so on. As such, EntityManager of the same configuration injected into various classes can share the same PersistenceContext in a call stack.
On the other hand, EntityManager created from EntityManagerFactory is application-managed EntityManager. Application code is responsible for managing its whole lifecycle. And there is no PersistenceContext propagation for application-managed EntityManager.
Are all EntityManager's obtained from EntityManagerFactory application-managed EntityManager? Yes.
Is it possible to get a container-managed EntityManager from EntityManagerFactory? No.
You may have read about the method EntityManagerFactory.getEntityManager(), which returns a container-managed EntityManager. This method was considered and included in the early draft version of Java Persistence API, but was eventually removed from its final release.
1
2
3
4
5
6
7
8
9
10
11
12
| public class EMTestServlet extends HttpServlet { //This field injection is thread-safe @PersistenceUnit private EntityManagerFactory emf; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { EntityManager em = emf.createEntityManager(); //work with em } } |
Continuing container-managed EntityManager vs application-managed EntityManager.
There are important differences between the injected EntityManager, and the EntityManager created from an injected EntityManagerFactory. Basically, injected EntityManager is container-managed, meaning all of its lifecycle is controlled by the container (web container or EJB container). Application code cannot close it, or otherwise interfere with its life.
In addition, for a container-managed EntityManager, its associated PersistenceContext is automatically propagated along with the underlying JTA, from servlet A to servlet B, from servlet to EJB, from EJB a to EJB B, and so on. As such, EntityManager of the same configuration injected into various classes can share the same PersistenceContext in a call stack.
On the other hand, EntityManager created from EntityManagerFactory is application-managed EntityManager. Application code is responsible for managing its whole lifecycle. And there is no PersistenceContext propagation for application-managed EntityManager.
Are all EntityManager's obtained from EntityManagerFactory application-managed EntityManager? Yes.
Is it possible to get a container-managed EntityManager from EntityManagerFactory? No.
You may have read about the method EntityManagerFactory.getEntityManager(), which returns a container-managed EntityManager. This method was considered and included in the early draft version of Java Persistence API, but was eventually removed from its final release.
Question 2, 3, and 4 -- Spring does not pay attention to any class that is not a Spring Bean. Therefor Spring does not pay attention to you
MyServlet
class.
The JPA specification defines two kinds of entity managers:
Application-managed —Entity managers are created when an application directly requests one from an entity manager factory. With application-managed entity managers, the application is responsible for opening or closing entity managers and involving the entity manager in transactions.
Container-managed —Entity managers are created and managed by a Java EE container. The application doesn’t interact with the entity manager factory at all. Instead, entity managers are obtained directly through injection or from JNDI. The container is responsible for configuring the entity manager factories.
LocalEntityManagerFactoryBean produces an application-managed EntityManagerFactory.
LocalContainerEntityManagerFactoryBean produces a container-managed EntityManagerFactory.
Persistence Unit: a group of entity classes defined by the developer to map database records to objects that are managed by an Entity Manager, basically all classes annotated with @Entity, @MappedSuperclass, and @Embedded in an application. All entity classes must define a primary key, must have a non-arg constructor or not allowed to be final. Keys can be a single field or a combination of fields.
Persistence Context: a context containing a set of domain objects/entities in which for every persistent entity there is a unique entity instance.