Spring+hibernate+jpa how does it work? - spring

In the new project that I have joined, they keep using the terms Hibernate and JPA interchangeably. So, I tried to dive down into the code and try to understand how this whole thing works (I am new to Spring, JPA and Hibernate world). I'll try to put the code here for better understanding:
1) There is a #Configuration class where they have the following:
#Resource
private HibernateJpaVendorAdapter hibernateOracleJpaVendorAdapter;
LocalContainerEntityManagerFactoryBean entityManager =
new LocalContainerEntityManagerFactoryBean();
entityManager.setJpaVendorAdapter(hibernateOracleJpaVendorAdapter);
entityManager.setPersistenceUnitName("abc");
.
.
So, in this configuration class, we are returning an EntityManagerFactory.
2) Then there is a persistor class marked #Persistor, where a method of repository is invoked (for example, for a save operation):
blahblahRepository.save(blahblahEntity, abcdef);
3) Finally there is a repository class which is annotated #Repository. Then again, they have this piece of code:
#PersistenceContext(unitName = "same as the name in persistence.xml")
protected EntityManager entityManager;
The "save" method wraps around the persist method of JPA:
getEntityManager().persist(entityObject);
My questions are as follows:
1) There is no word about Hibernate other than in the hibernateJpaVendorAdapter. I searched the entire workspace and it showed just 3 occurences of the word hibernate, all in the configuration file.
2) From whatever knowledge I have, one should use either an EntityManagerFactory or an EntityManager but we are doing both?

Hibernate is one of the implementations of the JPA spec. Since your project chose Hibernate as its JPA implementation, it uses the JPA API, which delegates the Hibernate. Just like when you use the JDBC API, which delegates to a specific Oracle or PostgreSQL driver.
EntityManagerFactory, as its name indicates, is a factory for EntityManager. I don't see why you wouldn't use both. EntityManager is the main interface of the JPA API, used to execute all database operations (find, persist, merge, query, etc.). EntityManagerFactory must be configured before asking it to create an EntityManager.

Related

Why JPA Repository always create a transaction?

When I use P6Spy to capture SQL statements, I found there always a commit action takes about 200ms, which means there is always a transaction.
After more research, I found JPA always creates a transaction.
JPA always create a transaction even for findById method.
JPA always create a transaction even when explicitly annotate a method with "#Transactional(propagation = Propagation.NEVER)".
The root cause is SimpleJpaRepository class is annotated with #Transactional, and the
default propagation is REQUIRED.
#Repository
#Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID>
SimpleJpaRepository seems so obsessed with transaction...
Question:
Why SimpleJpaRepository add #Transactional at class level? The deleteById and delete method already annotated with #Transactional right?
How to avoid transaction for JPA query like findById?
When I hack Spring JPA source code like below, and recompiled as a home-made jar to replace the canonical jar, now JPA queries work like a charm, and for queries the commit is gone!
//Hack!
#Repository
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID>
P.S.
Related spring source codes here:
TransactionalRepositoryProxyPostProcessor.RepositoryAnnotationTransactionAttributeSource
Edit:
JPA Transaction here means JpaTransactionManager hold a physical connection with setAutoCommit(false) and follows with a commit action in the end.

How to use StatelessSession with Spring Data JPA and Hibernate?

I'm using Spring + Spring Data JPA with Hibernate and I need to perform some large and expensive database operations.
How I can use a StatelessSession to perform these kind of operations?
A solution is to implement a Spring factory bean to create this StatelessSession and inject it in your custom repositories implementation:
public class MyRepositoryImpl implements MyRepositoryCustom {
#Autowired
private StatelessSession statelessSession;
#Override
#Transactional
public void myBatchStatements() {
Criteria c = statelessSession.createCriteria(User.class);
ScrollableResults itemCursor = c.scroll();
while (itemCursor.next()) {
myUpdate((User) itemCursor.get(0));
}
itemCursor.close();
return true;
}
}
Check out the StatelessSessionFactoryBean and the full Gist here. Using Spring 3.2.2, Spring Data JPA 1.2.0 and Hibernate 4.1.9.
Thanks to this JIRA and the guy who attached StatelessSessionFactoryBean code. Hope this helps somebody, it worked like a charm for me.
To get even better performance results you can enable jdbc batch statements on the SessionFactory / EntityManager by setting the hibernate.jdbc.batch_size property on the SessionFactory configuration (i.e.: LocalEntityManagerFactoryBean).
To have an optimal benefit of the jdbc batch insert / updates write as much entities of the same type as possible. Hibernate will detect when you write another entity type and flushes the batch automatically even when it has not reached the configured batch size.
Using the StatelessSession behaves basically the same as using something like Spring's JdbcTemplate. The benefit of using the StatelessSession is that the mapping and translation to SQL is handled by Hibernate. When you use my StatelessSessionFactoryBean you can even mix the Session and the StatelessSession mixed in one transaction. But be careful of modifying an Entity loaded by the Session and persisting it with the StatelessSession because it will result into locking problems.

Spring : #PersistenceContext and #Autowired thread safety?

based on this example :
#Service
public class Purchase {
#PersistenceContext
private EntityManager em;
#Autowired
private PurchaseDAO dao;
private String normalField;
.... // methods, operations, etc
}
Please help correct me if im mistaken :
The service class Purchase and the PurchaseDAO are singletons that are managed by spring
The service class's field normalField is not threadsafe, because singleton is a single object shared by many
Let's assume the #Repository-annotated-PurchaseDAO doesnt have any field, which means it's threadsafe, will be injected automatically by spring
The EntityManager instance is also a threadsafe property because #PersistenceContext will make sure that the entityManager of the current transaction will be used.
Thank you !
They are singletons by default (when they are Spring managed), unless you have configured them otherwise (from either the xml-configuration or with annotations you can set it with #Scope).
Yes and no. Yes, it's not safe in the sense that multiple threads can access and modify it simultaneously, and no because it depends on the data type and String is immutable (and at least said to be thread safe). It could possibly blow up if two different threads tried to store a new string in the member variable at the exact same moment.
Yes and no again. If the DAO has no internal state, yes, I'd say it's thread safe, but the objects it is handling might not be (although if you're using JPA-entities, they should be).
At least Hibernate's documentation says that EntityManagers are not threadsafe, but when using an EntityManager injected by Spring, it shouldn't be an issue.
SpringSource forums:
I have been looking for answers to the same question on the forum... 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 and two DAO with PersistenceContextType.EXTENDED

I have a problem with my entity manager in my application. I have two DAO clasess like this:
#Repository
public abstract class DaoA
{
protected ClassA persistentClass;
#PersistenceContext(name="my.persistence", type=PersistenceContextType.EXTENDED)
protected EntityManager entityManager;
-------------- some typical action for DAO --------------
}
Second DAO is for ClassB and looks similar to DaoA. The rest of things are done for me by the Spring framework.
When I'm debugging the application I recognize that both DAO objects have different instances of EntityManager. In the result my two different DAOs are connected with different PersistenceContext.
Question is if this is correct behaviour or not? I would like to have the same PersistenceContext for all my DAO classes. Please give me a hint if this is possible and if I understood the JPA correctly?
Regards Hsd
It's a correct behaviour of EXTENDED persistence context, therefore you don't need it to be EXTENDED in this case.
In most cases you need a TRANSACTIONAL persistence context, that is the default mode when type is omitted:
#PersistenceContext(name="my.persistence")
protected EntityManager entityManager;
In this mode persistence context is associated with the transaction, so that all DAOs will share the same persistence context when working inside the same transaction. I guess it's what you need.

JPA and DAO - what's the standard approach?

I'm developing my first app with JPA/Hibernate and Spring. My first attempt at a DAO class looks like this:
#Repository(value = "userDao")
public class UserDaoJpa implements UserDao {
#PersistenceContext
private EntityManager em;
public User getUser(Long id) {
return em.find(User.class, id);
}
public List getUsers() {
Query query = em.createQuery("select e from User e");
return query.getResultList();
}
}
I also found some examples using JpaDaoSupport and JpaTemplate. Which design do you prefer? Is there anything wrong with my example?
I'd say your approach looks totally sound. Personally I don't use JpaDaoSupport or JpaTemplate because you can do everything you need with the EntityManager and Criteria Queries.
Quote from the JavaDoc of JpaTemplate:
JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering the same style for people used to it. For newly started projects, consider adopting the standard JPA style of coding data access objects instead, based on a "shared EntityManager" reference injected via a Spring bean definition or the JPA PersistenceContext annotation.
I prefer the template-less approach (i.e. your current approach) because
it's less invasive, you don't tie DAOs to Spring
templates don't offer much value with APIs that use unchecked exceptions
And this is the Spring recommendation, as summarized in the blog post "So should you still use Spring's HibernateTemplate and/or JpaTemplate??" and the official javadoc:
The real question is: which approach to choose??
(...)
So in short (as the JavaDoc for
HibernateTemplate and
JpaTemplate already mention)
I'd recommend you to start using the
Session and/or EntityManager API
directly if you're starting to use
Hibernate or JPA respectively on a new
project–remember: Spring tries to be
non-invasive, this is another great
example!
I, personally, prefer your approach - inject EntityManager and use it directly. But JpaTemplate is also a good option. I don't like it, because adds yet another, unnecessary layer of abstraction.
I don't know if there's a "standard" approach.
If you're using JPA, you have your choice of implementations: Hibernate, TopLink, etc.
If you deploy to Google App Engine, you'll use JPA talking to BigTable.
So if your objectives are to maximize portability, stick with the JPA standard, and not tie yourself to a particular implementation like Hibernate, make sure that your DAOs only use JPA constructs.

Resources