我有两个实体部门和雇员。部门有一个雇员列表。雇员有一个部门字段。我可以创建雇员并将他们添加到部门内的列表中。数据库表按预期填充。如果我查询部门,我会得到部门,雇员列表也会填充。这样一切都很好。如果我查询雇员,并得到部门字段,它会返回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
4条答案
按热度按时间osh3o9ms1#
看起来像是
Owning entity
的问题,所以我认为您的测试以两种不同的方式持久化数据,在注解@OneToMany(cascade = CascadeType.ALL)
中,您声明Department
为关系的所有者。则将更新部门(ID)字段
但如果你坚持
那么雇员的部门(ID)字段将不会得到更新。
如果雇员的部门ID没有持久化,那么您就不能检索部门,如果您使雇员成为关系的所有者会更有效,因为它有外键。
并在持久化关系时设置职员所属的部门,则插入时使用departmentid,不再单独更新。
标准代码没有明显的错误,因为JPA将遵循注解的关系,但它在两个单独的查询中执行,因为您没有特定的连接。
如果您添加了一个特定的Fetch,那么它将在一个SQL语句中完成。
以及
vaj7vani2#
在我看来,您的关系Map不正确!请尝试像这样更改代码。
puruo6ea3#
我发现了这个问题,我使用了相同的会话进行持久化和查询。
如果我在坚持后关闭会话并打开一个新会话,一切都将正常工作。
我在问题中添加了测试项目的固定版本,以防有人感兴趣。
hkmswyz64#
用下面的代码试试看,只需将连接表从
Employee
指向Department
。