具有 iner 类异常的休眠 SQlite 映射类 数据库文件已锁定(数据库已锁定)



我需要将对象映射到一个内部对象,该内部对象具有多个内部对象或内部数组。

从这个答案

{  
"id":1,
"zip_code":"0001",
"user":{  
"data":{  
"id":1,
"username":"user",
"email":"user@gmail.com"
}
}
}

如果我评论对象字段并且只留下 zipCode 和 id 都可以正常工作。

StackOverflow说SQLite应该有1个打开的会话 所以我将hibernate.connection.pool_size设置为 1,这样它就会抛出

Java/Hibernate - Exception: The internal connection pool has reached its maximum size and no connection is currently available

但那是昨天。今天我又有"锁定例外"。
我认为级联的问题。当休眠尝试保存第一个主实体时,它应该保存用户,但数据库已经锁定,结果,它会抛出异常。 即使我是对的,我也不知道如何避免它。我尝试使用 MERGE 级联类型,但它在我的情况下不起作用。

将项目添加到 git 存储库 https://github.com/JoaoMunozIII/hibernate

更多信息如下。

在此 sql 查询之后

Hibernate: select mainentity_.mId, mainentity_.mZipCode as mZipCode2_0_ from main_entity mainentity_ where mainentity_.mId=?
Hibernate: select next_val as id_val from hibernate_sequence
Hibernate: update hibernate_sequence set next_val= ? where next_val=?

我得到了这个例外 [SQLITE_BUSY] 数据库文件已锁定(数据库已锁定)

org.hibernate.exception.LockAcquisitionException: error performing isolated work
at dialect.SQLiteDialect$3.convert(SQLiteDialect.java:197)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
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.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:218)
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.cascade(Cascade.java:104)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:414)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:252)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:638)
at DAO.saveEntityDb(DAO.java:16)
at Main.main(Main.java:32)
Caused by: org.sqlite.SQLiteException: [SQLITE_BUSY]  The database file is locked (database is locked)
at org.sqlite.core.DB.newSQLException(DB.java:909)
at org.sqlite.core.DB.newSQLException(DB.java:921)
at org.sqlite.core.DB.throwex(DB.java:886)
at org.sqlite.core.DB.exec(DB.java:155)
at org.sqlite.jdbc3.JDBC3Connection.commit(JDBC3Connection.java:174)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:60)

在项目中。 我创建模型: 主实体类

@Entity
@Table(name = "main_entity")
public class MainEntityModel {
@Id
private Long mId;
private Long mZipCode;
@OneToOne(cascade = CascadeType.ALL, targetEntity = User.class)
@JoinColumn(name = "id", insertable = false, updatable = false)
private User mUser;
public Long getmId() {
return mId;
}
public void setmId(Long mId) {
this.mId = mId;
}
public Long getmZipCode() {
return mZipCode;
}
public void setmZipCode(Long mZipCode) {
this.mZipCode = mZipCode;
}
public User getmUser() {
return mUser;
}
public void setmUser(User mUser) {
this.mUser = mUser;
}
}

用户类

@Entity
@Table(name = "user_data")
public class User {
@OneToOne(cascade = CascadeType.ALL, targetEntity = UserEntity.class)
@JoinColumn(name="mId")
private UserEntity mData;
public UserEntity getData() {
return mData;
}
public void setmData(UserEntity mData) {
this.mData = mData;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
public User() {
}
}

用户实体类

@Entity
@Table(name = "user_entity")
public class UserEntity {
@Id
private Long mId;
private String mUsername;
public Long getmId() {
return mId;
}
public void setmId(Long mId) {
this.mId = mId;
}
public String getmUsername() {
return mUsername;
}
public void setmUsername(String mUsername) {
this.mUsername = mUsername;
}
}

休眠实用程序

public class Hibernate {
private static SessionFactory sessionFactory = null;
private static String dbPath = "D:" + File.separator + "temp.db";
public static SessionFactory getSessionFactory() {
System.out.println("factory " + sessionFactory);
if (sessionFactory == null) {
Configuration cfg = new Configuration()
.setProperty("hibernate.connection.driver_class", "org.sqlite.JDBC")
.setProperty("hibernate.dialect", "dialect.SQLiteDialect")
.setProperty("hibernate.connection.pool_size", "1")
.setProperty("hibernate.connection.url", "jdbc:sqlite:" + dbPath)
.setProperty("hibernate.connection.username", "pass")
.setProperty("hibernate.connection.password", "pass")
.setProperty("hibernate.show_sql", "true")
.setProperty("hibernate.format_sql", "false")
.setProperty("hibernate.hbm2ddl.auto", "create-drop")
.setProperty("hibernate.use_sql_comments", "false")
.addAnnotatedClass(MainEntityModel.class)
.addAnnotatedClass(User.class)
.addAnnotatedClass(UserEntity.class);
sessionFactory = cfg.buildSessionFactory();
return sessionFactory;
} else {
return sessionFactory;
}
}

和主类

public class Main {
static Long userId = 1l;
private static Long entityId = 1l;
private static Long entityZip = 1000l;
private static List<MainEntityModel> mainEntityModelList = new ArrayList();
public static void main(String[] args) {
UserEntity userEntity = new UserEntity();
userEntity.setmId(userId);
userEntity.setmUsername("User Name " + userId++);
User user = new User();
user.setmData(userEntity);
for (int i = 0; i < 5; i++) {
MainEntityModel mainEntityModel = new MainEntityModel();
mainEntityModel.setmId(entityId++);
mainEntityModel.setmUser(user);
mainEntityModel.setmZipCode(entityZip++);
mainEntityModelList.add(mainEntityModel);
}
DAO.saveEntityDb(mainEntityModelList);
System.out.println("saved");
List<MainEntityModel> savedList = DAO.getEntityDb();
for (MainEntityModel entity: savedList) {
System.out.println(entity.getmZipCode() + "t"
+ entity.getmUser().getData().getmUsername()
);
}
}
}

道类

public class DAO {
static final Session session = Hibernate.getSessionFactory().openSession();
public static void saveEntityDb(List<MainEntityModel> entityList){
Transaction tx=null;
try {
tx = session.beginTransaction();
for (MainEntityModel entity : entityList) {
session.saveOrUpdate(entity);
}
session.flush();
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
tx.rollback();
} finally{
if(session != null) {
session.close();
}
}
}
public static List<MainEntityModel> getEntityDb(){
Session session = Hibernate.getSessionFactory().openSession();
List<MainEntityModel> entityModel = session.createQuery("from MainEntityModel").list();
session.close();
return entityModel;
}
}
  1. 问题:自动生成user.id- 它与插入语句相互锁定/一致。
  2. 问题:锁定修复后,我们在输出循环中遇到NPE

溶液:

  1. 问题

    • 手动分配user.id并删除@GeneratedValue()注释。(已验证/测试)

      Main.java://or somewhere else
      ...
      user.setId(userId);
      ...
      
      User.java:
      ...
      @Id
      //!@GeneratedValue(strategy=GenerationType.AUTO)
      private Long id;
      ...
      
      • "其他地方"的一个不错的选择是:

        User.java:
        ...
        public void setmData(UserEntity mData) {
        this.mData = mData;
        if(mData == null) {
        this.id = null;
        } else {
        this.id = mData.getmId();
        }
        }
        @Id
        //!@GeneratedValue(strategy=GenerationType.AUTO)
        private Long id;
        ...
        
    • 或者:在先前/单独事务中的Perist User/UserData。喜欢。。。

      • "改进"你的DAO.java:

        public static <T extends Object> void saveEntityDb(T... entityList) {
        //local variable!
        final Session session = Hibernate.getSessionFactory().openSession();
        Transaction tx = null;
        try {
        if (session.isConnected()) {
        tx = session.beginTransaction();
        for (T entity : entityList) {
        session.saveOrUpdate(entity);
        }
        session.flush();
        tx.commit();
        }
        } catch (HibernateException ex) {
        if (tx != null && tx.getStatus().canRollback()) {
        tx.rollback();
        }
        } finally {
        if (session != null) {
        session.close();
        }
        }
        }
        
      • 并使用它两次(!

        Main.java:
        ...
        User user = new User();
        user.setmData(userEntity);
        //do this before...
        DAO.saveEntityDb(user);
        List<MainEntityModel> mainEntityModelList = ...
        //...you do this
        DAO.saveEntityDb(mainEntityModelList.toArray(new MainEntityModel[0]));
        
  2. 问题

    • 摆脱MainEntityModelJoinColumn上的insertable = false, updatable = false

。这里的OneToOne有点奇怪(@MainEntityModel),它可以工作,但用作ManyToOne(5 比 1?!

最新更新