JPA - 交易没有被提交 [英] JPA - transactions not being committed

查看:112
本文介绍了JPA - 交易没有被提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个第一次使用JPA,Hibernate和所有这些东西的项目,并且遇到了未提交的事务问题。我使用类似这样的用户:

  package org.tomasherman.JBTBackup.Resource.Entity; 

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




$ b @Entity
@Table(name =users)
public class User实现Serializable {
@Id
@GeneratedValue
private int id;

私人字符串登录;
私人字符串电子邮件;
私人字符串密码;
私人信贷;
$ b $ 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.0encoding =UTF-8? > 




 < persistence-unit name =JBTBackupPersistance> 
< provider> org.hibernate.ejb.HibernatePersistence< / provider>
< class> org.tomasherman.JBTBackup.Resource.Entity.User< / class>
<属性>
< property name =hibernate.connection.urlvalue =jdbc:hsqldb:file:./ database / database.hsql/>
< property name =hibernate.dialectvalue =org.hibernate.dialect.HSQLDialect/>
< property name =hibernate.connection.driver_classvalue =org.hsqldb.jdbcDriver/>
< property name =hibernate.connection.usernamevalue =SA/> <! - 默认hsql登录 - >
< property name =hibernate.connection.passwordvalue =/>
< property name =hibernate.archive.autodetectionvalue =class/>
< property name =hibernate.show_sqlvalue =true/>
< property name =hibernate.format_sqlvalue =true/>
< property name =connection.shutdownvalue =true/>
< / properties>
< / persistence-unit>



并在JUnit测试中进行测试看起来像这样:

  package org.tomasherman.JBTBackup.Resource.Entity; 

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

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

/ **
*由IntelliJ IDEA创建。
*用户:arg
*日期:2010年6月29日
*时间:11:24:35 PM
*要更改此模板,请使用文件|设置|文件模板。
* /

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

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

@Test
public void emptyTest(){
System.out.println(em.createQuery(from User)。getResultList()。size ());
如果(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());





$ b现在问题在于插入通常不会写入数据库。测试的输出如下所示:

  ...一些hibernate的东西... 
Hibernate:
选择
user0_.id为id0_,
user0_.credit为credit0_,
user0_.email为email0_,
user0_.login为login0_,
user0_.password为password0_
from
users user0_
20
Hibernate:

插入
用户
(id,credit,email,login ,密码)

(空,?,?,?,?)
Hibernate:

插入
用户
(id ,信用卡,电子邮件,登录名,密码)

(空,?,?,?,?)
Hibernate:

插入
用户
(id,credit,email,login,password)
values
(null,?,?,?,?)
Hibernate:
select
user0_.id as id0_,
user0_.credit as credit0_,
user0_.email as e mail0_,
user0_.login as login0_,
user0_.password as password0_
from
users user0_
23

所以实体位于数据库的内存中,但是当我在单元测试后检查数据库时,没有数据。然而,它会不时地承诺。



如果任何人都可以帮助我,那就太棒了。

<编辑:
以防万一,有一个库文件列表(以maven格式):

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

UPDATE2:
另一个有趣的事情是,如果我添加Thread.sleep(1000 );在测试结束时,所有交易都会被提交。难道是程序完成得更快,那么数据库可以更新吗?根据HSQLDB用户指南:


关闭数据库



从版本1.7.2开始,当
上次连接时,进程内
数据库不再关闭数据库是通过JDBC显式关闭的
[并且数据
没有写入磁盘],需要明确的
SHUTDOWN 命令[in
为了保持数据不变]。在
1.8.0中,可以在
上指定一个连接属性 shutdown = true ,作为与数据库
的第一个连接打开
数据库的连接)在
上次连接关闭时强制关闭。


通过本地查询 SHUTDOWN 命令或向连接字符串添加 ; shutdown = true

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

$ hr

关于 write_delay 的问题, ,不,将它设置为 0 不会导致单元测试环境中的问题(它只是会影响性能)。实际上,我认为 shutdown = true 就足够了,正如文档中提到的那样:


应用程序开发和测试



...



如果您不想运行Server
实例,并且需要持久性
在不同进程中的测试之间,
则应该使用文件:
数据库。您可以将
shutdown = true 连接属性用于
,确保在连接关闭后数据库完全保持为

替代选项是使用
hsqldb.write_delay = false 连接
属性,但这比
略慢其他选项。

据报道,某些数据
访问框架在
之后不会关闭所有
与数据库的连接试验。在这种情况下,如果您的
希望数据在
结尾处持续存在,那么您
需要使用零WRITE DELAY


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


i'm working on a project in which i use JPA, Hibernate and all this stuff for the first time and i ran into problem with transactions not being committed. I use class User which looks like this:

 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;
    }
}

and use HSQL database to persist it in MEMORY table. The persistence.xml file looks like this:

<?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>

and test it in JUnit test which looks like this:

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());

    }
}

Now the problem is that the insert is quite often not written into the database. The output of test looks like this:

    ...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

so the entites are in the memory of the database, but when i check the database after the unit test, there are no data. It, however, gets committed from time to time.

If anyone could help me, it would be fantastic.

EDIT: in case it would help anyone, there is a list of libraries versions(in maven format):

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

UPDATE2: Another interesting thing, it seems that if i add Thread.sleep(1000); at the end of the test, all transactions get committed. Could it be that the program finishes faster then the database can be update?

解决方案

According to the HSQLDB user guide:

Closing the Database

From version 1.7.2, in-process databases are no longer closed when the last connection to the database is explicitly closed via JDBC [and data are not written to disk], an explicit SHUTDOWN command is required [in order to keep data persistent]. In 1.8.0, a connection property, shutdown=true, can be specified on the first connection to the database (the connection that opens the database) to force a shutdown when the last connection closes.

So either send that SHUTDOWN command through a native query or add ;shutdown=true to the connection string:

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


Regarding the question about write_delay, no, setting it to 0 won't cause a problem in a unit testing context (it "just" has an impact on performances). Actually, I would have expect shutdown=true to be enough as mentioned in the documentation:

Application Development and Testing

...

If you do not want to run a Server instance, and you need persistence between tests in different processes, then you should use a file: database. You can use the shutdown=true connection property to ensure the database is persisted fully after the connections are closed. An alternative option is to use hsqldb.write_delay=false connection property, but this is slightly slower than the other option.

It has been reported that some data access frameworks do not close all their connection to the database after the tests. In such situations, you need to use zero WRITE DELAY if you want the data to persist at the end of the tests

But I guess that you are facing the situation described in the second paragraph. I wonder if the data access layer is really guilty though.

这篇关于JPA - 交易没有被提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆