当前位置: 首页 > 知识库问答 >
问题:

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

查宜民
2023-03-14

我有一个例子,在Employee实体和Shift实体之间除了@OneTomany关系之外,还有几个@OneToOne关系。员工有当前轮班、上次轮班和轮班集合,这些轮班集合表示员工已执行轮班的历史记录。下面的代码显示了我如何设置hibernate注释来表示这一点。

@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

换档表

到目前为止一切都很好...

   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,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个班次在班次列表中,hibernate正在更新db以仅映射这3个班次,而其他班次则处于孤立状态,但我真正想要的是在数据库中保留这些历史记录。我想象像这样的事情可以做;我只是冬眠做得不对。任何帮助都将不胜感激。

谢谢你!

共有1个答案

岳曦
2023-03-14

通过从Employee类中删除@JoinColumn(name=“emp_id”)并使用MappedBy关系属性,我能够获得所需的行为。

@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注释。相反,通过使用mappedBy属性,我能够指定关系将由反向实体管理。这对我的案子很管用。

 类似资料:
  • 数据库 (Repository) 是记录文件或目录状态的地方,存储着内容修改的历史记录。在数据库的管理下,把文件和目录修改的历史记录放在对应的目录下。 远程数据库和本地数据库 首先,Git的数据库分为远程数据库和本地数据库的两种。 远程数据库: 配有专用的服务器,为了多人共享而建立的数据库。 本地数据库: 为了方便用户个人使用,在自己的机器上配置的数据库。 数据库分为远程和本地两种。平时用手头上的

  • 在重新启动Spring Boot Admin服务器后,是否有任何方法可以在Spring Boot Admin日志页面中保存有关应用程序状态更改的历史记录?所有已注册应用程序的所有状态更改都有历史记录,但如果我重新启动管理服务器,历史记录将消失,并开始记录自启动以来的更改。有没有办法将历史记录永久保存在此页面中?即使spring boot管理服务器重新启动?

  • 问题内容: 我想过滤java.util.Collection基于谓词的。 问题答案: Java 8(2014)在一行代码中使用流和lambda解决了此问题: 这是一个教程。 使用修改收集到位。(注意:在这种情况下,谓词将删除满足该谓词的对象): 允许过滤集合而无需编写循环或内部类: 你能想象一些更具可读性的东西吗?

  • 我正试图在Tomcat 9下部署camunda以访问camunda驾驶舱界面。出于一些技术原因,我必须使用以下java代码(Spring-boot)将历史记录级别设置为123: ProcessEngine ProcessEngine=ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().Se

  • 问题内容: 关闭。 此问题不符合堆栈溢出准则。它当前不接受答案。 想改善这个问题吗? 更新问题,使其成为Stack Overflow 的主题。 6年前关闭。 改善这个问题 我一直在JQuery库中查找URL哈希,但是没有发现任何好的方法。有“历史插件”,但是我们都知道它有故障并且不灵活。 我正在div中加载页面。我需要一种与URL哈希一起进行前进/后退的方法。 什么是可以处理所有这些问题的最佳库?

  • 本文向大家介绍php浏览历史记录的方法,包括了php浏览历史记录的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php浏览历史记录的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的php程序设计有所帮助。