Spring boot JPA 如何在多关系中给定一个对象查询@OneToMany 关系

Spring boot JPA how to query a @OneToMany relationship given one object in the many relationship

我已经看到了一些相关的问题,但我似乎无法为我正在尝试做的事情找到正确的答案。 我有两个 tables 工作和工人,一个工作可以有很多工人,简化实体

@Entity
@Table(name = "jobs")
data class Job(
    @Id
    @Type(type = "pg-uuid")
    val id: UUID = UUID.randomUUID()
) {
    @ManyToOne
    var office: Office? = null

    @OneToMany(targetEntity = Worker::class)
    var requests: MutableList<Worker> = mutableListOf()
}

我希望能够获取特定工作人员的工作列表

我已经尝试了一些本机查询和非本机查询,但现在尝试仅通过 namedMethods 进行查询,老实说,我认为这里的任何工作似乎都应该在我的工作回购中工作

@Repository
interface JobsRepo : CrudRepository<Job, UUID> {

    @Query("SELECT j FROM Job j WHERE id = ?1")
    fun findJobById(id: UUID): Job?

    @Query("SELECT j FROM Job j WHERE office_id = ?1")
    fun findJobsByOffice(id: UUID): List<Job>?

    @Modifying
    @Transactional
    @Query("UPDATE jobs SET job_status = 4 WHERE job_status = 1 AND start_time < ?1", nativeQuery = true)
    fun expireJobs(date: Date)

    fun findByRequests_Worker(worker: Worker): List<Job>?

}

我不太确定如何查询数组属性

requests

有一名工人的投入。我也尝试查询工作人员的 UUID,因为那是连接中的内容 table

JPA 使用两个外键创建一个连接 table table 是

jobs_requests

和列

job_id UUID
requests_id UUID

您提到一个 Job 可以有多个 worker,并且您还提到您想要获取特定 worker 的作业列表。所以这听起来像是 ManyToMany 关系而不是 OneToMany。

对于多对多关系,连接 table 是不可避免的。您需要在两个实体上指定 @ManyToMany 注释,然后您可以使用 WorkerRepository 查询工作人员,然后获取该工作人员的工作列表,您只需要通过 worker.getJobs().

以下是多对多关系的设置,希望对您有所帮助:

@Entity
@Table(name = "jobs")
data class Job (
    @ManyToMany
    @get:ManyToMany
    @get:JoinTable(
            name = "worker_job",
            joinColumns = [JoinColumn(name = "job_id")],
            inverseJoinColumns = [JoinColumn(name = "worker_id")]
    )
    val worker: Set<Worker> = HashSet()

)
@Entity
@Table(name = "worker")
data class Worker (
    @ManyToMany
    @get:ManyToMany
    @get:JoinTable(
            name = "worker_job",
            joinColumns = [JoinColumn(name = "worker_id")],
            inverseJoinColumns = [JoinColumn(name = "job_id")]
    )
     val jobs: Set<Jobs> = HashSet()
)

还值得注意的是,对于所有实际用途,您应该尽量避免显式 ManyToMany 注释。您应该创建一个新的 Entity/Table,它将包含 Job 和 Worker 的字段,它们都与各自的实体有 ManyToOne 关联。

你应该避免显式 ManyToMany 的原因是,当有一个特定的工作时,例如 JavaDev,并且有 1000 个 Workers 在给定的工作上。有一次你有一个 JavaDev 实体,你想要获得所有年龄在 20 到 25 岁之间的工人。为此,可以迭代 Workers 列出 JavaDev 实体的一部分并将其过滤掉。当发生这种情况时,有 2 种情况:

  1. Workers 列表是一个惰性关联,当您尝试访问它时,hibernate 将向数据库发送 1000(n+1 个问题)查询。
  2. Workers 列表是一个急切的关联,hibernate 将向数据库发送相同数量的查询,但是一旦您尝试获取 JavaDev实体。

因此,您的执行时间将会增加,因为数据库本身会产生不必要的负载量。在更大的项目中,这会变得更加复杂。

如果您创建自己的 manytomany(例如 job_workers)table,并附带存储库和服务,那么所有这些都可以避免,来自 您将能够更有效地查询您的数据。