我正在使用一个扩展 Spring Data JpaRepository 的存储库,并希望让它扩展另一个接口。
以前,我的数据库存储库看起来像这样:
interface PublicTransportPricingZoneRepository : JpaRepository<PublicTransportPricingZone, Long> {
}
我现在创建了另一个界面
TransitTicketRepo
,定义如下
interface TransitTicketRepo {
fun findPossibleTickets(geometry: Geometry): Collection<TransitTicket>
}
现在想使用
PublicTransportPricingZoneRepository
中的默认方法实现接口。我尝试通过将 PublicTransportPricingZoneRepository 的代码更改为来解决此问题
interface PublicTransportPricingZoneRepository : JpaRepository<PublicTransportPricingZone, Long>, TransitTicketRepo {
fun findPossibleTickets(geometry: Geometry): Collection<TransitTicket> {
// do something
return emptyList()
}
}
但启动应用程序时收到以下错误消息。
org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.Collection PublicTransportPricingZoneRepository.findPossibleTickets(Geometry); Reason: Failed to create query for method public abstract java.util.Collection...
我假设解决方案是以某种方式告诉 spring data 停止自动生成
findPossibleTickets
的查询,但一直无法找出如何实现。
我最近再次遇到了这个问题(请参阅前面的评论),其中 Spring Boot Data 尝试生成接口的实现,尽管已经有一个实现。这与原来的问题并不完全相同,但也许我的解决方案对某人有用。
我从这个开始:
data class MyEntity(val name: String, val creationDateTime: ZoneDateTime)
@Repository
interface MyEntityRepository : JpaRepository<MyEntity, Long> {
fun findFirstByNameOrderByCreationDateTimeDesc(name: String)
}
函数
findFirstByNameOrderByCreationDateTimeDesc
有一个非常长且令人困惑的名称,所以我只是想添加一个默认函数 findMostRecent
来指向另一个函数。
我最初的尝试是这样的:
data class MyEntity(val name: String, val creationDateTime: ZoneDateTime)
@Repository
interface MyEntityRepository : JpaRepository<MyEntity, Long> {
fun findFirstByNameOrderByCreationDateTimeDesc(name: String)
fun findMostRecent(name: String) = findFirstByNameOrderByCreationDateTimeDesc(name)
}
但是,这以
PropertyReferenceException
结束,因为 Spring Boot Data 会尝试在 MyEntity
上创建属性“findMostRecent”的实现,而这显然不存在。
在网上,您可以找到涉及添加另一个接口并具有抽象类实现的解决方案,但这些对我不起作用,因为我想引用接口中获取生成的实现的函数。
最终我决定使用 Kotlin 扩展函数 将所需的函数添加到存储库中:
data class MyEntity(val name: String, val creationDateTime: ZoneDateTime)
@Repository
interface MyEntityRepository : JpaRepository<MyEntity, Long> {
fun findFirstByNameOrderByCreationDateTimeDesc(name: String)
}
fun MyEntityRepository.findMostRecent(name: String) =
findFirstByNameOrderByCreationDateTimeDesc(name)
通过这个我可以在存储库上调用
myEntityRepository.findMostRecent("someValue")
,而不会出现 Spring Boot Data 投诉。
你可以这样做这样
简而言之:
@Repository
// Your bean that will be glued together by spring
interface PublicTransportPricingZoneRepository extends JpaRepository<...>, PublicTransportPricingZoneCustomRepository {
// Other methods, but everything must be annotated with @Query or possible for spring to guess what it needs to do from its name (google derived methods)
}
interface PublicTransportPricingZoneCustomRepository {
// define custom methods
List<String> nameIsNotImportant();
}
@Service
// naming here is important - it must be names as interface + Impl, otherwise spring won't pick it up
// apart from that, it's a regular bean - you can Autowire, etc
class PublicTransportPricingZoneCustomRepositoryImpl implementats PublicTransportPricingZoneCustomRepository {
// Implement custom methods
@Overridden
public List<String> nameIsNotImportant() {
// impl
}
}