Hinernate SQlite映射类与iner类异常数据库文件被锁定(数据库被锁定)

时间:2018-02-02 16:36:19

标签: java hibernate sqlite mapping hibernate-mapping

我需要使用内部对象映射对象,该内部对象具有一个内部对象或内部数组。

从这个答案

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

但是昨天。今天我再次“锁定异常” 我认为级联问题。当hibernate尝试保存第一个MainEntity时,它应该保存User,但DB已经锁定并且在结果中,它会抛出异常。 即使我是对的,我也不知道如何避免它。我尝试使用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;
    }
}

Hibernate Util

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

DAO课程

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 个答案:

答案 0 :(得分:1)

  1. 问题:user.id的自动生成 - 它与insert语句相互锁定/一致。
  2. 问题:修复锁定后,我们会在输出循环中遇到NPE
  3. 解决方案:

    1. 问题

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

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

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

        • &#34;提高&#34;你的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. 问题

      • 摆脱insertable = false, updatable = false MainEntityModel JoinColumn上的OneToOne
    3. ... MainEntityModel在这里有些奇怪(@ ManyToOne),它有效,但是用作if (!map.getBounds().contains(marker.getPosition())) { myMap.panTo(pos) } (5比1?!)