我需要将对象映射到一个内部对象,该内部对象具有多个内部对象或内部数组。
从这个答案
{
"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;
}
}
- 问题:自动生成
user.id
- 它与插入语句相互锁定/一致。 - 问题:锁定修复后,我们在输出循环中遇到NPE
溶液:
-
问题
-
手动分配
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]));
-
-
-
问题
- 摆脱
MainEntityModel
JoinColumn
上的insertable = false, updatable = false
。
- 摆脱
。这里的OneToOne
有点奇怪(@MainEntityModel
),它可以工作,但用作ManyToOne
(5 比 1?!