簡體   English   中英

Hibernate 5 Java雙向oneToMany字段為空,但表包含數據

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

我有兩個實體Department和Employee。 部門有員工清單。 員工有一個現場部門。 我可以創建員工並將其添加到部門內部的列表中。 數據庫表將按預期的方式持久存儲。 如果我查詢一個部門,我會得到該部門,並填寫員工名單。 這樣一切都很好。 如果我查詢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;
...

-

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

部門表 員工表

該表似乎已正確填充。 但是,如果我在查詢的Employee上使用getDepartment,我將得到null。 如果我在查詢的部門上使用getEmployees,則會得到所有的Employees。

我嘗試了這里描述的兩種方法: https : //docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch07.html#collections-bidirectional

示例7.21。 雙向一對多,以一對多的身份作為關聯所有者

示例7.22 與所有者一對多的雙向關聯

對我來說也是一樣。

我想念什么?

這是完整的測試項目: 更新的項目zip

解決的固定項目: 解決的問題項目

看起來像一個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, ?, ?)

如果雇員的部門編號未保留,則無法檢索該部門。 如果使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;

並在保持關系時設置員工的部門。 然后,使用部門編號完成插入,並且不會單獨更新。

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=?

如果添加特定的提取,則它將在單個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

我認為您的關系映射不正確! 嘗試像這樣更改代碼。

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


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

使用以下代碼嘗試一下,只需將聯接表從Employee指向Department。

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

我發現了問題。 我使用相同的會話進行訪問和查詢。

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

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

query stuff

如果我在堅持后關閉會話並打開一個新會話,則一切正常。

我添加了一個固定版本的測試項目到我的問題,以防萬一有人被打擾了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM