Hibernate/JPA cascade='persist' causes an "error performing isolated work"

1,028 views
Skip to first unread message

Sergei D.

unread,
Jul 30, 2016, 5:54:11 PM7/30/16
to Xerial
Hello.

I have a some error "Database is locked. Error performing isolated work." when using cascade = 'persist' in Hibernate + SQLite. I have reproduced the error with a simple application. I have a entities Company and Person with the relationship @OneToMany. At first, I create the Company instance and put it into the database. After this I open a new session to load the Company, add the Person and persist the Company again. I expects that the Hibernate will persist the added Person on cascade but I got the mentioned error. So, what am I doing wrong and how to use cascade 'persist' with SQLite?

The Person class:

@Entity
public class Person {

   
@Id
   
@GeneratedValue
   
private Long id;

   
@ManyToOne
   
private Company company;

   
public void setCompany(Company company) {
       
this.company = company;
   
}
}

The Company class:

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

The test application:

public class App {

       
public static void main(String[] args) {

                createDatabase
();

               
Company company;

               
Session session = createSessionFactory("validate").openSession();

                company
= (Company) session.createCriteria(Company.class).uniqueResult();

               
Person person = new Person();
                company
.addPerson(person);

                session
.beginTransaction();
                session
.persist(company);
                session
.getTransaction().commit();

                session
.close();
                session
.getSessionFactory().close();
       
}

       
private static void createDatabase() {

               
Session session = createSessionFactory("create").openSession();

               
Company company = new Company();
                session
.beginTransaction();
                session
.persist(company);
                session
.getTransaction().commit();

                session
.close();
                session
.getSessionFactory().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;
       
}
}

The full error log:

 июл 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


Reply all
Reply to author
Forward
0 new messages