休眠级联持续存在:执行隔离工作时出错
Posted
技术标签:
【中文标题】休眠级联持续存在:执行隔离工作时出错【英文标题】:Hibernate cascade persist: error performing isolated work 【发布时间】:2016-12-04 13:42:58 【问题描述】:@ManyToOne
与 Hibernate 和 SQLite 的双向关系存在一些问题。实体是人:
@Entity
public class Person
@Id
@GeneratedValue
private Long id;
@ManyToOne
private Company company;
public void setCompany(Company company)
this.company = company;
和公司:
@Entity
public class Company
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "company", cascade = CascadeType.PERSIST )
private Set<Person> staff = new HashSet<>();
public void addPerson(Person person)
if (staff.add(person))
person.setCompany(this);
在一个简单的应用程序中,我使用公司创建了一个初始数据库,之后我打开一个新会话来加载公司实例并添加员工。我坚持公司并期望 Hibernate 坚持在cascade
中添加的人员。
public class App
public static void main(String[] args)
createDatabase();
Session session = createSessionFactory("validate").openSession();
Company company;
session.beginTransaction();
company = (Company) session.createCriteria(Company.class).uniqueResult();
session.getTransaction().commit();
company.addPerson(new Person());
session.beginTransaction();
session.persist(company);
session.getTransaction().commit();
private static void createDatabase()
Session session = createSessionFactory("create").openSession();
Company company = new Company();
session.beginTransaction();
session.persist(company);
session.getTransaction().commit();
session.close();
private static SessionFactory createSessionFactory(String ddl)
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder()
.configure("hibernate.cfg.xml");
serviceRegistryBuilder
.applySetting("hibernate.hbm2ddl.auto", ddl);
SessionFactory sessionFactory = new MetadataSources(serviceRegistryBuilder.build())
.buildMetadata()
.buildSessionFactory();
return sessionFactory;
但我得到了错误:
ERROR: database is locked
Exception in thread "main" org.hibernate.exception.GenericJDBCException: error performing isolated work
如果我在加入公司之前坚持这个人(所以没有级联),应用程序就可以工作。
我做错了什么?
这是完整的应用程序日志:
июл 29, 2016 9:07:57 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core 5.1.0.Final
июл 29, 2016 9:07:57 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
июл 29, 2016 9:07:57 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
июл 29, 2016 9:07:57 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations 5.0.1.Final
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.sqlite.JDBC] at URL [jdbc:sqlite:default.sqlite]
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: user=, password=****
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
июл 29, 2016 9:07:57 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.SQLiteDialect
июл 29, 2016 9:07:57 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [2] less than 4
июл 29, 2016 9:07:57 PM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.0.Final
Hibernate:
drop table if exists Company
Hibernate:
drop table if exists hibernate_sequence
Hibernate:
drop table if exists Person
Hibernate:
create table Company (
id bigint not null,
primary key (id)
)
Hibernate:
create table hibernate_sequence (
next_val bigint
)
Hibernate:
insert into hibernate_sequence values ( 1 )
Hibernate:
insert into hibernate_sequence values ( 1 )
Hibernate:
create table Person (
id bigint not null,
company_id bigint,
primary key (id)
)
июл 29, 2016 9:07:58 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@43f82e78'
Hibernate:
select
next_val as id_val
from
hibernate_sequence
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
insert
into
Company
(id)
values
(?)
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.sqlite.JDBC] at URL [jdbc:sqlite:default.sqlite]
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: user=, password=****
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
июл 29, 2016 9:07:59 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.SQLiteDialect
июл 29, 2016 9:07:59 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [2] less than 4
Hibernate:
select
this_.id as id1_0_0_
from
Company this_
Hibernate:
select
personal0_.company_id as company_2_1_0_,
personal0_.id as id1_1_0_,
personal0_.id as id1_1_1_,
personal0_.company_id as company_2_1_1_
from
Person personal0_
where
personal0_.company_id=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
июл 29, 2016 9:08:02 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 0, SQLState: null
июл 29, 2016 9:08:02 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: database is locked
Exception in thread "main" org.hibernate.exception.GenericJDBCException: error performing isolated work
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:79)
at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:125)
at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:412)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:105)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:768)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:761)
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:297)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:316)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:424)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:356)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:104)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:172)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:164)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:778)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:751)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:756)
at my.tests.hibernate.App.main(App.java:29)
Caused by: java.sql.SQLException: database is locked
at org.sqlite.core.DB.throwex(DB.java:859)
at org.sqlite.core.DB.exec(DB.java:142)
at org.sqlite.jdbc3.JDBC3Connection.commit(JDBC3Connection.java:165)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:60)
... 26 more
更新似乎,这是一个 Hibernate-SQLite 问题,因为如果我更改 H2 上的数据库,一切正常。
【问题讨论】:
【参考方案1】:可以尝试添加strategy
,生成id:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
【讨论】:
以上是关于休眠级联持续存在:执行隔离工作时出错的主要内容,如果未能解决你的问题,请参考以下文章