有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java OneToMany关联集合在Hibernate应用程序中为空

我正在开发一个简单的Hibernate应用程序来测试OneToMany关联。我使用的实体是EmployeeDepartment,它们有许多Employees

@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long departmentId;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="department")
    private Set<Employee> employees;

...
getters/setters

}

@Entity
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long employeeId;

    @ManyToOne
    @JoinColumn(name="employee_fk")
    private Department department;

...
getters/setters

}

我使用以下工具创建一些记录:

tx.begin();

        Department department = new Department();
        department.setDepartmentName("Sales");
        session.persist(department);

        Employee emp1 = new Employee("Ar", "Mu", "111");
        Employee emp2 = new Employee("Tony", "Almeida", "222");
        Employee emp3 = new Employee("Va", "Ka", "333");

        emp1.setDepartment(department);
        emp2.setDepartment(department);
        emp3.setDepartment(department);


        session.persist(emp1);
        session.persist(emp2);
        session.persist(emp3);

        Set<Employee> emps = department.getEmployees();
        emps.remove(emp2);

然而,在最后一行:emps.remove(emp2);我收到一个NullPointerExceptionemps集合就是null。我已尝试通过以下方式更改协会的所有者:

 @Entity
    public class Department {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long departmentId;

        @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
        @JoinColumn(name="department_fk")
        private Set<Employee> employees;

    ...
    getters/setters

    }

    @Entity
    public class Employee {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long employeeId;

        @ManyToOne
        @JoinColumn(name="department_fk", insertable=false, updatable=false)
        private Department department;

    ...
    getters/setters

    }

然而,结果是一样的。为什么EmployeesSet没有被创建。为了使它工作,必须改变什么


共 (2) 个答案

  1. # 1 楼答案

    在构造函数中或通过为字段指定初始值,自己初始化集合

    实际上,当您从数据库获取对象时,Hibernate会将集合初始化为空集合。但是,当您自己创建对象并将其持久化时,Hibernate不会真正触及您创建的对象,只会持久化它,因此在这种情况下,它不会为您初始化字段

    如果你想确保这个字段永远不为空,我同意这是可取的,你只需要自己确保它,甚至在坚持之前

  2. # 2 楼答案

    让我们仔细看看你的代码:

    Department department = new Department();
    department.setDepartmentName("Sales");
    session.persist(department);
    
    Employee emp1 = new Employee("Ar", "Mu", "111");
    Employee emp2 = new Employee("Tony", "Almeida", "222");
    Employee emp3 = new Employee("Va", "Ka", "333");
    
    emp1.setDepartment(department);
    emp2.setDepartment(department);
    emp3.setDepartment(department);
    
    
    session.persist(emp1);
    session.persist(emp2);
    session.persist(emp3);
    
    Set<Employee> emps = department.getEmployees();
    

    您已经创建了Department,三个Employees,为每个Employee设置对该Department的引用,并将它们持久化

    Setemps将为空,因为在将员工持久化到数据库后,您没有重新加载department。如果您这样更改代码:

    ....
    session.persist(emp3);
    department = session.get(Department.class, department.getDepartmentId());
    
    Set<Employee> emps = department.getEmployees();
    emps.remove(emp2);
    

    你应该没事的

    我想提到的另一点是DepartmentEmployees之间的关系是mappedBy{},这意味着Department是主实体,它的Employee是“从实体”,或者,如果你愿意,它承担维护映射和引用的所有责任。但是,在我上面评论的代码中,您将这个映射责任放在了Employee实体上。您可能希望以这种方式更改代码:

    department.add(emp1);
    department.add(emp2);
    department.add(emp2);
    
    session.persist(department);
    

    为了让Department完成维护映射和引用的工作