我正在尝试为扩展我的基本存储库的所有存储库定义通用查询:
@NoRepositoryBean
public interface DocumentRepository<T extends BaseDocument> extends JpaRepository<T, Long> {
@Query(value = "FROM BaseDocument bd WHERE (bd.createdAt IS NULL OR :to IS NULL OR bd.createdAt < :to) AND (bd.deletedAt IS NULL OR :from IS NULL OR bd.deletedAt > :from)")
Iterable<T> findAllActiveBetween(OffsetDateTime from, OffsetDateTime to);
}
@MappedSuperclass
@Where(clause="deleted_at IS NULL")
abstract public class BaseDocument {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private OffsetDateTime createdAt;
private OffsetDateTime deletedAt;
}
有问题的部分是在@Query 中使用BaseDocument。 可以在所有子存储库中定义这样的方法而不重复吗?
当您使用@MappedSuperclass时,继承的类不共享可供选择的表,因此每个类都需要单独的查询。存储库的继承在这里无法帮助您。
如果您使用其他继承策略,例如联合多表继承,则可以从超类的表中进行选择,然后您可以使用java对象进行导航。如果您需要在查询中使用子类的属性,那么每个子类当然需要实现自己的查询。
@NoRepositoryBean
public interface DocumentRepository<T extends BaseDocument> extends JpaRepository<T, Long> {
@Query(value = "FROM BaseDocument bd WHERE (bd.createdAt IS NULL OR :to IS NULL OR bd.createdAt < :to) AND (bd.deletedAt IS NULL OR :from IS NULL OR bd.deletedAt > :from)")
Iterable<T> findAllActiveBetween(OffsetDateTime from, OffsetDateTime to);
}
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="BaseDocument_TYPE")
@Table(name="BaseDocument")
abstract public class BaseDocument {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private OffsetDateTime createdAt;
private OffsetDateTime deletedAt;
}
@Entity
@DiscriminatorValue("TextDocument")
@Table(name="TextDocument")
public class TextDocument extends BaseDocument {
private String text;
}
@Entity
@DiscriminatorValue("AudioDocument")
@Table(name="AudioDocument")
public class AudioDocument extends BaseDocument {
private byte [] audio;
}
这可以通过 spel-expressions 实现,特别是 #{#entityName},它可在 spring-data-repositories 上使用,并扩展到存储库的域类型。
您需要做的就是将
BaseDocument
替换为 #{#entityName}
。
@NoRepositoryBean
public interface DocumentRepository<T extends BaseDocument> extends JpaRepository<T, Long> {
@Query(value = "FROM #{#entityName} bd WHERE (bd.createdAt IS NULL OR :to IS NULL OR bd.createdAt < :to) AND (bd.deletedAt IS NULL OR :from IS NULL OR bd.deletedAt > :from)")
Iterable<T> findAllActiveBetween(OffsetDateTime from, OffsetDateTime to);
}