简体   繁体   English

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

[英]Hibernate 5 Java bidirectional oneToMany field is null but table contains data

I have two entities Department and Employee. 我有两个实体Department和Employee。 Department has a list of Employees. 部门有员工清单。 And Employee has a field Department. 员工有一个现场部门。 I can create Employees and add them to to list inside Department. 我可以创建员工并将其添加到部门内部的列表中。 The Database Tables are filled as expected on persist. 数据库表将按预期的方式持久存储。 If I query for a Department I get the Department and the List of Employees is filled. 如果我查询一个部门,我会得到该部门,并填写员工名单。 Everything fine this way. 这样一切都很好。 If I query for an Employee and get the Department field it Returns null. 如果我查询Employee并获取Department字段,则返回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;
...

-- -

The query where employee.getDepartment() return null 查询employee.getDepartment()返回null

        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
            }
        }

部门表 员工表

The tables seem to be filled correctly. 该表似乎已正确填充。 But if i use getDepartment on a queried Employee i get null. 但是,如果我在查询的Employee上使用getDepartment,我将得到null。 If i use getEmployees on a queried Department i get all the Employees. 如果我在查询的部门上使用getEmployees,则会得到所有的Employees。

I tried both ways described here : https://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch07.html#collections-bidirectional 我尝试了这里描述的两种方法: https : //docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch07.html#collections-bidirectional

Example 7.21. 示例7.21。 Bidirectional one to many with many to one side as association owner 双向一对多,以一对多的身份作为关联所有者

and

Example 7.22. 示例7.22 Bidirectional association with one to many side as owner 与所有者一对多的双向关联

Same result for me. 对我来说也是一样。

What am i missing? 我想念什么?

Here is the complete test Project: updated Project zip 这是完整的测试项目: 更新的项目zip

SOLVED FIXED PROJECT: SOLVED PROBLEM PROJECT 解决的固定项目: 解决的问题项目

Looks like a Owning entity issue, so I think your test is persisting data in two different ways. 看起来像一个Owning entity问题,所以我认为您的测试以两种不同的方式持久化数据。 In your annotation @OneToMany(cascade = CascadeType.ALL) you have declared Department to be the owner of the relationship. 在注释@OneToMany(cascade = CascadeType.ALL)您已声明Department为该关系的所有者。 So, if you persist data with 因此,如果您使用

dept.getEmployees().add(emp);

then the department (id) field will be updated 然后部门(id)字段将被更新

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

but if you persist with 但是如果你坚持

emp.setDepartment(dept);

then the department(id) field of employee won't get updated. 那么员工的部门(id)字段将不会更新。

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

If the department id of employee isn't persisted then you can't retrieve the department. 如果雇员的部门编号未保留,则无法检索该部门。 It's more efficient if you make Employee the owner of the relationship since it has the foreign key. 如果使Employee为关系的所有者,则效率更高,因为它具有外键。

@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;

and set the department of the employee when persisting relations. 并在保持关系时设置员工的部门。 Then the insert is done with the departmentid and not updated separately. 然后,使用部门编号完成插入,并且不会单独更新。

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

There is nothing expressly wrong with the criteria code as JPA will follow the annotated relationship but it does so in two separate queries since you don't have a specific join. 标准代码没有任何明显的错误,因为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=?

If you add a specific Fetch then it will do it in a single SQL statement. 如果添加特定的提取,则它将在单个SQL语句中完成。

root.fetch("department");

and

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

In my opinion, your relational mapping is incorrect! 我认为您的关系映射不正确! Try to change code like this. 尝试像这样更改代码。

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


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

try it with following code , just point the join table to Department from Employee. 使用以下代码尝试一下,只需将联接表从Employee指向Department。

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

I found the Problem. 我发现了问题。 I used the same session for persiting and querying. 我使用相同的会话进行访问和查询。

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

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

query stuff

If i close the session after persist and open a new session everything is working fine. 如果我在坚持后关闭会话并打开一个新会话,则一切正常。

I added a fixed version of the test project to my question just i case someone is iterested. 我添加了一个固定版本的测试项目到我的问题,以防万一有人被打扰了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从Java Spring中的Hibernate双向OneToMany ManyToOne中检索数据 - How to retrieve data from Hibernate bidirectional OneToMany ManyToOne in Java Spring 休眠-OneToMany双向插入导致null - Hibernate - OneToMany Bidirectional Insert resulting in null Spring 数据 JPA - Hibernate - OneToMany,ManytoOne 双向 - Spring Data JPA - Hibernate - OneToMany, ManytoOne bidirectional @OneToMany 双向 - 连接列插入“空”值(休眠) - @OneToMany Bidirectional - Join Column is inserting "null" value (Hibernate) Hibernate 双向@OneToMany 映射返回列 'xxx' 不能为 null - Hibernate bidirectional @OneToMany mapping return Column 'xxx' cannot be null 在 Hibernate 双向 ManytoOne, OnetoMany 的映射列中获取空值 - Getting null in mapping column in Hibernate bidirectional ManytoOne , OnetoMany 双向OneToMany和ManyToOne给出null - Bidirectional OneToMany and ManyToOne gives null Java Hibernate @OneToMany Criteria Projections返回NULL - Java Hibernate @OneToMany Criteria Projections returning NULL 对于repository.save(entityModel),Hibernate OneToMany关联表字段不能为null - Hibernate OneToMany associated table field cannot be null for repository.save(entityModel) HIbernate 忽略从 OnetoMany 字段获取数据 - HIbernate ignore fetching data from OnetoMany field
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM