我正在使用:Hibernate 3.6.8 和 mySQL、Tomcat 6、JDBC 连接池
我遇到了 Hibernate 打开大量连接的问题,这最终导致我的 Web 应用程序无法获得新连接。起初我以为问题是我在没有连接池的情况下运行,所以我连接了 Tomcat JDBC 池。
这使问题变得更糟。它没有在几次查询后失败,而是立即失败。原来这是因为 Hibernate 试图打开比我的池大小(30)更多的连接。我检查了一下,在我创建 EntityManager 的任何地方,如果有尝试,我都会在 finally 子句中调用 close(),所以我不确定它们为什么保持打开状态。
查看 close() 的源代码,我发现如果有一个事务打开,它实际上并没有关闭,所以我尝试在实体管理器上调用 getTransaction().commit(),即使它只是一个选择语句。这没有效果。然后我发现了这个配置标志,并将其打开:
<property name="hibernate.ejb.discard_pc_on_close" value="true" />
这有所不同,当我尝试渲染对象以进行输出时出现异常:未能延迟初始化角色集合:XXX.Comment.attachments,没有会话或会话已关闭
问题似乎是我进行了许多查询来创建评论集合,并且所有这些查询都保持连接打开。Comment 类包含以下内容:
@OneToMany
@JoinTable(name = "Object", joinColumns = { @JoinColumn(name = "parentId") }, inverseJoinColumns = { @JoinColumn(name = "id") })
public List<Attachment> getAttachments()
{
if (attachments == null)
{
attachments = new ArrayList<Attachment>();
}
return attachments;
}
我会提到这里有一些继承。
Attachment是KObject(db中的表名Object)的子类,KObject包含了用来映射回Comment的parentId(也是KObject的子类)。
为澄清起见,这是我给实体经理的电话:
public <T> T findById(Class<T> objClass, String id)
{
EntityManager em = theEMF.createEntityManager();
em.getTransaction().begin();
try {
T obj = em.find(objClass, id);
return obj;
} catch(NoResultException e) {
return null;
} finally {
em.getTransaction().commit();
em.clear();
em.close();
}
}
theEMF 是一个在首次使用时初始化的静态成员变量。
我认为解决方案是@OneToMany(fetch=FetchType.EAGER),但这没有效果。我究竟做错了什么?