时间:2011-09-29 08:56:13

标签: hibernate jpa one-to-many

我无法描述我的问题,我再次尝试使用示例:

我有两个实体(表格):部门人员。两个表都有一个字段 CODE 不唯一

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

  1. Departmen拥有使用Person.CODE eq Department.CODE
  2. 返回所有实体的人员
  3. 合作伙伴拥有收集部门,使用Department.CODE eq Partner.CODE
  4. 返回所有实体

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

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

    我需要在Department和Person之间创建一对多的hibernate关系(一个Department有很多人)。部门和人员具有时间有效性(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(休眠),很容易在指定日期选择特定部门的人员:

    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持久...)

2 个答案:

答案 0 :(得分:2)

您可以定义Filter。它允许您将该检查添加到您执行的每个查询中,或者如果您愿意,可以将其禁用。

示例:

<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>

问候。

答案 1 :(得分:2)

<强>已更新

首先,您提到要使用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持久化上下文和行映射过程更有效地管理实体关系中代码的使用。

最后,考虑将Person和Department之间的关系实际映射为架构中的连接表。然后,您就可以利用@ManyToMany@JoinTable注释在您的实体中执行基于模式的实际关系。