spring-data-jpa - 使用 Spring Data JPA 的 Kotlinic 模式 "query by example"

标签 spring-data-jpa kotlin

Spring Data JPA 引入了一个不错的功能,"query by example" (QBE) .您可以通过构造实体的实例来表达您的搜索条件。

您不必编写 JPQL。它比 repository query derivation 使用更少的“魔法”。 .语法很好。它可以防止琐碎的存储库代码爆炸。它可以很好地经受重构。

但有一个问题:QBE 仅在您可以部分构造一个对象时才有效。

这是我的实体:

@Entity
@Table(name="product")
data class Product(
        @Id val id: String,
        val city: String,
        val shopName: String,
        val productName: String,
        val productVersion: Short
)

这是我的存储库(空!这是 QBE 的一个好东西):

@Repository
interface ProductRepository : JpaRepository<Product, String>

以下是获取 List<Product> 的方法— 在某个商店、某个城市出售的所有产品:

productRepository.findAll(Example.of(Product(city = "London", shopName="OkayTea")))

或者至少,这是我想要做的。有问题。 不可能构造这个对象:

Product(city = "London", shopName="OkayTea")

这是因为 Product的构造函数要求 all 定义其字段。确实:这就是我大部分时间想要的。

Java 中通常的折衷方案是:使用无参数构造函数构造实体,使所有内容可变,不保证完整性。

有没有很好的 Kotlin 模式来解决这个问题:

  • 一般要求所有参数在构造时实例化
  • 提供一些机制来生成部分构造的实例以与示例 API 一起使用

诚然,这些看起来完全是相互矛盾的目标。但也许还有另一种方法可以解决这个问题?

例如:也许我们可以制作一个模拟/代理对象,它看起来是一个产品,但没有相同的构造约束?

最佳答案

您可以使用带有非空字段的 kotlin 数据类进行示例查询,但它看起来不如 java 代码。

val matcher = ExampleMatcher.matching()
    .withMatcher("city", ExampleMatcher.GenericPropertyMatcher().exact())
    .withMatcher("shopName", ExampleMatcher.GenericPropertyMatcher().exact())
    .withIgnorePaths("id", "productName", "productVersion")

val product = Product(
    id = "",
    city = "London",
    shopName = "OkayTea",
    productName = "",
    productVersion = 0
)

productRepository.findAll(Example.of(product, matcher))

如果您将它用于集成测试,并且您不想使用仅在所述测试中使用的方法污染您的 Repository 接口(interface),并且 您在数据库实体类中有很多字段,您可以创建一个扩展函数来提取将在查询中忽略的字段。

private fun <T : Any> KClass<T>.ignoredProperties(vararg exclusions: String): Array<String> {
    return declaredMemberProperties
        .filterNot { exclusions.contains(it.name) }
        .map { it.name }
        .toTypedArray()
}

并像这样使用它:

val ignoredFields = Product::class.ignoredProperties("city", "shopName")

val matcher = ExampleMatcher.matching()
    .withMatcher("city", ExampleMatcher.GenericPropertyMatcher().exact())
    .withMatcher("shopName", ExampleMatcher.GenericPropertyMatcher().exact())
    .withIgnorePaths(*ignoredFields)

关于spring-data-jpa - 使用 Spring Data JPA 的 Kotlinic 模式 "query by example",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45010230/

相关文章:

java - 错误 : Could not find org. jetbrains.kotlin:kotlin-stdlib-jdk8

android - 这个应用程式可以在单一 Activity 中运作,但在加入应用程式抽屉时会当机

java - 是否可以以编程方式访问 Android Q (SDK >= 29) 上的下载文件夹?

java - 当从 @Async 方法的 catch block 进行此 JPA 调用时,在 JPA 中使用主键删除单个记录不会生效

java - 在 spring 中,一对多实体关系不获取数据

enums - Kotlin - 将枚举值分配给没有 .value 的变量

kotlin - kotlin-stdlib-common 中的随机性来源

java - 在save()之前如何停止Spring数据JPA进行SELECT?

Spring Boot + JPA - CrudRepository更新再读取

java - Spring jpa onetomany 仅返回一个元素