【问题标题】:Inheritance in HQL with Spring Data JPA使用 Spring Data JPA 继承 HQL
【发布时间】:2012-02-04 14:02:12
【问题描述】:

我有一组继承自一个超类的类:

   Super
     |
     +------+-------+
     Aaaa   Bbbb    Cccc

然后每个 Aaaa、Bbbb、Cccc 都应该包含方法 findByTag。问题是我无法笼统地定义它。以下示例为 Aaaa 定义了特定的 findByTag。

public interface AaaaRepository extends SuperRepository<Aaaa> {
    @Query("select distinct a from Aaaa a " +
            "join a.tags t " +
            "join fetch a.locale where t = ?1")
    public List<Event> findByTag(Tag t);
}

请注意,超类是@MappedSuperclass,并且在数据库中没有自己的表。

我想在查询中使用某种“超级”,它将在每个类中被其名称替换。

我的第二个问题是我不知道如何强制 @ElementCollection 被急切地获取。我必须始终在查询中明确地说“join fetch”。如果它没有被提取,一旦事务完成,我就无法访问那些我没有明确提取的对象。 (LazyFetch 异常...)

谢谢

【问题讨论】:

    标签: java hibernate jpa spring-data


    【解决方案1】:

    查看documentation,自定义实现部分,这种方法怎么样:

    1. 创建一个接口,扩展存储库并使用您的 findByTag 方法,无需注释。
    2. 创建该类的实现,并在方法实现中使用 JPA 标准。您还需要一个类字段来保存域对象的实际类,因为泛型在编译时被删除。然后您使用该字段来构建标准。
    3. 阅读文档以将此实现用作存储库工厂的基类,然后 Spring Data 将基于此自定义构建其他存储库的实现。

      public interface MyRepository<T, ID> extends JpaRepository<T, ID> {        
          public List<Event> findByTag(Tag t);
      }
      
      public class MyRepositoryImpl<T, ID> implements MyRepository<T, ID> {
      
          private Class<T> actualClass; // initialized in the constructor
      
          public List<Event> findByTag(Tag t) {
               // here you build the criteria using actualClass field, and execute it.
          }
      }
      
      public interface AaaaRepository extends MyRepository <Aaaa, Integer> {
          // other methods...
      }
      

    查看“Example 1.16. Custom repository factory bean”的文档来创建工厂bean。

    Spring 实例化 AaaaRepository 的实现时,会使用 MyRepositoryImpl 作为基类。

    这对你有用吗?

    【讨论】:

    • 好吧,单个注释的美感已经消失了,但我同意这个问题可能没有其他解决方案。
    【解决方案2】:

    我不会这样写,而是创建一个类似于下面的伪 java 代码的数据访问对象:

    class DAO<T> {
         private Class<T> clazz;
         DAO( Class<T> class) { this.clazz = t; }
         @PersistenceContext
         private EntityManager em;
    
         public List<T> findByTag(Tag t ) {
            Query q = em.createQuery( "select from " + clazz.getSimpleName + "....";
            ...
            return q.getResultList();
         }
    }
    

    希望对你有帮助!

    【讨论】:

    • 感谢您的解决方案,但是我对使用 Spring data JPA 实现这一点很感兴趣。
    【解决方案3】:

    最后,我对 Spring Data JPA 的行为和不灵活感到非常不满,因此我为自己编写了一个小工具,用于以简单的方式构建查询。使用示例如下:

    https://github.com/knyttl/Maite/wiki/Maite-Persistence

    有两个子类和定义功能的父类。但诀窍在于构建查询的流畅界面。

    它只是在开始,但它已经起作用了,所以我没有重复和正确的继承。

    父类的小例子-查看上面的链接了解详细信息:

    @Autowired
    EntityManager em;
    
    protected abstract String getName();
    
    protected Clause select() {
        return em
                .select("DISTINCT i")
                .from(this.getName(), "i")
                .joinFetch("i.locale lf")
    }
    
    public List<T> findByTag(Tag tag) {
        return (T) this.select()
                .join("i.tags t")
                .where("t = ?", tag)
                .fetchAll();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-18
      • 2012-09-09
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多