Spring JPA NoRepositoryBean 查询
Spring JPA NoRepositoryBean Queries
如何在 @NoRepositoryBean
方法中使用 @Query
和 @MappedSuperclass
?
我有 @MappedSuperclass 时间(基础有长 id)
@MappedSuperclass
public abstract class Temporal extends Basis<Long> {
private Long temporalCode;
private Date dateBegin;
private Date dateEnd;
// getters/setters
}
和@NoRepositoryBean TemporalRepository
@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);
}
KI 认为您不能这样做,因为 @NoRepositoryBean
用于告诉 spring 不要为此接口创建存储库代理 bean。这种接口用于公开一些除了具体存储库接口之外的其他方法。那样的话你就得extend
这样的接口了,我再举个例子来解释一下:
假设我有 Student
和 Teacher
实体:
现在我的界面如下:
@NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
T findById(int id);
}
现在我们必须编写一个具体的 repo 接口,例如:
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。
实际上你可以使用 SpEL 表达式。
Spring Data JPA reference
所以我们可以用 #{#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);
}
如何在 @NoRepositoryBean
方法中使用 @Query
和 @MappedSuperclass
?
我有 @MappedSuperclass 时间(基础有长 id)
@MappedSuperclass
public abstract class Temporal extends Basis<Long> {
private Long temporalCode;
private Date dateBegin;
private Date dateEnd;
// getters/setters
}
和@NoRepositoryBean TemporalRepository
@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);
}
KI 认为您不能这样做,因为 @NoRepositoryBean
用于告诉 spring 不要为此接口创建存储库代理 bean。这种接口用于公开一些除了具体存储库接口之外的其他方法。那样的话你就得extend
这样的接口了,我再举个例子来解释一下:
假设我有 Student
和 Teacher
实体:
现在我的界面如下:
@NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
T findById(int id);
}
现在我们必须编写一个具体的 repo 接口,例如:
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。
实际上你可以使用 SpEL 表达式。
Spring Data JPA reference
所以我们可以用 #{#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);
}