【问题标题】:JPA without transaction无交易的 JPA
【发布时间】:2014-07-22 00:09:05
【问题描述】:

我是 JPA 的新手。我正在开发一个使用 JPA(Hibernate 实现)和 Spring 的应用程序。我已经在我的 persistence.xml 中声明了一个持久性单元,并在我的 Spring 配置文件中对 EntityManagerFactory 进行了配置。像这样的:

<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>

然后我有一些 DAO,我在其中注入带有 @PersistenceContext 注释的 entityManager:

public MyDaoImpl implements MyDao{
   private EntityManager entityManager;

   @PersistenceContext
   private void setEntityManager(EntityManager em){
        this.entityManager = em;
    }
 } 

最后,我有一些注入 DAO 的服务(通过 @Autowired Spring 的注释):

public MyServiceImpl implements MyService{
  @Autowired
  private MyDao myDao;

  public List<MyEntity> readOperation(){
   //
   return myDAo.searchAll();
 }
}

由于它是只读操作,我认为它不需要@Transactional 注释,但没有它,会有一个例外:

java.lang.IllegalStateException: No transactional EntityManager available
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:223)
    at $Proxy121.unwrap(Unknown Source) 

我读过一些类似的帖子:java.lang.IllegalStateException: No transactional EntityManager available

据说需要事务性注释。确实可以使用它,但我想知道(以及为什么)是否所有方法(甚至只读操作)都必须是事务性的。

【问题讨论】:

    标签: java jpa transactions


    【解决方案1】:

    您的所有方法都需要 JPA 事务 - 本质上,事务是打开 Hibernate 会话的对象,您需要一个打开的会话来与之交互。

    您可以将事务注释为只读或读写,也可以在类级别进行注释以节省您对每个方法的注释。例如:

    @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() {
        }
    } 
    

    【讨论】:

      【解决方案2】:

      您需要一个事务来处理更改数据库中任何内容的所有操作(唯一的例外是 SELECT 查询,没有锁定)。检查this answer

      【讨论】:

      • 是的,我知道即使您不使用 @Transaction 注释,数据库也会为每个操作(甚至是 SELECT 查询)创建一个事务。我的问题是是否需要在我的代码中编写注释。
      猜你喜欢
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      相关资源
      最近更新 更多