org.hibernate.id.IdentifierGenerationException:尝试从null一对一属性中分配id(使用session.merge)

时间:2015-01-08 09:36:07

标签: java hibernate one-to-one

我有问题。 我的应用程序出错: org.hibernate.id.IdentifierGenerationException:尝试从null一对一属性中分配id

我的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;

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
;

表UserDetail

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个问题:

  1. 如果我理解正确,当userdeteil从User保存userId为null因为UserId没有从Table获得icnrement Id,那是真的吗?

  2. 此处是否需要session.merge

  3. 如果需要合并,org.hibernate.id.IdentifierGenerationException:如何尝试从null一对一属性中分配id

  4. 如果不需要合并,有多正确“org.hibernate.HibernateException:非法尝试将集合与两个打开的会话相关联”

  5. 注意:合并的Delet是好的,使用merge创建其他Entity(不是User而不是UserDeteil)是好的。

2 个答案:

答案 0 :(得分:0)

要使其正常运行,请从DAO类的update方法中删除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方法返回的对象 保存(在这里)。 merger():将给定对象的状态复制到 具有相同标识符的持久对象。在你的情况下没有 持久对象。
  • 对于第2点:此处不需要合并方法,请使用save或 带会话的saveOrUpdate方法
  • 第3点:N / A

以下是One-To-One association mapping

的一个很好的例子

答案 1 :(得分:0)

我解决了我的问题。 在我的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);
}