【问题标题】:annotation to filter results of a @OneToMany association用于过滤 @OneToMany 关联结果的注释
【发布时间】:2011-10-18 16:20:06
【问题描述】:

我有两个表之间的父/子关系,以及我的 Java 类中的相应映射。表格大致如下:

A (ref number, stuff varchar2(4000))
B (a_ref number, other number, foo varchar2(200))

和 Java 代码:

@Entity
class A {
    @Id
    @Column(name = "REF")
    private int ref;

    @OneToMany
    @JoinColumn(name = "A_REF", referencedName = "REF")
    private Set<B> bs;
}

@Entity
class B {
    @Id
    @Column(name = "A_REF")
    private int aRef;

    @Id
    @Column(name = "OTHER")
    private int other;
}

这很好用,但我想对从子表中检索到的行添加一个过滤器。生成的查询如下所示:

select a_ref, other, foo from B where a_ref = ?

我希望它是:

select a_ref, other, foo from B where a_ref = ? and other = 123

附加过滤器将只是一个列名和一个硬编码值。有没有办法使用休眠注释来做到这一点?

我查看了@JoinFormula,但我总是必须引用父表中的列名(在 JoinFormula 的 name 属性中)。

提前感谢您的任何建议。

【问题讨论】:

  • 很好奇,为什么不直接把它作为参数传入呢? where a_ref = ? and other = ?。如果您需要这样做,传入的值可以硬编码(不过我建议使用可配置的属性系统)。

标签: java hibernate jpa jointable


【解决方案1】:

另一种解决方案是使用Hibernate的@Where:https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#pc-where

    @OneToMany
    @JoinColumn(name = "A_REF", referencedName = "REF")
    @Where(clause = "other = 123")
    private Set<B> bs;

【讨论】:

    【解决方案2】:

    如果我对问题的理解正确,有一种方法可以使用 javax.persistence 注释来做到这一点(我自己在 ManyToOne 上使用了这个,并从here 定制了答案):

    @JoinColumns({
        @JoinColumn(name = "A_REF", referencedColumnName = "REF"),
        @JoinColumn(name = "B_TABLE_NAME.OTHER", referencedColumnName = "'123'")})
    @OneToMany
    private Set<B> bs;
    

    注意referencedColumnName 中的 引号,这是您要查找的值。

    更多信息here

    【讨论】:

      【解决方案3】:

      使用 JPA 1,您可以使用提供的解决方案,但将 unwrap 更改为 getDelegate 即可

      Session session = (Session)entityManager.getDelegate();
      

      它会起作用的。

      【讨论】:

        【解决方案4】:

        JPA 不支持它,但如果您使用 hibernate 作为 JPA 提供程序,那么您可以使用注解 @FilterDef@Filter

        Hibernate Core Reference Documentation

        Hibernate3 能够预先定义过滤条件并附加 这些过滤器在类级别和集合级别。一个过滤器 条件允许您定义一个限制子句,类似于 类和各种可用的现有“where”属性 集合元素。然而,这些过滤条件可以是 参数化。然后应用程序可以在运行时决定是否 应启用某些过滤器及其参数值 应该。过滤器可以像数据库视图一样使用,但它们是 在应用程序内部进行参数化。

        示例

        @Entity
        public class A implements Serializable{
            @Id
            @Column(name = "REF")
            private int ref;
        
            @OneToMany
            @JoinColumn(name = "A_REF", referencedColumnName = "REF")   
            @Filter(name="test")
            private Set<B> bs;
        }
        
        @Entity
        @FilterDef(name="test", defaultCondition="other = 123")
        public class B implements Serializable{
            @Id
            @Column(name = "A_REF")
            private int aRef;
        
            @Id
            @Column(name = "OTHER")
            private int other;
        }
        
        Session session = entityManager.unwrap(Session.class);
        session.enableFilter("test");
        A a = entityManager.find(A.class, new Integer(0))
        a.getb().size() //Only contains b that are equals to 123
        

        【讨论】:

        • 谢谢,它运作良好。尽管您必须动态启用它(我将始终启用它),但这有点烦人。我会忍受的!
        • entityManager 上没有上包装方法 :(
        • 对不起,它只在 JPA 2.0 之后可用。 docs.oracle.com/javaee/6/api/javax/persistence/…
        • 也许这是不正确的,但从我读到的内容看来,这是应用程序过滤器,而不是除了 where 条件,是这样吗?
        猜你喜欢
        • 2011-06-22
        • 2011-06-25
        • 2019-12-19
        • 1970-01-01
        • 1970-01-01
        • 2021-06-03
        • 1970-01-01
        • 1970-01-01
        • 2019-04-26
        相关资源
        最近更新 更多