When using the Hibernate implementation of JPA and managing those resources using a Spring datasource, when does the EntityManager session get closed? For example I have the basic pattern below that has the Spring service layer calling a Spring DAO layer (#repository). The DAO repository autowires the PersistentContext's EntityManager and performs the DB operation. My question is when is the EntityManager session closed, after the getData Service method finishes? I'm asking this question as I'm trying to see how long the hibernate L1 cache will be around and since its directly tied to the EntityManager session...
#Service
public class TestService{
#Autowired
private dataDAO;
#Transaction
public List getData(Long id){
return dataDAO.getDate(id);
}
}
By default, spring is releasing the session at the end of the transaction. In this case, the session will be release at the end of the getData method. The first level cache (L1) is bound to the actual transaction and is cleared as soon as the transaction is terminated.
Related
I have set transaction timeout in my application as #Transactional(propagation=Propagation.REQUIRED,timeout=30)
ActiveMQXAConnectionFactory and Oracle XA Datasource are two resources of my Distributed transaction. after reading a message from queue my transaction begins and while processing the application is taking more than 30 seconds and still transaction is not timed out. Only when committing the transaction its throwing timeout exception. I wanted immediately after 30 seconds the transaction should time out and throw the exception and make that thread available to consume another message from queue. Is this possible?
Without seeing your configuration it will be hard to say. If you are just adding an #Transactional, it is not going to do anything. You going to need both an EntityManager and a TransactionManager, then you need to turn on annotation based transaction management, and Spring needs to be controlling your datasource if I recall correctly.
Another, probably unnecessary side note, #Transactional will only work on public methods. Spring will proxy your method in order to manage the transaction and Spring can only proxy public methods. Also, it will only be able to work on calls from another class to that method, if you are calling that method from another method inside the same class, Spring cannot proxy either, thus no transaction management. Spring is sneakily deceptive here.
#Service
public class A{
#Autowired
Datasource datasource;
#Transactional
public void save(){
datasource.doStuff();
}
public void callSave(){
save();
}
}
#Service
public class B{
#Autowired
A a;
public void callSave(){
a.save();
}
}
Here, if a.save() is called from a.callSave(), no proxy will occur, thus you will have no transaction management. But in the exact same application, if you call b.callSave(), you will have transaction management, since Spring can then proxy the method call to a.save().
Are you using Spring Boot or vanilla Spring? We can probably give you more of a direction if you divulge that.
Hopefully that helped a bit!
What is the difference between:
#Autowired
private EntityManager em;
versus:
#PersistenceContext
private EntityManager em;
Both options work in my application, but can I break something by using the #Autowired annotation?
You shouldn't use #Autowired.
#PersistenceContext takes care to create a unique EntityManager for every thread. In a production application you can have multiple clients calling your application in the same time. For each call, the application creates a thread. Each thread should use its own EntityManager. Imagine what would happen if they share the same EntityManager: different users would access the same entities.
usually the EntityManager or Session are bound to the thread (implemented as a ThreadLocal variable).
Source: https://stackoverflow.com/a/42074452/2623162
EntityManager instances are not thread-safe.
Source: https://docs.oracle.com/cd/E19798-01/821-1841/bnbqy/index.html
Please notice that #PersistenceContext annotation comes from javax.persistence package, not from spring framework. In JavaEE it is used by the JavaEE container (aka the application server) to inject the EntityManager. Spring borrowed the PersistenceContext annotation to do the same: to inject an application-managed (= not container-managed) EntityManager bean per thread, exactly as the JavaEE container does.
#PersistenceContext allows you to specify which persistence unit you want to use. Your project might have multiple data sources connected to different DBs and #PersistenceContext allows you to say which one you want to operate on
check the explanation here:
http://www.coderanch.com/t/481448/java-EJB-SCBCD/certification/unitName-PersistenceContext
#PersistenceContext:
does not return entity manager instance
it returns container-managed proxy that acquires and releases presistence context on behalf of the application code
#PersistenceContext is a JPA standard annotation designed for that specific purpose. Whereas #Autowired is used for any dependency injection in Spring. Using #PersistenceContext gives you greater control over your context as it provides you with ability to specify optional elements e.g. name, properties
I think #Autowire will work same way as #PersistenceContext
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.misc.jpa-context
When working with multiple EntityManager instances and custom
repository implementations, you need to wire the correct EntityManager
into the repository implementation class. You can do so by explicitly
naming the EntityManager in the #PersistenceContext annotation or, if
the EntityManager is #Autowired, by using #Qualifier.
As of Spring Data JPA 1.9, Spring Data JPA includes a class called
JpaContext that lets you obtain the EntityManager by managed domain
class, assuming it is managed by only one of the EntityManager
instances in the application. The following example shows how to use
JpaContext in a custom repository:
You can create the following FactoryBean to make EntityManager properly injectable, even via constructor injection:
/**
* Makes the {#link EntityManager} injectable via <i>#Autowired</i>,
* so it can be injected with constructor injection too.
* (<i>#PersistenceContext</i> cannot be used for constructor injection.)
*/
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {
#PersistenceContext
private EntityManager entityManager;
#Override
public Class<?> getObjectType() {
return EntityManager.class;
}
#Override
protected EntityManager createInstance() {
return entityManager;
}
}
Please note, that because we use the #PersistenceContext annotation internally, the returned EntityManager will be a proper thread-safe proxy, as it would have been injected directly at the place of usage with field injection (using #PersistenceContext).
In our project we use Spring and Spring Data (for server side API service), but sometimes we do query not using Spring Data, but using JPA criteria. In order to do so we use:
#PersistenceContext
private EntityManager em;
...
CriteriaBuilder cb = em.getCriteriaBuilder();
...
From the Spring docs:
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.
So it seems that the way we use should get the current session if exists and if not should create new one. The issue we are facing is a memory leak of this use. seems like this way opens a lot of Hibernate session and does not close them.
So for the question: What is the best practice to getCurrent/open new session in Spring with Hibernate?
Note: HibernateUtil does not have getSessionFactory() as suggested in some other posts
Thanks,
Alon
I have a question about spring + hibernate
I always use hibernate for my develeppoment, I generate images of the tables and the class DAO
then at logic metier I make simple calls to these methods dao ....
for exemple UserDao=new UserDao () then userdao.persist() ...
Now I have intgret spring, and I do not yet understand ..
1
what is the plus made by him knowing that he is also making calls
has dao Service (the writings that manually) it does not generate the
class dao with hibernate
2
is that with spring I would not worry about manage session for
example open session, close session commit() ...
thank you in advance I would like to have an idea Ccool:
At its core, Spring is a dependency injection framework. This means that instead of doing
public class MyService
private MyDao dao;
public MyService() {
dao = new MyDao();
}
}
You can do
public class MyService
private MyDao dao;
#Autowired
public MyService(MyDao dao) {
this.dao = dao;
}
}
And Spring will automatically call the constructor and inject an instance of MyDao. The main benefit is that the code is easily unit-testable.
On top of that, it allows injecting proxies instead of the actual implementations directly. These proxies will indeed handle the transaction management for you, and more (exception translation, security checks, etc.).
So instead of explicitely opening, committing and rollbacking transactions, you would simply annotate a service method with #Transactional, and Spring would open, commit/rollback the transaction. And the transaction context would automatically propagate to the nested service calls.
This short answer is only to give you an idea. To learn more, read about dependency injection, and read the Spring documentation.
Use Spring annotations like #Service for service classes, #Repository for Dao classes and #Controller for action controllers. Use of #Transactional on service class or methods is suffice to carry out transactions.
I have a list of Transaction objects.
List<Transaction> transactions;
I need to batch process these transactions by creating a pool of threads which update transactions concurrently.
These threads update these transactions using the same DAO class(Spring singleton bean) to update the transaction. I'm using Hibernate as ORM
What am I to consider to make sure my code is thread safe? I'm a bit confused.
Here's the DAO class. SessionFactory is also defined as a Spring bean which is then autowired to DAO class.
#Autowired
SessionFactory sessionFactory;
#Override
public Transaction update(Transaction transaction) {
Session session = sessionFactory.openSession();
session.beginTransaction();
session.update(transaction);
session.getTransaction().commit();
return transaction;
}
To get much better performance look at pooling the DB connections, there are open source implementations like c3p0 which works nicely with spring and hibernate. This is particularly import for batch processing.
Are you using the hibernate implementation of SessionFactory? If that is the case then it is indeed thread safe so you should be good.
Another suggestion is to look at spring batch which might be useful for your situation.
Update: you've already said you are using Hibernate so the SessionFactory should be good.
I think your problem is a bit bigger than threadsafety, you need to evoke transaction management.
The session generated by the session factory is threadlocal (spring's HibernateTransactionManager and the beanFactory that creates the sessuinFactory -for ex: AnnotationSessionFactoryBean- manages all this stuff)
So Your code is Safe ;)