【发布时间】:2015-06-03 21:45:11
【问题描述】:
给定两个实体 Department 和 Employee 形成从 Department 到 Employee 的一对多关系。
由于关系非常直观,我省略了实体类。
下面的代码段,简单地保存了一个实体Employee。
public void insert() {
Employee employee = new Employee();
employee.setEmployeeName("k");
Department department = entityManager.find(Department.class, 1L);
employee.setDepartment(department);
entityManager.persist(employee);
entityManager.flush();
List<Employee> employeeList = department.getEmployeeList();
employeeList.add(employee);
}
以下方法返回与特定部门关联的员工列表。
public List<Employee> getList() {
return entityManager.find(Department.class, 1L).getEmployeeList();
}
这两种方法都是使用 CMT(此处不是 BMT)在无状态 EJB 中编写的,比如说 EmployeeService。
客户端应用程序按顺序调用这些方法,
employeeService.insert();
List<Employee> employeeList = employeeService.getList();
for (Employee e : employeeList) {
System.out.println(e.getEmployeeId() + " : " + e.getEmployeeName());
}
上面foreach 循环中的sout 语句显示了一个新添加的Employee 实体到Department 中的List<Employee>,其中包含null employeeId 考虑到@987654337 行@ 在第一个代码 sn-p 中不存在。
EntityManager#persist(Object entity) 不保证生成 id。 id 只保证在刷新时生成。
如果entityManager.flush(); 被删除/注释,那么实体Employee 将添加到Employees (List<Employee> employeeList) 列表中,其中包含null 标识符(主键列在底层数据库表中)。
维持双向关系的常用方法是什么?每次将实体添加到由关系的反面维护的实体集合中时,是否总是需要EntityManager#flush(); 以生成与新持久化实体相关联的 id?
另外,在删除 Employee 时是否总是需要手动从 List<Employee> 中删除 Employee(由关系的反面维护 - Department)实体(使用entityManager.remove(employee);)?
编辑:实体类:
部门:
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"department_id"})})
public class Department implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "department_id", nullable = false)
private Long departmentId;
@Column(name = "department_name", length = 255)
private String departmentName;
@Column(length = 255)
private String location;
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)
private List<Employee> employeeList = new ArrayList<Employee>(0);
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
员工:
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"employee_id"})})
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "employee_id", nullable = false)
private Long employeeId;
@Column(name = "employee_name", length = 255)
private String employeeName;
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
【问题讨论】:
-
删除flush()会发生什么?
-
如果
entityManager.flush();被移除,那么Employee实体将添加到Deparment中的List<Employee>,并带有nullid (employeeId) - "如果@987654358 @ 被删除/注释,然后实体Employee被添加到Employees 列表(List<Employee> employeeList)中带有null标识符(基础数据库表中的主键列)。 " -
是的,所以?这会使应用程序崩溃吗?这会导致抛出异常吗?这会破坏您的数据库吗?
-
否,但即使在使用
List<Employee> employeeList = department.getEmployeeList();的不同事务中,这也会获取具有nullid 的列表(直到重新部署应用程序)。因此,如果在某个地方(可能是客户端应用程序)尝试此列表,则可能会引发适当的异常。 -
没有。事务 A 永远不会使用与并发事务 B 相同的实体实例。实体是短暂的、非线程安全的对象,并且不在事务之间共享。一旦发生刷新,ID 无论如何都会分配给实体,因此即使它是共享的,它也不会有空 ID。
标签: java hibernate jpa hibernate-mapping bidirectional-relation