【问题标题】:JPA - transactions not being committedJPA - 未提交的事务
【发布时间】:2011-03-13 12:59:29
【问题描述】:

我正在做一个项目,在该项目中我第一次使用 JPA、Hibernate 和所有这些东西,但我遇到了事务未提交的问题。我使用的类 User 看起来像这样:

 package org.tomasherman.JBTBackup.Resource.Entity;

import javax.persistence.*;
import java.io.Serializable;



@Entity
@Table(name = "users")
public class User implements Serializable {
    @Id
    @GeneratedValue
    private int id;

    private String login;
    private String email;
    private String password;
    private int credit;

    public User() {
    }

    public User(String login, String email, String password, int credit) {
        setLogin(login);
        setEmail(email);
        setPassword(password);
        setCredit(credit);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getCredit() {
        return credit;
    }

    public void setCredit(int credit) {
        this.credit = credit;
    }
}

并使用 HSQL 数据库将其持久化到 MEMORY 表中。 persistence.xml 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<persistence-unit name="JBTBackupPersistance">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>org.tomasherman.JBTBackup.Resource.Entity.User</class>
    <properties>
        <property name="hibernate.connection.url" value="jdbc:hsqldb:file:./database/database.hsql"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
        <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
        <property name="hibernate.connection.username" value="SA"/> <!--default hsql login-->
        <property name="hibernate.connection.password" value=""/>
        <property name="hibernate.archive.autodetection" value="class"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="connection.shutdown" value="true"/>
    </properties>
</persistence-unit>

并在 JUnit 测试中对其进行测试,如下所示:

package org.tomasherman.JBTBackup.Resource.Entity;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * Created by IntelliJ IDEA.
 * User: arg
 * Date: Jun 29, 2010
 * Time: 11:24:35 PM
 * To change this template use File | Settings | File Templates.
 */

public class UserTest {
    private EntityManagerFactory emf;
    private EntityManager em;

    private final User u1 = new User("and","now","for",1234);
    private final User u2 = new User("something","completely","different",123123123);
    private final User u3 = new User("a","man","with",123123123);

    @Before
    public void initEmfAndEm() {
        emf = Persistence.createEntityManagerFactory("JBTBackupPersistance");
        em = emf.createEntityManager();
    }

    @After
    public void cleanup() {
        em.close();
    }

    @Test
    public void emptyTest() {
        System.out.println(em.createQuery("from User").getResultList().size());
        if(em.getTransaction().isActive()){
            System.out.println("FFfffffffffFFFFUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU");
            System.out.println("FFfffffffffFFFFUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU");
            System.out.println("FFfffffffffFFFFUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU");
            System.out.println("FFfffffffffFFFFUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU");
            System.out.println("FFfffffffffFFFFUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU");
        }else{
            em.getTransaction().begin();
            em.persist(u1);
            em.persist(u2);
            em.persist(u3);         
        em.getTransaction().commit();
        }
        System.out.println(em.createQuery("from User").getResultList().size());

    }
}

现在的问题是插入经常没有写入数据库。测试的输出如下所示:

    ...some hibernate stuff...
Hibernate: 
    select
        user0_.id as id0_,
        user0_.credit as credit0_,
        user0_.email as email0_,
        user0_.login as login0_,
        user0_.password as password0_ 
    from
        users user0_
20
Hibernate: 
    insert 
    into
        users
        (id, credit, email, login, password) 
    values
        (null, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        users
        (id, credit, email, login, password) 
    values
        (null, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        users
        (id, credit, email, login, password) 
    values
        (null, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id0_,
        user0_.credit as credit0_,
        user0_.email as email0_,
        user0_.login as login0_,
        user0_.password as password0_ 
    from
        users user0_
23

所以实体在数据库的内存中,但是当我在单元测试后检查数据库时,没有数据。但是,它会不时提交。

如果有人可以帮助我,那就太好了。

编辑: 如果它可以帮助任何人,有一个库版本列表(以 maven 格式):

<dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.0</version>
  </dependency>
  <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>20040616</version>
  </dependency>
  <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.0.0</version>
  </dependency>
  <dependency>
      <groupId>hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.4.0.GA</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.6.0</version>
  </dependency>
  <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-search</artifactId>
      <version>3.1.0.GA</version>
  </dependency>
  <dependency>
      <groupId>hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.0.5</version>
  </dependency>
  <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>
  </dependency>

更新2: 另一个有趣的事情是,如果我添加 Thread.sleep(1000);在测试结束时,所有事务都被提交。会不会是程序完成得更快,然后数据库才能更新?

【问题讨论】:

    标签: hibernate jpa hsqldb


    【解决方案1】:

    根据 HSQLDB 用户指南:

    Closing the Database

    从 1.7.2 版开始,正在进行中 数据库不再关闭时 到数据库的最后一个连接是 通过 JDBC [和数据显式关闭 不写入磁盘],显式 SHUTDOWN 命令是必需的 [in 为了保持数据持久]。在 1.8.0,可以指定连接属性shutdown=true 第一次连接数据库 (打开的连接 数据库)强制关闭时 最后一个连接关闭。

    因此,要么通过本机查询发送 SHUTDOWN 命令,要么将 ;shutdown=true 添加到连接字符串:

    jdbc:hsqldb:file:./database/database.hsql;shutdown=true
    

    关于write_delay 的问题,不,将其设置为0 不会在单元测试上下文中引起问题(它“只是”对性能有影响)。实际上,我希望 shutdown=true 就足够了,如文档中所述:

    Application Development and Testing

    ...

    如果您不想运行服务器 实例,并且您需要持久性 在不同过程中的测试之间, 那么你应该使用file: 数据库。您可以使用 shutdown=true 连接属性到 确保数据库完全持久化 连接关闭后。一个 替代选择是使用 hsqldb.write_delay=false 连接 属性,但这稍慢 比其他选项。

    据报道,一些数据 访问框架不会全部关闭 他们连接到数据库之后 测试。在这种情况下,您 如果您需要使用零写入延迟 希望数据在结束时保持不变 测试

    但我猜你正面临第二段中描述的情况。我想知道数据访问层是否真的有罪。

    【讨论】:

    • Nit:我认为 shutdown=true 仅适用于 HSQLDB >= 1.8,但答案是正确的,根据 sourceforge 上的文档:hsqldb.sourceforge.net/doc/guide/ch01.html#N101DB
    • 嗯,我根据您的建议更新了 jdbc url,但没有任何区别,除了我认为 与您的建议相同.谢谢你的帖子
    • @Arg Doh!我没有发现hibernate.connection.shutdown。与以前版本的 hsqldb (1.8.0.10) 有相同的行为吗?由于您使用的是 maven,因此应该很容易测试。我无法重现该问题。
    • 其实我想我明白了。在 database.hsql.script 中设置“SET FILES WRITE DELAY 500”,我将其更改为“SET FILES WRITE DELAY 0”,它现在似乎正在工作。您认为这会导致问题吗?
    【解决方案2】:

    您需要调用一次,而不是调用两次em.getTransaction(),并保存对它的引用。每次你调用它,你都会得到一个新的事务。所以你开始一个,然后提交一个单独的。

    【讨论】:

    • 这不是真的。第二个调用为您提供 当前 事务。代码是正确的。
    • 是的,我实际上尝试了保存交易和使用代码中显示的方法,但没有任何区别,但感谢您的帖子:]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 2015-12-17
    • 2016-08-30
    • 2017-06-17
    • 1970-01-01
    • 2015-07-24
    相关资源
    最近更新 更多