简体   繁体   English

实体管理员如何读取他人插入的新记录

[英]How entity manager read new record inserted by others

My application use JPA/hibernate to read data from database. 我的应用程序使用JPA / hibernate从数据库读取数据。 The application is read only, and data is inserted by other program. 该应用程序是只读的,并且数据是由其他程序插入的。

The problem is that my application can only read flesh data in the first time. 问题是我的应用程序只能在第一时间读取肉数据。 When new data is inserted by other program, my application cannot see it. 当其他程序插入新数据时,我的应用程序看不到它。

Here is my test code: 这是我的测试代码:

public class TestJpaRead {
   private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa");

   public static void main(String[] args) {
       LOG.debug("first time");
       countRow();   //output row size = X

       //set break point here, and manually insert an new row by using mysql client

       LOG.debug("second time");
       countRow();   //should output row size = X + 1, but it is still X
   }

   public static void countRow() {
       EntityManager em = emf.createEntityManager();
       Query query = em.createQuery("SELECT a FROM " + Report.class.getSimpleName() + " a");
       List result = query.getResultList();
       LOG.debug("countRow: {}", result.size());
       em.close();
   }
}

and here is my persistence.xml (nothing special): 这是我的persistence.xml(没什么特别的):

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
         version="2.0">

<persistence-unit name="org.hibernate.tutorial.jpa" transaction-type="RESOURCE_LOCAL">
    <description>
        Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide
    </description>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <properties>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/foo" />
        <property name="javax.persistence.jdbc.user" value="root" />
        <property name="javax.persistence.jdbc.password" value="bar" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.hbm2ddl.auto" value="auto" />
    </properties>

</persistence-unit>

Thanks! 谢谢!

From MySQL query log, I find the reason of the problem: 从MySQL查询日志中,我发现了问题的原因:

                   48 Query SET autocommit=0
140606 11:35:41    48 Query select report0_.id from Report report0_  /*countRow()*/
                   48 Query SHOW WARNINGS
140606 11:35:42    48 Query select report0_.id from Report report0_  /*countRow()*/
                   48 Query SHOW WARNINGS
  1. Hibernate does not work in the autocommit mode by default. 默认情况下,Hibernate在自动提交模式下不起作用。

  2. em.close() does not implicit commit or rollback the transaction, ie, the JDBC connection and transaction is still alive/open. em.close()不会隐式提交或回滚事务,即JDBC连接和事务仍处于活动/打开状态。 This is what I misunderstood. 这就是我的误解。 (emf.close() will actually close the connection.) (emf.close()实际上将关闭连接。)

  3. When you get EntityManager from emf.createEntityManager(), the new EntityManager may reuse old JDBC connection. 当从emf.createEntityManager()获取EntityManager时,新的EntityManager可能会重用旧的JDBC连接。 It means that you may in the transaction opened by previous closed EntityManager. 这意味着您可以在事务中由先前关闭的EntityManager打开。

  4. When you are in a uncommit/opened transaction, and use the default MySQL isolation level, you cannot see change made by others. 当您处于未提交/已打开的事务中并且使用默认的MySQL隔离级别时,您将看不到其他人所做的更改。

Solution: explicit open and commit the transaction, or tell Hibernate to allow autocommitted JDBC connections. 解决方案:显式打开并提交事务,或告诉Hibernate允许自动提交的JDBC连接。 Refs: Select using hibernate 参考: 使用休眠选择

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM