在ManyToOne上指定条件

时间:2018-03-21 07:12:54

标签: hibernate jpa spring-boot

我有两个实体:Element与一个Diagram相关联。 Diagram可以包含多个Elements

@Entity
public class Diagram 
    @ID
    private UUID uuid;

    private UUID id;

    private String name;

    private Date update_date;

我可以有几个版本的图表。但是最新的update_date给了我当前版本的图表。

uuid(PK) |      id | name |update_date         
--------------------------------------
BLOB     |  UUID-A | foo  | 2018-03-19 
BLOB     |  UUID-A | bar  | 2018-03-21

当我致电element.getDiagram()时,Hibernate应该在Element.diagramId=Diagram.id上搜索最新的图表。

@Entity
public class Element
    @ID
    private int id;

    @ManyToOne
    private Diagram diagram;

例如: 我想要2018-01-20的图表状态。 SQL查询看起来就像那样。 所以它会给我一个名为foo的图表。

select d.* 
from element e 
join diagram d 
 on e.diagramId=d.id and d.updated_at < '2018-01-20'
order by d.updated_at desc
limit 1;

我尝试了什么

  1. @ManyToOne放在Element.diagram字段上。但是Hibernate会自动在Diagram.id上创建一个唯一约束。在我的情况下这是不可能的,因为我可以有几个版本的图表具有相同的ID(这不是主键)。

  2. 也不可能@ManyToMany。因为Hibernate会在unique constraint上创建Diagram.Id。这是不可能的,因为我们可以在Diagram中有几个与图表的所有版本相对应的条目。

  3. 有什么想法吗? 提前谢谢。

1 个答案:

答案 0 :(得分:1)

你不需要创建diagramId作为参考,Spring会为你做。

创建新图表时,您只需要将最新的图表ID更新为元素表格。这样您就不必创建引用键(diagramId,id等)

您可以通过以下方式解决此问题:

Element.java

@Entity
public class Element {

  @Id
  private Long id;

  private String elementName;

  @ManyToOne(fetch = FetchType.EAGER, cascade= { CascadeType.MERGE })
  @JoinColumn(name="diagram_id", nullable = false)
  private Diagram diagram;

Diagram.java

@Entity
public class Diagram {

  @Id
  private Long id;

  private String diagramName;

  private Date update_date;

测试

@ResponseBody
@RequestMapping(value = "/get/elements", method = RequestMethod.GET)
public List<Element> getElements() {
    return elementRepository.findAll();
}

结果

[
 {
"id": 1,
"elementName": "Element 1",
"diagram": {
         "id": 1,
         "diagramName": "Diagram 1",
         "update_date": "2018-03-21T08:31:00.000+0000"
           }
}]