JPQL对同一个表的多个JOIN查询

时间:2016-10-20 23:30:46

标签: java jpa inner-join jpql

在给定一组传递到RESTful端点的参数的情况下,我的Java代码正在构建以下JPQL(动态):

SELECT i FROM Item i JOIN FETCH i.itemCharacterizations ic2 WHERE 1 = 1 AND ic2.type = 2 AND ic2.intValue = 0 AND LOWER(i.externalId) LIKE :itemName

这导致以下错误:

<openjpa-2.2.0-r422266:1244990 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: "Encountered "ic2" at character 57, but expected: [",", ".", "GROUP", "HAVING", "INNER", "JOIN", "LEFT", "ORDER", "WHERE", <EOF>]." while parsing JPQL "SELECT i FROM Item i JOIN FETCH i.itemCharacterizations ic2 WHERE 1 = 1 AND ic2.type = 2 AND ic2.intValue = 0 AND LOWER(i.externalId) LIKE :itemName". See nested stack trace for original parse error.

这是我的Java代码:

    .
    .
    .
    .
    List<Item> items = null;
    // Query base string - WHERE 1 = 1 used strictly for convenience purposes.
    StringBuilder queryBuffer = new StringBuilder();
    if (itemGradeLevelId == -1 && itemContentAreaId == -1) {
        queryBuffer.append("SELECT i FROM Item i WHERE 1 = 1");
    }
    else {
        queryBuffer.append("SELECT i FROM Item i");
        if (itemGradeLevelId > -1) {
            queryBuffer.append(" JOIN FETCH i.itemCharacterizations ic1");
        }
        if (itemContentAreaId > -1) {
            queryBuffer.append(" JOIN FETCH i.itemCharacterizations ic2");
        }
        queryBuffer.append(" WHERE 1 = 1");
        if (itemGradeLevelId > -1) {
            queryBuffer.append(" AND ic1.type = " + ItemCharacterizationTypeConstants.GRADE_LEVEL +
                               " AND ic1.intValue = " + itemGradeLevelId);
        }
        if (itemContentAreaId > -1) {
            queryBuffer.append(" AND ic2.type = " + ItemCharacterizationTypeConstants.CONTENT_AREA +
                               " AND ic2.intValue = " + itemContentAreaId);
        }
    }
    .
    .
    .
    .
    TypedQuery<Item> itemQuery = this.entityManager.createQuery(queryBuffer.toString(), Item.class);
    items = itemQuery.getResultList();
    return items;
}

我不确定我想要实现的目标是什么样的正确语法(即):

根据我的项目实体中定义的以下关系选择项目实体:

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "i_id")
private List<ItemCharacterization> itemCharacterizations;

以下ItemCharacterization Entity字段:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private long id;

@Basic
@Column(name="i_id")
private long itemId;

@Basic
@Column(name="ic_type")
private int type;

@Basic
@Column(name="ic_value")
private int intValue;

@Basic
@Column(name="ic_value_str")
private String strValue;

1 个答案:

答案 0 :(得分:0)

这个问题似乎得到了回答。但只是说明导致问题的原因。

在查询中

SELECT i FROM Item i JOIN FETCH i.itemCharacterizations ic2 WHERE 1 = 1 AND ic2.type = 2 AND ic2.intValue = 0 AND LOWER(i.externalId) LIKE :itemName

使用了关联的标识变量(ic2),JPA specification section 4.4.5.3中不允许使用该标识变量:

  

FETCH JOIN子句右侧引用的关联必须是从实体引用的关联或元素集合,或者作为查询结果返回的可嵌入对象。

     

不允许为FETCH JOIN子句右侧引用的对象指定标识变量,并且因此对隐式获取的实体或元素的引用不能出现在查询的其他位置

由于查询的目的不是fetch join两个实体,而是将它们连接在一起,因此必须从查询中删除FETCH关键字,如下所示:

SELECT i FROM Item i JOIN i.itemCharacterizations ic2 WHERE 1 = 1 AND ic2.type = 2 AND ic2.intValue = 0 AND LOWER(i.externalId) LIKE :itemName

应返回Item s及其关联的ItemCharacterization个实例的集合。