Hibernate 5 Java双向oneToMany字段为空,但表包含数据

bn31dyow  于 2022-12-19  发布在  Java
关注(0)|答案(4)|浏览(158)

我有两个实体部门和雇员。部门有一个雇员列表。雇员有一个部门字段。我可以创建雇员并将他们添加到部门内的列表中。数据库表按预期填充。如果我查询部门,我会得到部门,雇员列表也会填充。这样一切都很好。如果我查询雇员,并得到部门字段,它会返回null。

@Entity
@Table(name = "DEPARTMENT")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "DPT_ID")
    private long id;

    @Column(name = "NAME", nullable = false, unique = true)
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "DEPARTMENT") //we need to duplicate the physical information
    private List<Employee> employees = new ArrayList<>();
…

--

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "EMP_ID")
    private long id;

    @Column(name = "NAME", nullable = false)
    private String name;

    @Column(name = "DESIGNATION")
    private String designation;

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

--
employee.getDepartment()返回空值的查询

session = HibernateUtil.getSessionFactory().openSession();
        transaction = session.getTransaction();
        transaction.begin();

        Department department = new Department();
        department.setName("IT Department");

        Employee employee1 = new Employee();
        employee1.setName("Adam");
        employee1.setDesignation("Manager");

        Employee employee2 = new Employee();
        employee2.setName("Miller");
        employee2.setDesignation("Software Engineer");

        Employee employee3 = new Employee();
        employee3.setName("Smith");
        employee3.setDesignation("Associate  Engineer");

        department.getEmployees().add(employee1);
        department.getEmployees().add(employee2);
        department.getEmployees().add(employee3);

        session.persist(department);
        session.flush();
        transaction.commit();

        transaction = session.getTransaction();
        transaction.begin();

        {
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Employee> query = builder.createQuery(Employee.class);
            Root<Employee> root = query.from(Employee.class);
            query.select(root);
            Query<Employee> q = session.createQuery(query);
            List<Employee> employees = q.getResultList();
            for (Employee employee : employees) {
                System.out.println("EMPLOYEE NAME: " + employee.getName());
                System.out.println("DEPARTMENT NAME: " + employee.getDepartment()); // gives null
            }
        }
        {
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Department> query = builder.createQuery(Department.class);
            Root<Department> root = query.from(Department.class);
            query.select(root);
            Query<Department> q = session.createQuery(query);
            List<Department> departments = q.getResultList();
            for (Department deps : departments) {
                System.out.println(deps.getName());
                System.out.println(deps.getEmployees()); // list of employees is filled
            }
        }

第一节第一节第一节第一节第一次
这些表看起来填充正确,但是如果我对查询的Employee使用getDepartment,得到的是null,如果我对查询的Department使用getEmployees,得到的是所有Employees。
I tried both ways described here : https://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch07.html#collections-bidirectional
例7.21双向一对多,多对一方作为关联所有者
以及
例7.22一对多方作为所有者的双向关联
我也一样。
我错过了什么?
以下是完整的测试项目:updated Project zip
解决的固定项目:SOLVED PROBLEM PROJECT

osh3o9ms

osh3o9ms1#

看起来像是Owning entity的问题,所以我认为您的测试以两种不同的方式持久化数据,在注解@OneToMany(cascade = CascadeType.ALL)中,您声明Department为关系的所有者。

dept.getEmployees().add(emp);

则将更新部门(ID)字段

Hibernate: insert into EMPLOYEE (EMP_ID, DESIGNATION, NAME) values (null, ?, ?)
Hibernate: update EMPLOYEE set DEPARTMENT=? where EMP_ID=?

但如果你坚持

emp.setDepartment(dept);

那么雇员的部门(ID)字段将不会得到更新。

Hibernate: insert into EMPLOYEE (EMP_ID, DESIGNATION, NAME) values (null, ?, ?)

如果雇员的部门ID没有持久化,那么您就不能检索部门,如果您使雇员成为关系的所有者会更有效,因为它有外键。

@OneToMany(cascade = CascadeType.ALL, mappedBy="department")
private List<Employee> employees; // don't need to make a list, only for fetches
// and 
@ManyToOne
@JoinColumn(name = "DEPARTMENT")
private Department department;

并在持久化关系时设置职员所属的部门,则插入时使用departmentid,不再单独更新。

Hibernate: insert into EMPLOYEE (EMP_ID, DEPARTMENT, DESIGNATION, NAME) values (null, ?, ?, ?)

标准代码没有明显的错误,因为JPA将遵循注解的关系,但它在两个单独的查询中执行,因为您没有特定的连接。

Hibernate: select employee0_.EMP_ID as EMP_ID1_1_, employee0_.DEPARTMENT as DEPARTME4_1_, employee0_.DESIGNATION as DESIGNAT2_1_, employee0_.NAME as NAME3_1_ from EMPLOYEE employee0_
Hibernate: select department0_.DPT_ID as DPT_ID1_0_0_, department0_.NAME as NAME2_0_0_ from DEPARTMENT department0_ where department0_.DPT_ID=?

如果您添加了一个特定的Fetch,那么它将在一个SQL语句中完成。

root.fetch("department");

以及

Hibernate: select employee0_.EMP_ID as EMP_ID1_1_0_, department1_.DPT_ID as DPT_ID1_0_1_, employee0_.DEPARTMENT as DEPARTME4_1_0_, employee0_.DESIGNATION as DESIGNAT2_1_0_, employee0_.NAME as NAME3_1_0_, department1_.NAME as NAME2_0_1_ from EMPLOYEE employee0_ inner join DEPARTMENT department1_ on employee0_.DEPARTMENT=department1_.DPT_ID
vaj7vani

vaj7vani2#

在我看来,您的关系Map不正确!请尝试像这样更改代码。

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

@OneToMany(mappedBy = "department",cascade = CascadeType.ALL)
private List<Employee> employees = new ArrayList<>();
puruo6ea

puruo6ea3#

我发现了这个问题,我使用了相同的会话进行持久化和查询。

session = HibernateUtil.getSessionFactory().openSession();
transaction = session.getTransaction();
transaction.begin();
…
session.persist(stuff);
session.flush();
transaction.commit();

transaction = session.getTransaction();
transaction.begin();

query stuff

如果我在坚持后关闭会话并打开一个新会话,一切都将正常工作。
我在问题中添加了测试项目的固定版本,以防有人感兴趣。

hkmswyz6

hkmswyz64#

用下面的代码试试看,只需将连接表从Employee指向Department

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

相关问题