Hibernate:尝试从null一对一属性中分配id:employee

Paw*_*wan 29 hibernate exception one-to-one

这是我的数据库结构,MySQL中的一对一映射:

DB Schema

这是我的java文件:

public class Employee {

private EmployeeDetail empdetail;
private String firstname;
private String lastname;

// getters and setters 

}


public class EmployeeDetail {
    private Employee employee ;
    private int employee_id;
    private String street;
    private String city;
    private String state;
    private String country;

// getters and setters 

}
Run Code Online (Sandbox Code Playgroud)

这是我的映射文件:

<hibernate-mapping>

     <class name="Employee" table="employee">
        <id name="employee_id"  type="java.lang.Integer"  column="employee_id">
            <generator class="assigned" />
        </id>
        <one-to-one name="empdetail" class="EmployeeDetail"
            cascade="all"></one-to-one>

        <property name="firstname" type="java.lang.String" column="firstname" />
        <property name="lastname" type="java.lang.String" column="lastname" />

    </class>



 <class name="EmployeeDetail" table="employeedetail">
        <id name="employee_id" type="java.lang.Integer"  column="employee_id">
       <generator class="foreign">
                <param name="property">employee</param>
            </generator>
        </id>
        <one-to-one name="employee" class="Employee"
            cascade="save-update"></one-to-one>

        <property name="street"  type="java.lang.String" column="street" />
        <property name="city" type="java.lang.String" column="city" />
        <property name="state" type="java.lang.String" column="state" />
        <property name="country" type="java.lang.String" column="country" />

 </class>

</hibernate-mapping>
Run Code Online (Sandbox Code Playgroud)

这是我的客户端程序:

Session session = factory.openSession();
        Transaction tx = session.beginTransaction();

        EmployeeDetail edetail = new EmployeeDetail();
        edetail.setCity("Hyd");
        edetail.setCountry("India");
        edetail.setEmployee_id(222);
        edetail.setState("Andhra Pradesh");

        Employee employee = new Employee();

        employee.setEmployee_id(222);
        employee.setFirstname("Pavan");
        employee.setLastname("Jaooi");
        employee.setEmpdetail(edetail);

        session.merge(employee);
        tx.commit();
        session.close();
        factory.close();
Run Code Online (Sandbox Code Playgroud)

这是我得到的例外:

INFO: Not binding factory to JNDI, no JNDI name configured
Hibernate: select employee0_.employee_id as employee1_0_1_, employee0_.firstname as firstname0_1_, employee0_.lastname as lastname0_1_, employeede1_.employee_id as employee1_1_0_, employeede1_.street as street1_0_, employeede1_.city as city1_0_, employeede1_.state as state1_0_, employeede1_.country as country1_0_ from employee employee0_ left outer join employeedetail employeede1_ on employee0_.employee_id=employeede1_.employee_id where employee0_.employee_id=?
Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.street as street1_0_, employeede0_.city as city1_0_, employeede0_.state as state1_0_, employeede0_.country as country1_0_ from employeedetail employeede0_ where employeede0_.employee_id=?
Exception in thread "main" org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: employee
    at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:44)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:99)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:186)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:240)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
    at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
    at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:194)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:240)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
    at CustomerClient.main(CustomerClient.java:31)
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 55

您告诉Hibernate从其employee属性的ID生成EmployeeDetail ID ,但您从未初始化此属性.

添加edetail.setEmployee(employee);到您的代码中.

  • 因为您应该保持对象图的一致性,更重要的是,因为您使用ID生成器配置了EmployeeDetail实体,该生成器从其`employee`属性获取EmployeeDetail的ID.很明显,如果此属性为null,则Hibernate无法生成ID.这就是错误消息中明确说明的内容. (6认同)
  • 我认为hibernate应该自动执行此操作.当ParentEntity p有一个集合<ChildEntity>时,不能假设p的子节点中的所有c都有p的父节点吗?为什么我必须手动循环并设置所有这些以避免hibernate中的null id错误? (5认同)
  • 是的,但是其他ORM却很容易做到,因为它确实“应该自动执行此操作”。此错误不是程序员的错,而是ORM本身 (4认同)
  • 谢谢,但为什么employee.setEmpdetail(edetail); 还不够吗?为什么我需要做edetail.setEmployee(员工); 还?? ?? (2认同)
  • @PeterJames因为它是如何工作和指定的.实体是POJO.当您将子项添加到父项集合时,Hibernate无法神奇地设置子项的父项. (2认同)