org.hibernate.id.IdentifierGenerationException:尝试从空的一对一属性分配 id(使用 session.merge)
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property (with session.merge)
我有问题。
我的应用出现错误:org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
我的pojos
用户:
@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements Serializable {
private static final long serialVersionUID = -5415891222321582213L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "userId", length = 100)
private int userId;
...
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserDetail userDetail;
用户详细信息:
@Entity
@Table(name = "userdetail")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserDetail implements Serializable {
private static final long serialVersionUID = 2155190440305692224L;
@Id
@GenericGenerator(
name = "gen",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "user")
)
@GeneratedValue(generator = "gen")
@Column(name = "userId", length = 100)
private int userId;
...
@OneToOne
@PrimaryKeyJoinColumn
private User user;
表用户:
CREATE TABLE `user` (
`userId` INT(100) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL DEFAULT NULL,
`surname` VARCHAR(255) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`password` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
表用户详细信息
CREATE TABLE `userdetail` (
`userId` INT(100) NOT NULL,
`country` VARCHAR(255) NULL DEFAULT NULL,
`city` VARCHAR(255) NULL DEFAULT NULL,
`address` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
DAO层:
private Session session = HibernateUtil.getHibernateUtil().getSession();
@Override
public void create(T t) throws DaoException {
Object object = session.merge(t);
session.save(object);
log.info("Update: " + t);
}
服务层
private Session session = HibernateUtil.getHibernateUtil().getSession();
private Transaction transaction = null;
private Dao<T> dao = new BaseDao<T>();
@Override
public void create(T t) throws DaoException {
try {
transaction = session.beginTransaction();
dao.create(t);
transaction.commit();
log.info("Create: " + t);
} catch (HibernateException e) {
log.error("Error creating " + getPersistentClass() + " in Dao " + e);
transaction.rollback();
throw new DaoException(e);
}
}
保存用户的类
User user = new User(name, surname, email, password);
UserDetail userDetail = new UserDetail(country, city, address);
user.setUserDetail(userDetail);
userDetail.setUser(user);
userService.create(user);
HiberUtil
public class HibernateUtil {
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static HibernateUtil util = null;
private static SessionFactory sessionFactory = null;
private static final ThreadLocal<Session> sessions = new ThreadLocal<Session>();
private HibernateUtil() {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
log.info("Hibernate Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
log.info("Hibernate serviceRegistry created");
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable e) {
log.error("Initial SessionFactory creation failed. " + e);
System.exit(0);
}
}
public Session getSession () {
Session session = sessions.get();
if (session == null) {
session = sessionFactory.openSession();
sessions.set(session);
}
return session;
}
public static synchronized HibernateUtil getHibernateUtil(){
if (util == null){
util = new HibernateUtil();
}
return util;
}
}
如果我在 DAO 层中更改:
@Override
public void create(T t) throws DaoException {
session.save(t);
log.info("Create: " + t);
}
我收到错误:org.hibernate.HibernateException:非法尝试将集合与两个打开的会话相关联
所以我有 4 个问题:
如果我没理解错的话,当userdeteil save userId from User 为null 因为UserId 没有从表中获取icnrement Id,是真的吗?
是否需要session.merge
如果需要合并,如何正确org.hibernate.id.IdentifierGenerationException:试图从空的一对一属性分配 id
如果不需要合并,正确度如何"org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions"
注意:删除与合并是好的,创建与合并其他实体(不是用户也不是 UserDeteil)是好的。
要使其正常工作,请从您的 DAO class 的更新方法中删除 Object object = session.merge(t);
。这是更新的更新方法
@Override
public void update(T t) throws DaoException {
session.saveOrUpdate(t);
log.info("Update: " + t);
}
这将修复您的 org.hibernate.id.IdentifierGenerationException
异常。
- 对于第 1 点:您的记录未保存,您正在调用 merge()
方法,则传入merge方法的对象return
保存(这里)。 merger():将给定对象的状态复制到
具有相同标识符的持久对象。在你的情况下没有
持久对象。
- 对于第2点:这里不需要merge方法,使用save或者
session
的 saveOrUpdate 方法
- 对于第 3 点:N/A
这里有一个很好的例子One-To-One association mapping
我解决了我的问题。
在我的 BaseDao 和 BaseService 中,我删除了:
private Session session = HibernateUtil.getHibernateUtil().getSession();
我在 BaseDao 和 BaseService 中添加了所有方法:
HibernateUtil.getHibernateUtil().getSession();
所以我删除了这两个会话
我的方法,示例创建,变成了:
@Override
public void create(T t) throws DaoException {
HibernateUtil.getHibernateUtil().getSession().save(t);
log.info("Create: " + t);
}
我有问题。 我的应用出现错误:org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
我的pojos 用户:
@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements Serializable {
private static final long serialVersionUID = -5415891222321582213L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "userId", length = 100)
private int userId;
...
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserDetail userDetail;
用户详细信息:
@Entity
@Table(name = "userdetail")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserDetail implements Serializable {
private static final long serialVersionUID = 2155190440305692224L;
@Id
@GenericGenerator(
name = "gen",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "user")
)
@GeneratedValue(generator = "gen")
@Column(name = "userId", length = 100)
private int userId;
...
@OneToOne
@PrimaryKeyJoinColumn
private User user;
表用户:
CREATE TABLE `user` (
`userId` INT(100) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL DEFAULT NULL,
`surname` VARCHAR(255) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`password` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
表用户详细信息
CREATE TABLE `userdetail` (
`userId` INT(100) NOT NULL,
`country` VARCHAR(255) NULL DEFAULT NULL,
`city` VARCHAR(255) NULL DEFAULT NULL,
`address` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
DAO层:
private Session session = HibernateUtil.getHibernateUtil().getSession();
@Override
public void create(T t) throws DaoException {
Object object = session.merge(t);
session.save(object);
log.info("Update: " + t);
}
服务层
private Session session = HibernateUtil.getHibernateUtil().getSession();
private Transaction transaction = null;
private Dao<T> dao = new BaseDao<T>();
@Override
public void create(T t) throws DaoException {
try {
transaction = session.beginTransaction();
dao.create(t);
transaction.commit();
log.info("Create: " + t);
} catch (HibernateException e) {
log.error("Error creating " + getPersistentClass() + " in Dao " + e);
transaction.rollback();
throw new DaoException(e);
}
}
保存用户的类
User user = new User(name, surname, email, password);
UserDetail userDetail = new UserDetail(country, city, address);
user.setUserDetail(userDetail);
userDetail.setUser(user);
userService.create(user);
HiberUtil
public class HibernateUtil {
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static HibernateUtil util = null;
private static SessionFactory sessionFactory = null;
private static final ThreadLocal<Session> sessions = new ThreadLocal<Session>();
private HibernateUtil() {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
log.info("Hibernate Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
log.info("Hibernate serviceRegistry created");
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable e) {
log.error("Initial SessionFactory creation failed. " + e);
System.exit(0);
}
}
public Session getSession () {
Session session = sessions.get();
if (session == null) {
session = sessionFactory.openSession();
sessions.set(session);
}
return session;
}
public static synchronized HibernateUtil getHibernateUtil(){
if (util == null){
util = new HibernateUtil();
}
return util;
}
}
如果我在 DAO 层中更改:
@Override
public void create(T t) throws DaoException {
session.save(t);
log.info("Create: " + t);
}
我收到错误:org.hibernate.HibernateException:非法尝试将集合与两个打开的会话相关联
所以我有 4 个问题:
如果我没理解错的话,当userdeteil save userId from User 为null 因为UserId 没有从表中获取icnrement Id,是真的吗?
是否需要session.merge
如果需要合并,如何正确org.hibernate.id.IdentifierGenerationException:试图从空的一对一属性分配 id
如果不需要合并,正确度如何"org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions"
注意:删除与合并是好的,创建与合并其他实体(不是用户也不是 UserDeteil)是好的。
要使其正常工作,请从您的 DAO class 的更新方法中删除 Object object = session.merge(t);
。这是更新的更新方法
@Override
public void update(T t) throws DaoException {
session.saveOrUpdate(t);
log.info("Update: " + t);
}
这将修复您的 org.hibernate.id.IdentifierGenerationException
异常。
- 对于第 1 点:您的记录未保存,您正在调用 merge() 方法,则传入merge方法的对象return 保存(这里)。 merger():将给定对象的状态复制到 具有相同标识符的持久对象。在你的情况下没有 持久对象。
- 对于第2点:这里不需要merge方法,使用save或者 session 的 saveOrUpdate 方法
- 对于第 3 点:N/A
这里有一个很好的例子One-To-One association mapping
我解决了我的问题。 在我的 BaseDao 和 BaseService 中,我删除了:
private Session session = HibernateUtil.getHibernateUtil().getSession();
我在 BaseDao 和 BaseService 中添加了所有方法:
HibernateUtil.getHibernateUtil().getSession();
所以我删除了这两个会话 我的方法,示例创建,变成了:
@Override
public void create(T t) throws DaoException {
HibernateUtil.getHibernateUtil().getSession().save(t);
log.info("Create: " + t);
}