我的班级模型是以下列方式。 有一个名为“IdClass”的Base类,它有id,version,createdBy,createdDate等信息。 所有其他实体类派生自此基类(因此自动获取id,版本等IdClass属性)。
我使用Hibernate / JPA来处理这些类的数据库级实现。
我添加了另一个名为Attachment的类,其中包含一个用于存储任何附件的blob。为了保持通用性,我在附件中添加了对IdClass的引用。这样,任何实体都可以拥有一个或多个附件,而不必在每个表中存储blob。
问题是当我尝试插入Attachment对象时。我需要添加对指定实体的引用。我有一个公共服务方法“createAttachment”,它接受一个附件对象和实体的“id”。现在,在这个方法中,我需要使用这个'id'找到实体,然后将它与新的Attachment对象相关联。为此,我编写了以下方法“findEntity”
public IdClass findEntity(Long id) {
IdClass entity;
entity = (IdClass) getSession().get(IdCass.class, id);
return entity;
}
但是当这个方法被执行时,我得到一个异常,说“太多表:MySQL只能在一个连接中使用61个表”。 我有超过100个实体。休眠/ JPA。看起来Hibernate / JPA试图在IdClass的所有子类上进行连接,只需查询IdClass表本身就足够了(因为id存储在IdClass表中)。
另外,我尝试创建Hibernate Criteria查询来搜索实体。即使这会导致相同的表太多错误。
请让我知道我做错了什么。如何仅使用id获取IdClass对象(不必在所有子类表上引入连接)?
答案 0 :(得分:0)
这不是最简洁的解决方案,但我能够使用NamedQuery
解决同一问题:
@NamedQuery(name="BaseItem.findById",
query="SELECT a FROM BaseItem a WHERE a.id = :id")
然后我有以下实用程序函数来调用查询(使用纯JPA):
@SuppressWarnings("unchecked")
public static <T extends BaseItem> T findById(Class<T> entityClass, long id,
EntityManager em) {
try {
Query query = em.createNamedQuery("BaseItem.findById");
query.setParameter("id", id);
T result = (T)query.getSingleResult();
return result;
}
catch (NoResultException ignored) {
//expected
}
catch (Exception e) {
LOG.warn("Failed to execute 'findByAndId' query for id=" + id, e);
}
//couldn't find it
return null;
}
使用它通过id通过超类查找任意实体,我调用:
BaseItemDAO.findById(BaseItem.class, id, em);
然后JPA / Hibernate在幕后发挥其魔力,确保返回的内容是提供的id的完整子类实体,而不仅仅是超类字段。并且它没有因“太多表”错误而死亡。