在jpql中加入半相关实体

rhfm7lfc  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(385)

好 啊。。。我有三个实体:
A, B, C A 两者都没有关系 B 或者 C .

  1. @Entity
  2. class A{
  3. }
  4. ``` `B` 有一个 `A` 但对这件事一无所知 `C` ```
  5. @Entity
  6. class B {
  7. @ManyToOne
  8. @JoinColumn(name = "a_id", referencedColumnName = "id")
  9. A a;
  10. @Column(name = "sequence")
  11. String sequence;
  12. }
  13. ``` `C` 据说是匹配的 `A` 如果 `A` 与 `B` 那是一样的 `sequence` 值为 `C` ```
  14. @Entity
  15. class C {
  16. @Column(name = "sequence")
  17. String sequence;
  18. }

我现在想找到 A 一些过滤器适用的地方。我们把过滤器设为 TRUE ,暂时。
在sql中,我可能会这样写:

  1. SELECT DISTINCT a.id
  2. FROM
  3. a a
  4. LEFT JOIN b b ON b.a_id = a.id
  5. LEFT JOIN c c ON c.sequence = b.sequence
  6. WHERE
  7. (TRUE)
  8. ;

(参见。https://dbfiddle.uk/?rdbms=postgres_9.6&fiddle=e14a14707409bf667bc7544c5efea1d7 )
现在让我们在jpql中尝试同样的方法。。。 (TRUE) 显然是“不是一个有效的条件表达式”,所以我们把它换成 (1 = 1) . 其余的都很相似:

  1. SELECT DISTINCT a.id
  2. FROM
  3. A a
  4. LEFT JOIN B b ON b.a.id = a.id
  5. LEFT JOIN C c ON c.sequence = b.sequence
  6. WHERE
  7. (1 = 1)

... 或者至少这是我所期望的工作。
让我们找一个 EntityManager 并创建查询。。。

  1. inNewTransaction { em ->
  2. val query = """
  3. SELECT DISTINCT a.id
  4. FROM
  5. A a
  6. LEFT JOIN B b ON b.a.id = a.id
  7. LEFT JOIN C c ON c.sequence = b.sequence
  8. WHERE
  9. (1 = 1)
  10. """.trimIndent()
  11. em.createQuery(query, Int::class.java).resultList
  12. }

哪里

  1. /**Creates a new [EntityManager] using the [entityManagerFactory] and passes it to [action].
  2. * Wraps execution of [action] in a transaction and closes the [EntityManager] after execution
  3. * before the result is returned.*/
  4. private fun <Result> inNewTransaction(action: (EntityManager) -> Result): Result {
  5. with(entityManagerFactory.createEntityManager()) {
  6. transaction.begin()
  7. val result = action(this)
  8. transaction.commit()
  9. close()
  10. return result
  11. }
  12. }

以及 private val entityManagerFactory: EntityManagerFactory 是Spring注射的。
我希望这将生成与我在上面的psql中编写的相同类型的查询,只是参数化了。
相反,生成的是

  1. org.springframework.orm.jpa.JpaSystemException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.6.v20200131-b7c997804f):
  2. org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException:
  3. ERROR: missing FROM-clause entry for table "t3" Position: 78
  4. Error Code: 0 Call:
  5. SELECT DISTINCT t0.ID
  6. FROM
  7. a t0
  8. LEFT OUTER JOIN b t1 ON (t3.ID = t0.ID)
  9. LEFT OUTER JOIN c t2 ON (t2.sequence = t1.sequence),
  10. a t3
  11. WHERE ((? = ?) AND (t3.ID = t1.a_id))
  12. bind => [2 parameters bound]

所以

  1. LEFT JOIN B b ON b.a.id = a.id

不会转换为简单联接条件。相反,jpa将推另一个 a 进入 FROM 条款,与我们的 b 然后过滤掉所有与 a 我们最初想要的。
或者至少这是它似乎想做的,直到它在中途感到厌烦,坚持说它添加的from子句不见了。
表“t3”的子句条目中缺少
为什么会这样?
更重要的是,如何让这个查询工作?

aij0ehis

aij0ehis1#

jpa规范要求提供程序在为关系指定点“.”时使用内部联接。这将强制“left join b on b.a.id=a.id”中的“b.a.id”被解释为您已经定义并试图在此外部联接定义中使用的“a”之外的另一个来自b->a的内部联接。
你只想利用这段关系;请尝试“left join b on b.a=a”,或者为您可以在此处使用的a\u id外键定义一个基本Map。

相关问题