我有一种情况,除了在Employee实体和Shift实体之间的@OneToMany关系外,我还有几个@OneToOne关系。员工具有当前班次,上一次班次和班次的集合,它们表示该员工已执行的班次的历史记录。下面的代码显示了如何设置休眠注释来表示这一点。
@Entity
public class Employee {
@Id
@Column(name = "EMP_ID")
private Long id;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "CURRENT_SHIFT_ID")
private Shift currentShift;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "LAST_SHIFT_ID")
private Shift lastShift;
@OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
@JoinColumn(name = "EMP_ID")
private List<Shift> shifts;
}
@Entity
public class Shift {
@Id
@Column(name = "SHIFT_ID")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EMP_ID", nullable = false)
private Employee employee;
@Column(name = "START_DATE")
private Calendar startDate;
@Column(name = "END_DATE")
private Calendar endDate;
}
这里有一些示例代码来说明我正在尝试做的事情。
public void test1(long employeeId) {
Employee dbEmployee = entityManager.find(Employee.class, employeeId);
Calendar startDate = Calendar.getInstance();
Calendar endDate = Calendar.getInstance();
// create the first shift
Shift one = new Shift();
one.setEmployee(dbEmployee);
one.setStartDate(startDate);
one.setEndDate(endDate);
// create the second shift
Shift two = new Shift();
two.setEmployee(dbEmployee);
two.setStartDate(startDate);
two.setEndDate(endDate);
// create the third shift
Shift three = new Shift();
three.setEmployee(dbEmployee);
three.setStartDate(startDate);
three.setEndDate(endDate);
// add shifts 1-3 to the collection of shifts that the employee just performed
List<Shift> shifts = new ArrayList<Shift>();
shifts.add(one);
shifts.add(two);
shifts.add(three);
dbEmployee.setShifts(shifts);
// set the last shift to shift #2
dbEmployee.setLastShift(two);
// set the current shift to shift #3
dbEmployee.setCurrentShift(three);
entityManager.merge(dbEmployee);
}
在上面的[[Test1方法中,我将为员工创建1-3班次,并填充班次集合,同时指定哪个班次是员工的上次和当前班次。当我对员工执行合并时,我生成的数据库表如下所示:
员工表
id:1,currentShiftId:3,lastShiftId:2Shift Table
id:1,employeeId:1,startDate:...,endDate:...id:2,employeeId:1,startDate:...,endDate:...
id:3,employeeId:1,startDate:...,endDate:...
到目前为止一切都很好...
public void test2(long employeeId) {
Employee dbEmployee = entityManager.find(Employee.class, employeeId);
Calendar startDate = Calendar.getInstance();
Calendar endDate = Calendar.getInstance();
// create the fourth shift
Shift four = new Shift();
four.setEmployee(dbEmployee);
four.setStartDate(startDate);
four.setEndDate(endDate);
// create the fifth shift
Shift five = new Shift();
five.setEmployee(dbEmployee);
five.setStartDate(startDate);
five.setEndDate(endDate);
// create the sixth shift
Shift six = new Shift();
six.setEmployee(dbEmployee);
six.setStartDate(startDate);
six.setEndDate(endDate);
// add shifts 4-6 to the collection of shifts that the employee just performed
List<Shift> shifts = new ArrayList<Shift>();
shifts.add(four);
shifts.add(five);
shifts.add(six);
dbEmployee.setShifts(shifts);
// set the last shift to shift #5
dbEmployee.setLastShift(five);
// set the current shift to shift #6
dbEmployee.setCurrentShift(six);
entityManager.merge(dbEmployee);
}
但是当我执行上面的[[方法时,会创建班次4-6,并对员工执行合并,结果是:员工表Test2
id:1,currentShiftId:6,lastShiftId:5
Shift Table
id:1,employeeId:NULL,startDate:...,endDate:...
id:2,employeeId:NULL,startDate:...,endDate:...id:3,employeeId:NULL,startDate:...,endDate:...
id:4,employeeId:1,startDate:...,endDate:...
id:5,employeeId:1,startDate:...,endDate:...
id:6,employeeId:1,startDate:...,endDate:...
所以1-3班正与我的员工失去联系。我了解,由于我正在执行合并,其中只有班次列表中的班次为4-6,所以休眠状态将数据库更新为仅映射这3个班次,而其他班次却变得孤立了,但是我真正想要的是保持这些历史记录在数据库中。我想可以做到这样。我只是没有做正确的冬眠。任何帮助将不胜感激。
谢谢!
@Entity
public class Employee {
@Id
@Column(name = "EMP_ID")
private Long id;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "CURRENT_SHIFT_ID")
private Shift currentShift;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "LAST_SHIFT_ID")
private Shift lastShift;
@OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "employee")
//@JoinColumn(name = "EMP_ID") // this will try to manage the relationship
private List<Shift> shifts;
}
@Entity
public class Shift {
@Id
@Column(name = "SHIFT_ID")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EMP_ID", nullable = false)
private Employee employee;
@Column(name = "START_DATE")
private Calendar startDate;
@Column(name = "END_DATE")
private Calendar endDate;
}
我的新理解是,当您希望该实体管理关系时,将使用@JoinColumn批注。相反,通过使用mapledBy属性,我可以指定该关系将由逆向实体管理。这完全适合我的情况。