我需要将对象与一个内部对象进行映射,该内部对象还有一个内部对象或内部数组。
来自这个答案
{
"id":1,
"zip_code":"0001",
"user":{
"data":{
"id":1,
"username":"user",
"email":"user@gmail.com"
}
}
}
如果我评论对象字段并只留下 zipCode 和 id 则一切正常。
StackOverflow 表示 SQLite 应该有 1 个打开的 session 所以我将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 实用程序
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;
}
}
最佳答案
- 问题:自动生成
user.id
- 它与插入语句相互锁定/一致。 - 问题:锁定修复后,我们在输出循环中遇到 NPE
解决方案:
问题
手动分配
user.id
并删除@GenerateValue()
注释。 (已验证/测试)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; ...
或者:在先前/单独的事务中保留用户/用户数据。 ...就像...
“改进”你的 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]));
问题
- 删除
MainEntityModel
的JoinColumn
上的insertable = false, updatable = false
。
- 删除
...这里的 OneToOne
有点奇怪 (@MainEntityModel
) ,它可以工作,但可以用作 ManyToOne
(5 到1?!)
关于java - Hibernate SQlite映射类与内部类异常数据库文件被锁定(database is lock),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48587094/