2

我的班级模型如下。有一个名为“IdClass”的基类,它具有 id、版本、createdBy、createdDate 等信息。所有其他实体类都派生自这个基类(因此会自动获取 IdClass 属性,如 id、版本等)。

我使用 Hibernate/JPA 来处理这些类的数据库级实现。

我添加了另一个名为 Attachment 的类,其中包含一个用于存储任何附件的 blob。为了保持通用性,我在附件中添加了对 IdClass 的引用。这样,任何实体都可以有一个或多个附件,而无需在每个表中存储 blob 的开销。

问题是当我尝试插入附件对象时。我需要添加对指定实体的引用。我有一个通用服务方法“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 对象(无需在所有子类表上产生连接)?

4

1 回答 1

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 的完整子类实体,而不仅仅是超类字段。而且它不会因“太多表”错误而死。

于 2014-10-17T00:15:04.553 回答