Java 使用Spring数据JPA在HQL中进行继承

Java 使用Spring数据JPA在HQL中进行继承,java,hibernate,jpa,spring-data,Java,Hibernate,Jpa,Spring Data,我有一组从单个超类继承的类: Super | +------+-------+ Aaaa Bbbb Cccc Aaaa、Bbbb、Cccc中的每一个都应该包含findByTag方法。问题是我无法概括地定义它。下面的示例为Aaaa定义了特定的findByTag public interface AaaaRepository extends SuperRepository<Aaaa> { @Query("select distinc

我有一组从单个超类继承的类:

   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);
}
公共接口AaaaRepository扩展超级存储库{
@查询(“从Aaaa中选择不同的a”+
“加入a.t”+
“join fetch a.locale,其中t=?1”)
公共列表findByTag(标签t);
}
请注意,超类是@MappedSuperclass,并且在数据库中没有自己的表

我想在查询中使用某种“Super”,它在每个类中都会被其名称替换

我的第二个问题是,我不知道如何强制急切地获取@ElementCollection。我必须在查询中明确地说“joinfetch”。如果没有提取,一旦事务完成,我就无法访问那些我没有显式提取的对象。(懒散的人…)


谢谢

我将创建一个类似下面的伪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();
     }
}
类DAO{
私人课堂;
DAO(Class){this.clazz=t;}
@持久上下文
私人实体管理者;
公共列表findByTag(标记t){
Query q=em.createQuery(“从“+clazz.getSimpleName+”…”中选择”;
...
返回q.getResultList();
}
}

希望它能有所帮助!

我将创建一个类似下面的伪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();
     }
}
类DAO{
私人课堂;
DAO(Class){this.clazz=t;}
@持久上下文
私人实体管理者;
公共列表findByTag(标记t){
Query q=em.createQuery(“从“+clazz.getSimpleName+”…”中选择”;
...
返回q.getResultList();
}
}
希望能有所帮助!

查看“自定义实现”部分,该方法如何:

  • 创建一个扩展存储库的接口,该接口包含您的findByTag方法,不带注释
  • 创建该类的实现,并在方法实现中使用JPA标准。还需要一个类字段来保存域对象的实际类,因为泛型在编译时被擦除。然后使用该字段来构建标准
  • 阅读文档,将此实现用作存储库工厂的基类,然后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...
    }
    
    公共接口MyRepository扩展了JpaRepository{ 公共列表findByTag(标签t); } 公共类MyRepositoryImpl实现MyRepository{ 私有类actualClass;//在构造函数中初始化 公共列表findByTag(标记t){ //在这里,您使用actualClass字段构建标准,并执行它。 } } 公共接口AaaaRepository扩展了MyRepository{ //其他方法。。。 }
  • 查看文档中的“示例1.16.自定义存储库工厂bean”来创建工厂bean

    当Spring实例化aaarepository的实现时,它将使用MyRepositoryImpl作为基类

    这对您有用吗?

    查看“自定义实现”部分,您认为这种方法如何:

  • 创建一个扩展存储库的接口,该接口包含您的findByTag方法,不带注释
  • 创建该类的实现,并在方法实现中使用JPA标准。还需要一个类字段来保存域对象的实际类,因为泛型在编译时被擦除。然后使用该字段来构建标准
  • 阅读文档,将此实现用作存储库工厂的基类,然后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...
    }
    
    公共接口MyRepository扩展了JpaRepository{ 公共列表findByTag(标签t); } 公共类MyRepositoryImpl实现MyRepository{ 私有类actualClass;//在构造函数中初始化 公共列表findByTag(标记t){ //在这里,您使用actualClass字段构建标准,并执行它。 } } 公共接口AaaaRepository扩展了MyRepository{ //其他方法。。。 }
  • 查看文档中的“示例1.16.自定义存储库工厂bean”来创建工厂bean

    当Spring实例化aaarepository的实现时,它将使用MyRepositoryImpl作为基类


    这对您有用吗?

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

    有两个子类和父类定义了功能,但关键在于构建查询的流畅接口

    它只是在乞讨,但它已经起作用,所以我没有口是心非和正确的继承

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

    @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();
    }
    
    @Autowired
    实体管理器;
    受保护的抽象字符串getName();
    受保护子句select(){
    返回em
    .选择(“不同的i”)
    .from(this.getName(),“i”)
    .joinFetch(“i.locale lf”)
    }
    公共列表findByTag(标记标记){
    返回(T)this.select()
    .加入(“i.t”)
    .其中(“t=?”,标记)
    .fetchAll();
    }
    
    最后,我对Spring数据JPA的行为和灵活性感到非常不满意,因此我为自己编写了一个小工具,用于以简单的方式构建查询。使用示例如下:

    有两个子类和父类定义了功能,但关键在于流畅的界面