一尘不染

使用非唯一密钥的休眠关系OneToMany

hibernate

我无法描述我的问题,请通过示例再次尝试:

我有两个实体(表): DepartmentPerson 。这两个表有一个字段 CODE 这是 不是唯一的

如何 定义 这些表之间的manyToMany 双向关系

  1. 部门人员具有收集人员,该人员返回具有Person.CODE eq Department.CODE的所有实体
  2. 合作伙伴有收集部门,该部门返回所有带有Department.CODE eq的Partner.CODE实体

我需要关系定义-没有sql或hpql查询。

---------原始问题-------

我需要在部门和人之间建立一对多的hibernate关系(一个部门有很多人)。部门和人员具有时间有效性(validFrom,validTill)

class Department {
  Long id;
  String code; 
  String name;
  Date validFrom;
  Date validTill;
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "departmentId")
  @OnDelete(action = OnDeleteAction.CASCADE)
  private Set<Person> persons = new HashSet<Person>();
}






 class Person {
      Long id;
      String name;
      String surname;
      Date validFrom;
      Date validTill;
    }

没有ORM(hibernate),很容易在指定日期选择特定部门的人员:

select P.* from Person P, Deparment d 
where d.code = ? and 
p.department_id = d.department_id and 
? between d.validFrom and d.validTill and 
? between p.validFrom and p.validTill

该关系必须使用非唯一键(CODE)代替部门ID。

有可能用hibernate做类似的事情吗?

我不需要单独的对象并自己构造查询。

我想使用ORM提供的所有功能(延迟加载,cascase持久化…)


阅读 226

收藏
2020-06-20

共1个答案

一尘不染

更新

首先,您提到要使用ORM提供的所有功能。如果是这种情况,则需要使用Hibernate友好的模式。JPA持久性API和特定于Hibernate的API中都有可用的批注,使您可以更轻松地使用“旧版”数据库。但是,如果您想完全正确地使用Hibernate,则必须根据Hibernate的期望来设计架构。

在这种情况下,您可以通过使用联接公式而不是关系的联接列来执行您要的操作。连接公式是有效的SQL片段(可能会降低可移植性)。在下面的示例中,我省略了实际的SQL。

public class Person {
    ...
    @OneToMany
    @JoinFormula("sql fragment")
    private List<Department> departments;
    ...
}

public class Department {
    ...
    @OneToMany
    @JoinFormula("sql fragment")
    private List<Person> people;
    ...
}

您还应该考虑将代码视为Hibernate对象:

@Embeddable
public class Code {
    ...
    @Column(nullable = false, length = 20)
    private String code;
    ...
}

Hibernate持久性上下文和行映射过程可以有效地管理实体关系中的代码,而不仅仅是字符串。

最后,考虑将人与部门之间的关系实际映射为架构中的联接表。然后,您就可以利用@ManyToMany@JoinTable注释在实体中进行实际的基于架构的关系。

2020-06-20