JPA's EntityManager or Hibernate's HibernateTemplate with Spring - spring

I have decided to use Spring, Hibernate, and Restlet to create a web service. I am new to all of these three technologies. My question is this: How do I decide whether to use JPA's EntityManager or Hibernate's HibernateTemplate?
Code snippet for JPA's EntityManager:
protected EntityManager entityManager;
#PersistenceContext
public void setEngityManager(EntityManager entityManger) {
this.entityManager = entityManager;
}
Code snippet for Hibernate's HibernateTemplate:
private SessionFactory sessionFactory;
private HibernateTemplate hibernateTemplate;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}

If you are someone who like interface-based-implementation, then JPA is the interface definition and Hibernate is one of the implementations. We decided to use JPA semantics in our project (with a very long term plan to replace Hibernate with something similar and light-weight probably).

If you want to stick to hibernate in future, then no point in using EntityManagerFactory, you can go ahead and use SessionFactory. And just inject definition for this using java based configuration or xml. It must be available in application context.
But in future if you might want to move to different jpa provider, like toplink etc, then you should use EntityManagerFactory as it allows you to have implementation from various provider. Because providers implement jpa specification. So in future you just need to have different configuration in your application context and you should be able to use that.

Related

Autowire repositories from similar tables in different datasources

I have two versions of the same application. They are using similar database schemas. I want to run a junit test that compares two tables on both sides. I am using Springboot and JPA. I can autowire both datasources in the same test. I can autowire a CrudRepository for one of the tables in the primary datasource. But how can I autowire a similar repository for the same table that is sitting on the second datasource, at the same time in the same Junit test? I would like to do something like this on the same class:
#Autowired( Datasource="primarydatasource")
CustomerRepository fistCustomerRepository;
#Autowired( Datasource="seconddatasource")
CustomerRepository secondCustomerRepository;
I have checked many tutorials and answers here, but I have not found a clear example on this.
Using multiple datasources with Spring Boot
You can create two EntityManager
#Bean("em1")
public LocalContainerEntityManagerFactoryBean em1(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(customDataSource1())
.packages(DataSource.class)
.build();
}
#Bean("em2")
public LocalContainerEntityManagerFactoryBean em2(
EntityManagerFactoryBuilder builder) {
return ...;
}
Then you can inject the entity manager in you repository
#Repository
class CustomerRepositoryOracle{
#PersistenceContext(name="em1")
private EntityManager entityManager;
}
#Repository
class CustomerRepositoryPostgreSQL{
#PersistenceContext(name="em2")
private EntityManager entityManager;
}

Hibernate Filters with JPA EntityManagerFactory and Spring

I have a jersey + spring application that is using EntityManagerFactory and spring JpaTransactionManager to handle the db manipulations. The JPA implementation is hibernate.
I would like to know is there a way to enable hibernate filters in this scenario.
I tried extending org.springframework.orm.jpa.JpaTransactionManager and overriding
#Override
protected EntityManager createEntityManagerForTransaction() {
EntityManager manager = super.createEntityManagerForTransaction();
Session session = manager.unwrap(Session.class);
return manager;
}
But I am not sure that this method is called at the right place.
EDIT:
I am using spring JpaRepositories to persist/query entities.
I found an answer for this problem. It seems like other people are still struggling with this, I will post my solution.
I am enabling the filters that I need in business service methods that are marked as #Transactional (that is important).
In your service, inject the entity manager factory:
#Autowired
private EntityManagerFactory entityManagerFactory;
Inside the #Transactional method obtain the entity manager from the transactionManager, unwrap it to hibernate session and enable the filters that you need. This is done as follows:
//Obtain the entity manager for the current transaction
EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory);
EntityManager entityManager = holder.getEntityManager();
//Unwrap to get the underlying hibernate session
Session hibernateSession = entityManager.unwrap(Session.class);
//Configure your filters
Filter publishedAfterFilter = hibernateSession.enableFilter("...");
publishedAfterFilter.setParameter("...", ...);
publishedAfterFilter.validate();

org.springframework.orm.hibernate3.HibernateTemplate

We are using hibernate template by using the following package.
org.springframework.orm.hibernate3.HibernateTemplate;
protected HibernateTemplate template = null;
here template is from org.springframework.orm.hibernate3.HibernateTemplate package. I am not able to understand how to interpret this package.
is it the spring hibernate because package name starts with springframework. But there is no such spring hibernate. There is only ORM module i guess in spring.
Can anyone help me understand how to understand this package org.springframework.orm.hibernate3.HibernateTemplate.
update:
below is the exactly repository class I am using
#Repository
#Transactional
public class ABCDImplements ABCD {
private Log logger = LogFactory.getLog(this.getClass());
protected HibernateTemplate template = null;
#Resource(name = "abcSessionFactory")
protected SessionFactory sessionFactory;
#Autowired
public void init(SessionFactory sessionFactory) {
setSessionFactory(sessionFactory);
}
public void setSessionFactory(SessionFactory sessionFactory) {
template = new HibernateTemplate(sessionFactory);
}
}
Spring provides integration with Hibernate 3 and 4 under the form of HibernateTemplate, and the one you show provides integration with Hibernate 3.
The main goal of this class was to provide a Hibernate session via a callback, and another important functionality was to translate Hibernate exceptions to Spring exceptions.
The use of this class is not recommended anymore, have a look at this answer. The recommended way is to use the #Transactional annotation.

Recommended way to hit the database within the DAO's in Spring3.1.1 (hibernate4)?

I am upgrading my project from spring 3.0.5 & hibernate 3 to spring 3.1.1 & hibernate 4.1
I use org.springframework.orm.hibernate3.support.HibernateDaoSupport extensively. In concrete HibernateTemplate; like in this snippet:
public class MenuDaoImpl extends HibernateDaoSupport implements MenuDao, Serializable {
public List<Menu> getMenus() {
return getHibernateTemplate().find("from Menu menu");
}
//etc
}
But I read that HibernateTemplate isn't recommended for use anymore.
So, what’s the recommended way to hit the database within the DAO's in Spring3.1.1?
Thanks
Inject an EntityManager and use it directly.
public class MenuDaoImpl implements MenuDao {
#PersistenceContext
private EntityManager entityManager;
...
}
Here's a good example on the SpringSource blog.
As of Hibernate 3.0.1, Spring recommends the use of SessionFactory, rather than the HibernateTemplate.
From the Spring 3.0 HibernateTemplate API docs:
NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can
also be coded in plain Hibernate style. Hence, for newly started
projects, consider adopting the standard Hibernate3 style of coding
data access objects instead, based on
SessionFactory.getCurrentSession().
Example:
public class MenuDao {
#Autowired
private SessionFactory sessionFactory;
public List<Menu> getMenus() {
return (List<Menu>) sessionFactory.getCurrentSession.createQuery("from Menu").list();
}
}

Spring JPA : Application managed persistence context with #Transactional and #PersistenceContext

Currently im trying out the application managed persistence context, by creating the entity manager manually and store them to enable transaction that spans multiple request calls (perhaps something like extended persistence context) in JSE application.
But, im wondering whether i can avoid sending the entityManager object throughout the service and DAO methods as an additional parameter by making use of the spring's #PersistenceContext injection and mark the methods with #Transactional annotation to use the transaction started manually with that entity manager.
I think i can somehow manage this by using a ThreadLocal for this feature, but i'll be happier to be able to attach this to the spring framework.
This is an example of What i have in mind :
The UI action method :
Here we can see the transaction is started by the ui logic, since there iss no facade / command method in the backend to group these callings to the business logic :
Long transactionid = tool.beginTransaction();
// calling business methods
tool.callBusinessLogic("purchase", "receiveGoods",
paramObject1, transactionid);
tool.callBusinessLogic("inventory", "updateInventory",
paramObject2, transactionid);
tool.commitTransaction(transactionid);
Inside the tool :
public Long beginTransaction() {
// create the entity --> for the #PersistentContext
Entitymanager entityManager = createEntityManagerFromFactory();
long id = System.currentTimeMillis();
entityManagerMap.put(id, entitymanager);
// start the transaction --> for the #Transactional ?
entityManager.getTransaction().begin();
return id;
}
public void commitTransaction(Long transactionId) {
EntityManager entityManager = entityManagerMap.get(transactionId);
entityManager.getTransaction().commit();
}
public Object callBusinessLogic(String module, String function,
Object paramObject, Long transactionid) {
EntityManager em = entityManagerMap.get(transactionId);
// =================================
// HOW TO DO THIS????
// =================================
putEntityManagerIntoCurrentPersistenceContext(em);
return executeBusinessLogic(module, function, paramObject, transactionid);
}
And the example for the service method :
public class Inventory {
// How can i get the entityManager that's been created by the tool for this thread ?
#PersistenceContext
private EntityManager entityManager;
// How can i use the transaction with that transactionId ?
#Transactional
public void receiveGoods(Param param) {
// ........
}
}
Is there anyway to achieve this ?
Thank you !
Spring's handling of the #PersistenceContext annotation does almost exactly what you're after, with one big difference: you always get a transaction scoped EntityManager and Spring injects always the same instance for the same thread, so you have kind of propagation and don't have to worry about thread-safety. But you'll never get an extended context this way!
Believe me, Spring 3 and extended persistence context don't play well together, maybe this will change in Spring 3.1 but I'm afraid that's not in their focus. If you want to use an extended persistence context let Spring inject the EntityManagerFactory (via #PersistenceUnit annotation) and then create the EntityManager on your own. For propagation you'll have to either pass the instance as a parameter or store it in a ThreadLocal yourself.
Indeed to have a application managed persistence context, you need to somehow "hack" the #Transactional & #PersistenceContext infrastructure by providing them your own Entity Manager and do not let Spring create its own.
The key to achieve this is to play a little bit with the TransactionSynchronizationManager class to register your own Entity Manager to the thread local, Spring will use it to inject to the #PersistenceContext attribute.
I had this need some time ago for my own application and I've designed a small architecture based on Spring AOP to manage the extended persistence context.
Details here: JPA/Hibernate Global Conversation with Spring AOP
When you configure your transactions via #Transactional, then you should handover the configuration of your transactions to the annotation.
Here you start your transaction and then hope that the #Transactional will also be triggerd.
for more information you would best start reading http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html => 9.5.6. Using #Transactional

Resources