如何将 FindAllBy 与 JpaRepository 中的多个字段一起使用?
Posted
技术标签:
【中文标题】如何将 FindAllBy 与 JpaRepository 中的多个字段一起使用?【英文标题】:How to use FindAllBy with multiple fields in a JpaRepository? 【发布时间】:2019-08-09 18:45:31 【问题描述】:您可以在下面找到一个显示我的问题的最小示例:
src/main/kotlin/com/mytest/findallbytest/Application.kt
:
package com.mytest.findallbytest
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class MyTestApplication
fun main(args: Array<String>)
runApplication<MyTestApplication>(*args)
src/main/kotlin/com/mytest/findallbytest/model/Thing.kt
:
package com.mytest.findallbytest.model
import org.springframework.data.jpa.domain.AbstractPersistable
import javax.persistence.Entity
import javax.persistence.Table
@Entity
@Table(name = "things")
class Thing(
val foo: Long,
val bar: Long
) : AbstractPersistable<Long>()
src/main/kotlin/com/mytest/findallbytest/repository/ThingRepository.kt
:
package com.mytest.findallbytest.repository
import com.mytest.findallbytest.model.Thing
import org.springframework.data.jpa.repository.JpaRepository
interface ThingRepository : JpaRepository<Thing, Long>
fun findAllByFooAndBar(foos: Iterable<Long>, bars: Iterable<Long>): Iterable<Thing>
src/main/resources/application.yml
:
spring:
datasource:
url: jdbc:h2:mem:db;MODE=PostgreSQL
src/main/resources/db/migration/V1__things.sql
:
CREATE SEQUENCE HIBERNATE_SEQUENCE;
CREATE TABLE things (
id BIGINT PRIMARY KEY NOT NULL,
foo BIGINT NOT NULL,
bar BIGINT NOT NULL
);
src/test/kotlin/com/mytest/findallbytest/FullTest.kt
:
package com.mytest.findallbytest
import com.mytest.findallbytest.model.Thing
import com.mytest.findallbytest.repository.ThingRepository
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension
@ExtendWith(SpringExtension::class)
@SpringBootTest
class FullTest
@Autowired
lateinit var repo: ThingRepository
@Test
fun `basic entity checks`()
repo.save(Thing(1, 2))
repo.save(Thing(3, 4))
repo.save(Thing(1, 4))
assertThat(repo.findAll()).hasSize(3)
// ERROR: Expected size:<2> but was:<0>
assertThat(repo.findAllByFooAndBar(listOf(1L, 3L), listOf(2L, 4L))).hasSize(2)
问题是,findAllByFooAndBar
返回一个空列表。但是我希望它返回三个已保存实体中的前两个。
我做错了什么,我的目标或查询多个实体,匹配多个字段,如何实现?
【问题讨论】:
【参考方案1】:fun findAllByFooInAndBarIn(foos: Iterable<Long>, bars: Iterable<Long>): Iterable<Thing>
【讨论】:
感谢您的快速回答,但findAllByFooInAndBarIn
也返回一个空列表。另外,我希望查询不包括Thing(1, 4)
。刚刚相应地编辑了我的问题。【参考方案2】:
一个(不是很好)解决方案是手动创建一个查询并使用EntityManager
发送它:
@Repository
class SecondThingRepository(private val entityManager: EntityManager)
fun selectByFoosAndBars(foosAndBars: Iterable<Pair<Long, Long>>): Iterable<Thing>
val pairsRepr = foosAndBars.joinToString(prefix = "(", postfix = ")") "($it.first, '$it.second')"
val query: TypedQuery<Thing> = entityManager.createQuery("SELECT t FROM Thing t WHERE (t.foo, t.bar) IN $pairsRepr", Thing::class.java)
return query.resultList
然后:
repo2: SecondThingRepository
...
assertThat(repo2.selectByFoosAndBars(listOf(Pair(1L, 2L), Pair(3L, 4L)))).hasSize(2)
【讨论】:
以上是关于如何将 FindAllBy 与 JpaRepository 中的多个字段一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
Swinject:如何将委托模式与接口隔离(类与接口)一起使用?