配置Hibernate批注以管理历史记录集合的最佳方法是什么?

问题描述 投票:0回答:1

我有一种情况,除了在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:2

Shift 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); }

但是当我执行上面的[[

Test2

方法时,会创建班次4-6,并对员工执行合并,结果是:员工表

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个班次,而其他班次却变得孤立了,但是我真正想要的是保持这些历史记录在数据库中。我想可以做到这样。我只是没有做正确的冬眠。任何帮助将不胜感激。

谢谢!

hibernate collections merge one-to-many many-to-one
1个回答
0
投票
@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属性,我可以指定该关系将由逆向实体管理。这完全适合我的情况。
© www.soinside.com 2019 - 2024. All rights reserved.