I´m new to JPA. I´m developing an application which uses JPA (Hibernate implementation) and Spring. I´ve declared a persistence unit in my persistence.xml and configuration about EntityManagerFactory in my Spring config files. Something like this:
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="my.package" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
Then I have some DAOs where I inject the entityManager with the @PersistenceContext annotation:
public MyDaoImpl implements MyDao{
private EntityManager entityManager;
@PersistenceContext
private void setEntityManager(EntityManager em){
this.entityManager = em;
}
}
And finally, I have some services where DAOs are injected (by @Autowired Spring's annotation):
public MyServiceImpl implements MyService{
@Autowired
private MyDao myDao;
public List<MyEntity> readOperation(){
//
return myDAo.searchAll();
}
}
As its a read only operation I thought it wasn´t needed the @Transactional annotation, but without it, there is an exception:
java.lang.IllegalStateException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:223)
at $Proxy121.unwrap(Unknown Source)
I´ve read some other posts like this: java.lang.IllegalStateException: No transactional EntityManager available
And all is said is that the transactional annotation is needed. It´s true that it works with it, but I´d like to know (and why) if all methods (even read only operations) must be transactional.
A JPA Transaction is needed for all your methods - essentially a transaction is what opens a Hibernate session, and you need an open session to interact with it.
You can annotate the transactions as readonly or readwrite, and you can also annotate at the class level to save you annotating each method. For example:
@Transactional(readOnly = true)
public MyDaoImpl implements MyDao{
private EntityManager entityManager;
@PersistenceContext
private void setEntityManager(EntityManager em){
this.entityManager = em;
}
@Transactional(readOnly = false)
public void saveItem(MyEntity entity) {
}
public List<MyEntity> searchAll() {
}
}
You a need a transaction for all operations that change anything in DB (the only exception is SELECT queries, without locking). Check this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With