java.lang.IllegalStateException:没有可用的事务性 EntityManager
Posted
技术标签:
【中文标题】java.lang.IllegalStateException:没有可用的事务性 EntityManager【英文标题】:java.lang.IllegalStateException: No transactional EntityManager available 【发布时间】:2013-01-09 11:15:32 【问题描述】:项目使用 Hibernate (JPA)、Spring 和 Maven。我的实体和 DAO 在一个单独的 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>
道:
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);
...
....
我有一个使用 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>
服务:
public class AuthServiceImpl implements AuthService
@Autowired
private UserDAO userDAO;
@Override
public void authorization()
userDAO.fooBar();
当我试图从 EntityManager 获取会话时,我发现了这个异常:
java.lang.IllegalStateException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:223)
at $Proxy121.unwrap(Unknown Source)
【问题讨论】:
so.. 你希望什么样的实体管理器可用? 对不起,我详细描述了这个问题。你的意思是?不幸的是,我是 Hibernate 的新手。 好的,感谢您提供的补充信息。当您调用该方法时,您是否在事务中并收到异常? 嗯...我认为处理事务是在自动模式下,因为我使用<tx:annotation-driven />
它说它是注释驱动的,您需要为需要进行事务处理的地方提供注释。我在您的代码中没有看到 @Transactional
注释。
【参考方案1】:
你必须用@Transactional注解包围方法:
@Transactional
public void fooBar()
//Exception from this line
Session session = getEntityManager().unwrap(Session.class);
...
并在您的 spring 的 xml 配置文件中使用以下声明启用 spring @Transactional 处理(txManager 是您的经理的 id)。
<tx:annotation-driven transaction-manager="txManager" />
【讨论】:
我已经添加了弹簧配置部分 我将该注释添加到我的测试方法中,尽管我不明白为什么,但它仍然有效。 我在@Transactional 旁边得到了 session.beginTrasaction() 的异常原因,这是一个错误!【参考方案2】:试试这个?
entityManager=entityManager.getEntityManagerFactory().createEntityManager();
Session session = (Session) entityManager.unwrap(Session.class);
【讨论】:
这对我有用,它背后的魔力是什么?为什么@PersistenceContext EntityManager entityManager
不是Transactional
而entityManager.getEntityManagerFactory().createEntityManager();
是?
我理解一下; @PersistenceContext : 用于应用程序服务器(如果没有配置,则没有事务控制)。如果您希望它具有事务性,您可以添加 @Transactional 注释以使其弹簧包装它。 createEntityManager : 用于 spring 的应用程序控制)spring 将使 entityManager 事务性(注入)。
@baybora.oren 你的意思是@Transactional @PersistenceContext private EntityManager entityManager
?这是不允许的
@baybora.oren 请看***.com/questions/27570641/…
@baybora 我真正理解的是,这里 entityManager
是明确创建的,实际上是 Application Managed Entity Managers 。 Spring 之类的容器不负责维护由它创建的EntityManager
的生命周期。但是你可以直接@Autowire
EntityManagerFactory
,因为 bean 已经在applicationContext
中配置好了。因此,这可能很简单,例如emf.createEntityManager().unwrap(Session.class)' to get
Session`【参考方案3】:
这些都不适合我,我终于发现问题是我正在创建我的方法@Transactional,而不是我需要类是@Transactional
【讨论】:
【参考方案4】:就我而言,这是另一个问题(对于那些对@Transactional 有问题的人):
@Transactional 需要动态代理才能工作。正是基于接口(JDK 代理。在这种情况下,CGLIB 不起作用)需要它的代理。因此,制作接口并通过服务实现,@Transactional注解就可以了。
【讨论】:
以上是关于java.lang.IllegalStateException:没有可用的事务性 EntityManager的主要内容,如果未能解决你的问题,请参考以下文章