Spring JPA NoRepositoryBean 查询

问题描述 投票:0回答:3

如何在

@Query
方法中使用
@NoRepositoryBean
@MappedSuperclass

我有@MappedSuperclass 时间(基础有长ID)

@MappedSuperclass
public abstract class Temporal extends Basis<Long> {

    private Long temporalCode;
    private Date dateBegin;
    private Date dateEnd;
    // getters/setters
}

@NoRepositoryBeanTemporalRepository

@NoRepositoryBean
public interface TemporalRepository<T extends Temporal> extends JpaRepository<T, Long> {
//    this two are ok
    List<T> findByTemporalCode(Long temporalCode);
    List<T> findByTemporalCodeAndDateBeginBeforeAndDateEndAfter(Long temporalCode, Date dateBegin, Date dateEnd);

//    query not working because Temporal is not an @Entity
//    @Query("select t from Temporal t 
//         where (t.dateBegin < ?1 or t.dateBegin is null) 
//         and (t.dateEnd < ?1 or t.dateEnd is null) ")
//    List<T> findByDate(Date date);
}

更新:
例如,我有时间实体 Worker:

@Entity
public class Worker extends Temporal {
//    fields and methods here
}

public interface WorkerRepo extends TemporalRepository<Worker> {
//    Looks like it will work but I don't want to write the same method in each TemporalRepository subclass
//    @Query("select w from Worker w where (w.dateBegin < ?1 or w.dateBegin is null) and (w.dateEnd < ?1 or w.dateEnd is null) ")
//    List<Worker> findByDate(Date date);
}
java spring hibernate spring-data-jpa
3个回答
3
投票

实际上你可以使用 SpEL 表达式。 Spring Data JPA 参考
所以我们可以用

#{#entityName}

替换超类的名称

参考示例:

@MappedSuperclass
public abstract class AbstractMappedType {
  …
  String attribute
}

@Entity
public class ConcreteType extends AbstractMappedType { … }

@NoRepositoryBean
public interface MappedTypeRepository<T extends AbstractMappedType>
  extends Repository<T, Long> {

  @Query("select t from #{#entityName} t where t.attribute = ?1")
  List<T> findAllByAttribute(String attribute);
}

public interface ConcreteRepository
  extends MappedTypeRepository<ConcreteType> { … }

我的示例的解决方案:

@NoRepositoryBean
public interface TemporalRepository<T extends Temporal> extends JpaRepository<T, Long> {
    List<T> findByTemporalCode(Long temporalCode);

    List<T> findByTemporalCodeAndDateBeginBeforeAndDateEndAfter(Long temporalCode, Date dateBegin, Date dateEnd);

    @Query("select t from #{#entityName} t 
        where (t.dateBegin < ?1 or t.dateBegin is null)
        and (t.dateEnd < ?1 or t.dateEnd is null)")
    List<T> findByDate(Date dateBegin);
}

2
投票

KI 认为你不能这样做,因为

@NoRepositoryBean
用于告诉 spring 不要为此接口创建存储库代理 bean。此类接口用于公开除具体存储库接口之外的一些附加方法。那你就必须
extend
这样的接口,我再举个例子来解释一下:

考虑我有

Student
Teacher
实体:

现在我的界面为:

@NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
  T findById(int id);
}

现在我们必须编写一个具体的存储库接口,例如:

public interface StudentRepository extends ReadOnlyRepository<Student, Long> {
  //override the methods of `ReadOnlyRepository` with @query
}

public interface TeacherRepository extends ReadOnlyRepository<Teacher, Long> { 

//override the methods of `ReadOnlyRepository` with @query
}

通过这种方式,可以通过简单地声明 JPA 命名查询

Student.findById
Teacher.findById
来手动定义学生和教师的查询。使用这种方法,您可以轻松地为您的应用场景定制基础接口。

因此使用@NoRepositoryBean来避免创建存储库bean。


0
投票

我最近看到一篇有趣的文章,讨论如何使用 @NoRepositoryBean 来简化数据库访问:

使用@NoRepositoryBean简化数据库访问

本文深入介绍了此注释如何帮助创建基本存储库接口,而无需绑定到特定于数据库的实现。对于任何想要了解此注释的实际应用的人来说,这都是一本很好的读物。

我认为这可能对那些探索类似解决方案的人有帮助

© www.soinside.com 2019 - 2024. All rights reserved.