JPA - 交易没有被提交 [英] JPA - transactions not being committed
问题描述
我正在开发一个第一次使用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屋!