简体   繁体   中英

How entity manager read new record inserted by others

My application use JPA/hibernate to read data from database. 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 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:

                   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.

  2. em.close() does not implicit commit or rollback the transaction, ie, the JDBC connection and transaction is still alive/open. This is what I misunderstood. (emf.close() will actually close the connection.)

  3. When you get EntityManager from emf.createEntityManager(), the new EntityManager may reuse old JDBC connection. It means that you may in the transaction opened by previous closed EntityManager.

  4. When you are in a uncommit/opened transaction, and use the default MySQL isolation level, you cannot see change made by others.

Solution: explicit open and commit the transaction, or tell Hibernate to allow autocommitted JDBC connections. Refs: Select using hibernate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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