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 种情况:
- Workers 列表是一个惰性关联,当您尝试访问它时,hibernate 将向数据库发送 1000(n+1 个问题)查询。
- Workers 列表是一个急切的关联,hibernate 将向数据库发送相同数量的查询,但是一旦您尝试获取 JavaDev实体。
因此,您的执行时间将会增加,因为数据库本身会产生不必要的负载量。在更大的项目中,这会变得更加复杂。
如果您创建自己的 manytomany(例如 job_workers)table,并附带存储库和服务,那么所有这些都可以避免,来自 您将能够更有效地查询您的数据。
我已经看到了一些相关的问题,但我似乎无法为我正在尝试做的事情找到正确的答案。 我有两个 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 种情况:
- Workers 列表是一个惰性关联,当您尝试访问它时,hibernate 将向数据库发送 1000(n+1 个问题)查询。
- Workers 列表是一个急切的关联,hibernate 将向数据库发送相同数量的查询,但是一旦您尝试获取 JavaDev实体。
因此,您的执行时间将会增加,因为数据库本身会产生不必要的负载量。在更大的项目中,这会变得更加复杂。
如果您创建自己的 manytomany(例如 job_workers)table,并附带存储库和服务,那么所有这些都可以避免,来自 您将能够更有效地查询您的数据。