通过委托增强Spring数据存储库

我最近写了几篇有关科特林代表团的文章。 通过这样做,我实现了一种将其应用于Spring Data存储库的有用方法。 这将使Spring Data在提供定制路线的同时继续散布一些魔力。 这篇文章中显示的代码在Kotlin中,但仍然与Java有关。

这篇文章使用R2DBC,但是内容足够通用,可以应用于任何Spring Data模块。

Reading Asynchronous [RDBMS access with Spring Data R2DBC and Class delegation in Kotlin would be beneficial here if you do not have much background knowledge in these areas.

作为回顾。 Spring Data提供的魔力是什么?

Spring Data允许您编写一个仅需要定义所需查询的接口。 然后它将完成创建实现和为您注入依赖项的所有工作。 看起来像这样:

@Repository
interface PersonRepository : R2dbcRepository<Person, Int> {

  @Query("SELECT * FROM people WHERE age > $1")
  fun findAllByAgeGreaterThan(age: Int): Flux<Person>
}
由于使用的是Spring Data R2DBC,因此尚不完全支持完全推断的查询。 这就是为什么手动写出查询的原因。

缺点是它正在基于接口创建实现。 因此,如果要进行任何类型的自定义,则需要自己创建接口的实例,注入其依赖关系并实现每个查询。 例如:

class PersonRepositoryImpl(
  private val entity: RelationalEntityInformation<Person, Int>,
  private val databaseClient: DatabaseClient,
  converter: R2dbcConverter,
  private val accessStrategy: ReactiveDataAccessStrategy
) : SimpleR2dbcRepository<Person, Int>(entity, databaseClient, converter, accessStrategy),
  PersonRepository {

  override fun findAllByAgeGreaterThan(age: Int): Flux<Person> {

    val mapper: StatementMapper.TypedStatementMapper<Person> =
      accessStrategy.statementMapper.forType(entity.javaType)

    val selectSpec: StatementMapper.SelectSpec = mapper
      .createSelect(entity.tableName)
      .withProjection(accessStrategy.getAllColumns(entity.javaType))
      .withCriteria(Criteria.where("age").greaterThan(age))

    val operation: PreparedOperation<*> = mapper.getMappedObject(selectSpec)

    return databaseClient.execute().sql(operation).`as`(entity.javaType).fetch().all()
  }
}
是的,该查询代码可能很糟糕,我相信您可以做得更好。 你明白我的意思。

可以通过委派基于您的接口实现的存储库Spring来消除创建此类的麻烦。 然后,您可以添加所需的所有自定义。

在Kotlin中,这看起来像:

@Repository
class DelegatingPersonRepository(private val delegate: PersonRepository) :
  PersonRepository by delegate {

  override fun <S : Person> save(objectToSave: S): Mono<S> {
    // override `save` implementation
  }

  // any other overrides (kotlin provides delegated implementations)
}

在Java中,这比较麻烦,但是仍然可以轻松实现:

@Repository
public class DelegatingPersonRepository implements PersonRepository {

  private final PersonRepository delegate;

  public DelegatingPersonRepository(PersonRepository delegate) {
    this.delegate = delegate;
  }

  @Override
  public Flux<Person> findAllByAgeGreaterThan(int age) {
    return delegate.findAllByAgeGreaterThan(age);
  }

  @Override
  public <S extends Person> Mono<S> save(S entity) {
    // override `save` implementation
  }

  // all other implementations of `PersonRepository` functions
}
在两个版本中Delegating人资料库调用执行findAllByAgeGreaterThan定义于人资料库。 到目前为止,还没有直接花费精力来编写查询数据库的功能。

当。。。的时候Delegating人资料库使用时,所有未被覆盖的函数调用将委托给人资料库春天创造的。

对于像我这样的人,他真的不喜欢将SQL查询放在一起并编写所有转换代码。 以这种方式使用委派确实可以使您充分利用Spring Data的好处,同时仍然为您提供自定义结果的空间。 您节省的代码量实际上可能不是那么大。 但是,将其组合在一起所需的工作量大大减少了。 让Spring为您完成所有繁重的工作!

If you enjoyed this post or found it helpful (or both) then please feel free to follow me on Twitter at @LankyDanDev and remember to share with anyone else who might find this useful!

from: https://dev.to//lankydandev/augmenting-a-spring-data-repository-through-delegation-5efp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值