我的应用程序使用JPA / hibernate从数据库中读取数据。应用程序是只读的,数据由其他程序插入。
问题是我的应用程序只能在第一次读取肉体数据。当其他程序插入新数据时,我的应用程序无法看到它。
这是我的测试代码:
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();
}
}
这是我的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>
谢谢!
答案 0 :(得分:0)
从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
默认情况下,Hibernate在自动提交模式下不起作用。
em.close()不隐式提交或回滚事务,即JDBC连接和事务仍处于活动/打开状态。 这是我误解的。 (emf.close()实际上会关闭连接。)
当您从emf.createEntityManager()获取EntityManager时,新的 EntityManager可以重用旧的JDBC连接。这意味着你可以 在先前关闭的EntityManager打开的事务中。
当您处于未提交/已打开的事务中时,使用默认值 MySQL隔离级别,你看不到别人做出的改变。
解决方案:显式打开并提交事务,或告诉Hibernate允许自动提交的JDBC连接。参考:Select using hibernate