【问题标题】:Incorrect JPQL query formed when joining tables连接表时形成不正确的 JPQL 查询
【发布时间】:2019-01-23 18:35:14
【问题描述】:

假设我有 2 个实体:ApplicationOrganization。它们是多对多相关的

组织:

@Entity
@Table(name = "organizations")
public class Organization
{

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "organizationIdGenerator")
    private long id;  // primary key

    @AttributeOverride(name = "id", column = @Column(name = "organization_id", unique = true, updatable = false))
    @Embedded
    private OrganizationId organizationId;

    @AttributeOverride(name = "id", column = @Column(name = "application_id"))
    @CollectionTable(name = "organization_applications")
    @ElementCollection
    private Set<ApplicationId> applications = new HashSet<>();  // there is no explicit @Many-to-many connection between applications and organizations

    private String name;

    // other data
}

应用:

@Entity
@Table(name = "applications")
public class Application
{

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "applicationIdGenerator")
    private long id; // primary key

    @AttributeOverride(name = "id", column = @Column(name = "application_id", unique = true, updatable = false))
    @Embedded
    private ApplicationId applicationId;

    private String label;

    // other data 
}

由于它们是多对多相关的,因此在关系数据库中我有以下表格:

  • organizations
  • applications
  • organization_applications

organization_applications 是使用以下 liquibase-migration 创建的:

<createTable tableName="organization_applications">
  <column name="organization_id" type="bigint">
    <constraints nullable="false" foreignKeyName="organization_application_organization_id_fk"
                 referencedTableName="organizations" referencedColumnNames="id"/>
  </column>
  <column name="application_id" type="varchar(50)">
    <constraints nullable="false"/>
  </column>
</createTable>

我想做的是在一个查询中为特定组织获取应用程序 (List&lt;Application&gt;)


我可以通过获取特定组织的 applicationIds 来做到这一点(比如说,organizationId = 1)并将它们与applications 一起使用如下查询:

select apps.application_id, apps.label 
    from organization_applications org_apps
    join applications apps 
        on (apps.application_id = org_apps.application_id and org_apps.organization_id = 1)

但是当我尝试使用这样的 JPQL 查询来完成此操作时:

SELECT new List(o.applications) FROM Organization o WHERE o.organizationId.id = 1

我收到以下查询,然后出现异常:

Hibernate: 
    /* SELECT
        new List(o.applications) 
    FROM
        Organization o 
    WHERE
        o.organizationId.id = :org_id */ select
            . as col_0_0_          // <-- problem here. why is there just a dot?
        from
            organizations organizati0_ 
        inner join
            organization_applications applicatio1_ 
                on organizati0_.id=applicatio1_.organization_id 
        where
            organizati0_.organization_id=?

SqlExceptionHelper   : SQL Error: 20000, SQLState: 42X01
SqlExceptionHelper   : Syntax error: Encountered "." at line 1, column 102.

似乎在这样的关系中,实体通过自定义 id 字段(applicationId、organiationId)相关联,hibernate 无法创建查询。

知道我该怎么做吗?

提前致谢!


更新:

ApplicationId 包含一些验证,如下所示:

public class ApplicationId
{
    private String id;

    // constructor and getters
}

OrganizationId看起来一模一样

【问题讨论】:

  • 您尚未在引用的 2 个实体之间定义实际的关系。您只需拥有一组未定义的嵌入对象。这不是 M-N 关系
  • 而且新的列表在查询中是不可能的。你想达到什么目的?
  • @BillyFrost 我添加了一个迁移,它创建了一个定义它们的关系的表,并且由于organization 不是该关系的所有者,因此没有明确定义的关系(通过@ManyToMany)跨度>
  • @SimonMartinelli,我正在尝试获取 属于特定组织的应用程序列表。由于 JPQL 需要一个将由结果值填充的 DTO,并且由于我试图获取应用程序列表,我应该使用什么类型?此外,如果我需要一个与One-to-Many 相关的属性(例如,组织的电话号码),select new List(...) 也很适合。看看this answer
  • 试试 SELECT o.applications FROM Organization o WHERE o.organizationId.id = 1 看看你会在结果列表中找到什么类型。

标签: java hibernate jpa hql jpql


【解决方案1】:
@Query("SELECT a FROM Application a WHERE a.applicationId IN " +
        "(SELECT apps FROM Organization o JOIN o.applications apps WHERE o.organizationId = :organization_id) ORDER BY label ASC")

【讨论】:

    【解决方案2】:

    您可以像这样选择 ApplicationId:

    SELECT a FROM Organization o JOIN o.applications a WHERE o.organizationId.id = 1
    

    【讨论】:

    • 看起来这个查询返回ApplicationIds 的列表(而不是Applications)当我这样执行它时:Query q = this.entityManager.createQuery("SELECT a FROM Organization o JOIN o.applications a WHERE o.organizationId.id = :org_id"); q.setParameter("org_id", "1"); List resultList = (List&lt;Object&gt;) q.getResultList(); 实际连接没有发生,我想知道为什么因为休眠产生查询加入:... inner join organization_applications applicatio1_ on organizati0_.id=applicatio1_.organization_id ...
    • 我很困惑。你想要什么作为返回类型?
    • 我想获取应用程序列表 (List&lt;Application&gt;)。因为获取ApplicationIds 的列表需要额外的查询(通过ApplicationIds 获取Applications)。所以我必须以某种方式加入表applications。我正在努力为此创建一个 JPQL 查询。对不起,如果我的解释让你感到困惑:)
    猜你喜欢
    • 1970-01-01
    • 2018-07-06
    • 2014-02-21
    • 1970-01-01
    • 2020-03-26
    • 2019-01-26
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多