Java 没有交易的JPA

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23984968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:33:41  来源:igfitidea点击:

JPA without transaction

javajpatransactions

提问by user1093643

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:

我是 JPA 的新手。我正在开发一个使用 JPA(Hibernate implementation)和 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>

Then I have some DAOs where I inject the entityManager with the @PersistenceContext annotation:

然后我有一些 DAO,在那里我用 @PersistenceContext 注释注入 entityManager:

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

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

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:

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

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

我读过其他一些类似这样的帖子: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.

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

回答by John Farrelly

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.

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

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

回答by Andrei I

You a need a transaction for all operations that change anything in DB (the only exception is SELECT queries, without locking). Check this answer.

您需要为更改数据库中的任何内容的所有操作创建一个事务(唯一的例外是 SELECT 查询,没有锁定)。检查这个答案