java.lang.IllegalStateException: No transactional EntityManager available

62,089

Solution 1

You must surround the method with the @Transactional annotation:

@Transactional
public void fooBar() {
   //Exception from this line
   Session session = getEntityManager().unwrap(Session.class);
   ...
}

And enable the spring @Transactional processing with the following declaration in your spring's xml configuration file (txManager is the id of the your manager).

<tx:annotation-driven transaction-manager="txManager" />

Solution 2

Try this ?

entityManager=entityManager.getEntityManagerFactory().createEntityManager();
Session session = (Session) entityManager.unwrap(Session.class);

Solution 3

None of this was working for me, I finally found that the issue was that I was making my method @Transactional instead I needed the class to be @Transactional

Share:
62,089

Related videos on Youtube

Anthony Tsivarev
Author by

Anthony Tsivarev

Updated on July 13, 2022

Comments

  • Anthony Tsivarev
    Anthony Tsivarev almost 2 years

    Project use Hibernate (JPA), Spring and Maven. My entity and DAO in a separate JAR.

    pom.xml:

    <project ...>
        ...
        <artifactId>database</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>3.5.4-Final</version>
            </dependency>
        </dependencies>    
    </project>
    

    DAO:

    public class AbstractDAO<T extends BaseEntity> implements GenericDAO<T> {
    
    
        private final Class<T> persistentClass;
    
        private EntityManager entityManager;
    
        public AbstractDAO(Class<T> entityClass) {
            super();
            this.persistentClass = entityClass;
        }
    
        @PersistenceContext
        public void setEntityManager(EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
    
        public EntityManager getEntityManager() {
            return entityManager;
        }
    
        ...
    
        public void fooBar() {
           //Exception from this line
           Session session = getEntityManager().unwrap(Session.class);
           ...
        }
    
        ....
    

    }

    I have a module, which use Spring.

    pom.xml:

    <project ...>
    ...
    <artifactId>api</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        ....
    </dependencies>
    
     ...    
    </project>
    

    AppContext.xml:

    <bean id="authService" scope="singleton" class="com.test.management.AuthServiceImpl" />
    
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" name="EntityManagerFactory">
            <property name="persistenceUnitName" value="default"></property>
            <property name="dataSource" ref="dataSource"></property>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="showSql" value="true" />
                    <property name="generateDdl" value="true" />
                    <property name="databasePlatform" value="${db.dialect}" />
                </bean>
            </property>     
        </bean>
    
        <!-- Values are defined in db.properties -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${db.driver}" />
            <property name="url" value="${db.url}" />
            <property name="username" value="${db.username}" />
            <property name="password" value="${db.password}" />
        </bean>
    
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" name="TransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"></property>
        </bean>
    
        <tx:annotation-driven />
    
        <bean id="userDAO" scope="singleton" class="com.test.database.dao.impl.UserDAOImpl">
        </bean>
    
    
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    
    </beans> 
    

    Service:

    public class AuthServiceImpl implements AuthService {
    
        @Autowired
        private UserDAO userDAO;
    
    
        @Override
        public void authorization() {
            userDAO.fooBar();
    
        }
    }
    

    When I'm trying to get the session from EntityManager, I catch this exception:

    java.lang.IllegalStateException: No transactional EntityManager available
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:223)
        at $Proxy121.unwrap(Unknown Source) 
    
    • eis
      eis over 11 years
      so.. what kind of entity manager you expect to be available?
    • Anthony Tsivarev
      Anthony Tsivarev over 11 years
      Sorry, I described in detail the question. What do you mean? Unfortunately, I'm new to Hibernate.
    • eis
      eis over 11 years
      Ok, thank you for the added information. Are you within a transaction when you call the method, getting the exception?
    • Anthony Tsivarev
      Anthony Tsivarev over 11 years
      Well... I thought that working with a transaction is in automatic mode, because i use <tx:annotation-driven />
    • eis
      eis over 11 years
      it says it's annotation driven, you'll need to provide annotations to places that you need to be transactional. I don't see @Transactional annotations in your code.
  • poussma
    poussma almost 11 years
    i have added the piece of spring configuration
  • daydreamer
    daydreamer almost 10 years
    This works for me, what is the magic behind it? why @PersistenceContext EntityManager entityManager is not Transactional but entityManager.getEntityManagerFactory().createEntityManager(‌​); is?
  • baybora.oren
    baybora.oren almost 10 years
    Shortly for my understanding; @PersistenceContext : is for application server usage (without transaction control if nothing configured). If you want it transactional you can add @Transactional annotation to make spring wrap it. createEntityManager : is for application control by spring) spring will make entityManager transactional (inject).
  • VB_
    VB_ over 9 years
    @baybora.oren do you mean @Transactional @PersistenceContext private EntityManager entityManager? That's not allowed
  • VB_
    VB_ over 9 years
    @baybora.oren look at stackoverflow.com/questions/27570641/… please
  • baybora.oren
    baybora.oren over 9 years
    @V_B @PersistenceContext private EntityManager entityManager; we cant use @Transactional because of before transactional proxy created we create entity manager.
  • Shafin Mahmud
    Shafin Mahmud about 7 years
    @baybora what I actually understand, Here entityManager is being created explicitly, that is actually Application Managed Entity Managers . Container like Spring is not resposible for maintaing the life cycle for the EntityManager created from it. But you can @Autowire EntityManagerFactory directly as the bean is already configured in the applicationContext. Hence this could be simple like this emf.createEntityManager().unwrap(Session.class)' to get Session`
  • djangofan
    djangofan over 6 years
    I added that annotation to my Test method, and it works although i dont understand why.
  • Mohammadreza Khatami
    Mohammadreza Khatami over 5 years
    I got this exception cause of session.beginTrasaction() beside @Transactional which was a mistake!
  • royatirek
    royatirek over 3 years
    It leaks connections. I have tested this code. We need to manage it manually.