JPA无事务操作

8

我是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;
    }
 } 

最后,我有一些服务,在这些服务中,DAOs 被注入(通过 Spring 的 @Autowired 注解):

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

所有的帖子都说需要事务注释。确实,使用它可以解决问题,但我想知道(为什么)是否所有方法(即使是只读操作)都必须是事务性的。

2个回答

4

对于所有更改DB的操作,您需要进行事务处理(唯一的例外是不带锁定的SELECT查询)。请查看此答案


是的,我知道即使您不使用@Transaction注释,数据库也会为每个操作(甚至是SELECT查询)创建一个事务。我的问题是关于是否需要在我的代码中编写该注释。 - user1093643

4

所有方法都需要使用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() {
    }
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接