【问题标题】:Conditional/composite JoinColumn In JPA/HibernateJPA/Hibernate 中的条件/复合 JoinColumn
【发布时间】:2013-04-26 09:18:40
【问题描述】:

在我的一堂课中,比如说位置,我有这样的事情:

private List<Magician> magicians;

...

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="location_id")
public List<Magician> getMagicians() {
    return magicians;
} 

public void setMagicians(List<Magician> magicians) {
    this.magicians = magicians;
}

魔术师有变量的地方

private Integer id;
private Integer location_id;
private Boolean active;

现在我想修改 getter 注释,以便只获取 active 为 true 的魔术师。

我怎样才能做到这一点?

感谢您的关注。

【问题讨论】:

  • 好的,感谢 JB 和 Kevin 的回答。我提出问题的动机是,在某些情况下,我可能希望限制应用程序访问的数据集,而不在代码中引入任何新方法。所以我会通过 db 查询将 active 设置为 true 来快速准备数据。

标签: hibernate jpa join joincolumn


【解决方案1】:

在 Hibernate 中,我的问题可以使用过滤器来解决,如下所述:https://stackoverflow.com/a/6920847/1966869。我刚刚测试过并且看起来非常实用的 xml 版本在此处进行了描述:http://www.mkyong.com/hibernate/hibernate-data-filter-example-xml-and-annotation/。 可能还有其他使用@Where (How to use @Where in Hibernate) 或@JoinFormula (@JoinFormula and @OneToMany definition - poor documentation) 的解决方案,但我没有测试它们。

【讨论】:

    【解决方案2】:

    我不会在实体级别执行这项工作,而是使用EntityManager 创建查询来执行它。正如 JB 提到的,您需要将位置添加为复合对象而不是整数。

    //在方法中

    List<Magician> magicians = 
       em.createQuery("select m from Location l join Magician m where m.active = true and
       l.[specify id here] = :locationId", Magician.class).setParameter("locationId",
       1).getResultList();
    

    【讨论】:

      【解决方案3】:

      首先,Magician 不应该有 location_id 字段。它应该有一个 Location 类型的字段。这将在两个实体之间建立双向关联:

      @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "location")
      public List<Magician> getMagicians() {
          return magicians;
      } 
      
      ...
      
      @ManyToOne
      @JoinColumn(name = "location_id")
      public Location getLocation() {
          return this.location;
      }
      

      然后,为了回答您的问题,实体的状态和关联不用于实现特定的用例或查询。您用于对数据库包含的内容进行建模。要获取给定位置的活跃魔术师,您应该简单地使用查询:

      select m from Magician m where m.active = true and m.location = :location
      

      【讨论】:

      • 感谢您的回复。至于单向与双向点,我同意 axtavt 的评论 (stackoverflow.com/a/5361587/1966869)”,即“导航访问并不总是好的,特别是对于“一对多”和“多对多” “关系”。我认为除非需要,否则不应使用双向,尤其是在“一对多”无处不在的应用程序中,例如我的。我认为这是一个非常相关的问题,而且还有更多欢迎您发表评论,我们将不胜感激。
      • 如果它是一对多,那么将其建模为单向多对一关联可能有充分的理由。但是您将其建模为单向 OneToMany。而且您的魔术师中无论如何都有该位置的 ID(这会使您的映射不正确,因为该列被映射了两次),那么为什么不使用延迟加载的位置呢?
      • 因为位置是一个大对象,当我和魔术师一起工作时我通常不需要(或者我已经拥有)它,而我通常只需要 location_id。所以我只保留了 location_id id。至于您观察到它被映射两次,据我了解,如果关系是双向的,即如果我遵循您的建议(我很感激,如果我错了,请纠正我),它将被映射两次。跨度>
      • 如果每个双向关联都会导致一个 mpping 错误,那么双向关联就不会很有用。通过将 ID 映射为 Magician 中的基本列,并将其映射为 Location 中 OneToMany 关联的连接列,您将其映射两次,这将导致映射异常。我的观点是你试图过早地优化。我会使用双向关联。通过 ID 获取位置应该非常快,即使它是一个大对象。如果您不需要该位置,因为它是延迟加载的,因此不会执行任何查询来加载它。
      • 我的意思是我经常需要 location_id,我不想每次需要 location_id 时都加载肥胖的位置。还没有映射异常,已经有一段时间了。顺便说一下,作为一个例子,魔术师可能是一个原子,而位置是一个蛋白质。更多的 cmets 总是受欢迎的。 PS 我的意思是,如果我听从你的建议并将 location_id 留在 Magician 中,它将被映射两次。我并不是说你的建议是错误的。
      猜你喜欢
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2012-08-09
      相关资源
      最近更新 更多