具有非唯一键的 Hibernate 关系 OneToMany

发布于 2024-12-07 13:36:42 字数 1385 浏览 0 评论 0原文

我无法描述我的问题,我再次尝试举例:

我有两个实体(表):部门人员。两个表都有一个代码字段,该字段不唯一

如何在这些表之间定义多对多双向关系

  1. Departmen 具有集合 Persons,它返回具有 Person.CODE eq Department.CODE 的所有实体。
  2. Partner 具有集合 Departments,它返回具有 Department.CODE eq Partner.CODE 的所有实体。

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

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

我需要在部门和人员之间创建一对多的休眠关系(一个部门有很多人)。部门和人员具有时间有效性(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 持久化...)

I am not able to describe my problem, I try it again with example:

I have two entities (tables): Department and Person. Both tables have a field CODE which is not unique.

How can I define manyToMany bidirectional relations between these tables?

  1. Departmen has collection Persons which returns all entities with Person.CODE eq Department.CODE
  2. Partner has collection Departments which returns all entities with Department.CODE eq Partner.CODE

I need the relation definition - no sql or hpql query.

--------- Original question -------

I need to create hibernate relation one to many between Department and Person (one Department has many persons). Department and persons has time validity (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;
    }

Without ORM (hibernate) it is easy to select persons of particular department at specified date:

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

The relation has to use non unique key (CODE) instead of department ID.

Is it possible to do something similar with hibernate?

I don't need separated objects and construct queries myself.

I want use all feature which ORM offers (lazy loading, cascase persist ...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽袖吟 2024-12-14 13:36:42

您可以定义一个过滤器。它允许您将该检查添加到您执行的每个查询中,或者根据需要禁用它。

例:

<class name="Department" ...>
    ...
    <many-to-one name="person" column="person_id" class="Person"/>
    <property name="validFrom" type="date" column="validFrom"/>
    <property name="validTill" type="date" column="validTill"/>
    <property name="code" type="string" column="code"/>
    ...
    <!--
        Note that this assumes non-terminal records have an eff_end_dt set to
        a max db date for simplicity-sake
    -->
    <filter name="effectiveDate"
            condition="code = :code and :asOfDate BETWEEN validFrom and validTill"/>
</class>

问候。

You can define a Filter. It allows you to add that check to every query you do, or disable it if you like.

Example:

<class name="Department" ...>
    ...
    <many-to-one name="person" column="person_id" class="Person"/>
    <property name="validFrom" type="date" column="validFrom"/>
    <property name="validTill" type="date" column="validTill"/>
    <property name="code" type="string" column="code"/>
    ...
    <!--
        Note that this assumes non-terminal records have an eff_end_dt set to
        a max db date for simplicity-sake
    -->
    <filter name="effectiveDate"
            condition="code = :code and :asOfDate BETWEEN validFrom and validTill"/>
</class>

Regards.

百善笑为先 2024-12-14 13:36:42

更新

首先,您提到您想要使用 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 注释在实体中建立实际的基于架构的关系。

UPDATED

First off, you mention that you want to use all features which ORM offers. If this is the case then you need to use a schema that Hibernate is friendly toward. There are annotations available in both the JPA persistence API and with Hibernate-specific API that allow you to more easily work with 'legacy' databases. But if you want full and correct Hibernate use, then you have to design your schema according to what Hibernate expects.

You can do what you are asking in this case by using a join formula instead of a join column for your relationships. The join formula is a valid SQL fragment (which may reduce portability). I've left the actual SQL out in the example below.

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

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

You should also consider treating code as a Hibernate object:

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

Rather than just a string so that the use of a code in entity relationships is more effectively managed by the Hibernate persistence context and the row mapping process.

Lastly, consider actually mapping the relationship between Person and Department as a join table in your schema. You'd then be able to take advantage of the @ManyToMany and @JoinTable annotations to do actual schema-based relationships in your entities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文