按需急切加载

时间:2009-11-03 15:30:01

标签: java hibernate lazy-loading

我提出疑问:

String query = "SELECT DISTINCT a FROM A a FETCH ALL PROPERTIES " +
        "JOIN a.Bs AS b " +
        "JOIN b.Cs AS c WHERE c = :c";
Query q = DAO.getSession().createQuery(query);
q.setParameter("c", c);
return q.list();

即使我在a上说FETCH ALL PROPERTIES,当我访问A所拥有的所有集合时,它们仍然需要加载,因此不会急切加载。它们被定义为延迟加载,这是我想要的默认行为,但这是例外:我希望它们现在加载。我已尝试将JOIN换成LEFT OUTER JOIN以激活Hibernate加载它们,我尝试设置q.setFetchMode("a", FetchMode.EAGER),但查询不存在。

As的列表很长,而且它们有很多集合,所以这个n + 1查询的东西非常慢(大约十秒,而不是在单个查询中进行,这可能是第二速度)。我更喜欢一个查询并加载所有必要的内容。关于我如何做到这一点的任何建议?

PS,小小的奖励问题:如果我用"JOIN b.Cs AS c WHERE c = :c"; 替换"WHERE :c IN b.Cs";行,我会得到一个SQL异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1

它所指的双重语句是“和('(151000000-0000'in(。))”其中151000000-0000是c的主键。知道为什么我这样做时会出现这个错误,相比之下,当我加入b.Cs时没有得到它?

UPDATE,根据要求,这是我用于映射的方式。 B和C的设计非常相似:

@Entity
@Table(name = "tblA")
public class A  {
  @Id
  String AId;

  @Column(name = "shortName", length = 12, nullable = false)
  String shortName;

  @OneToMany(fetch=FetchType.LAZY, mappedBy="theA")
  private Set<B> Bs;

  @OneToMany(fetch=FetchType.LAZY, mappedBy="theA")
  private Set<D> Ds;

  @OneToMany(fetch=FetchType.LAZY, mappedBy="theA")
  private Set<E> Es;

  @OneToMany(fetch=FetchType.LAZY, mappedBy="theA")
  private Set<F> Fs;
}

B,D,E和F中的A定义如下:

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "AId", nullable = true)
@ForeignKey(name="FK_KategoriID")
private A theA;

干杯

的Nik

2 个答案:

答案 0 :(得分:9)

fetch all properties不是你想要的;它用于告诉Hibernate你希望它获取单值延迟加载的属性。详细信息为here

您需要在查询中指定join fetch

SELECT DISTINCT a FROM A a
  LEFT JOIN FETCH a.Bs AS b
  LEFT JOIN FETCH b.Cs AS c
 WHERE c = :c

就奖金问题而言,WHERE :c IN b.Cs是非法语法。根据{{​​1}}的映射方式,您可能需要查看elements()函数。

答案 1 :(得分:1)

FETCH ALL PROPERTIES仅适用于惰性属性(其中属性是String,Integer,...)不是一对一关联(即集合)

请参阅A Short Primer On Fetching Strategies