给定实体:
@Entity
@Data
public class Collection {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String createdBy;
@OneToMany(mappedBy = "collection")
private List<CollectionAccess> collectionAccesses;
}
@Entity
@Data
public class CollectionAccess {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(
foreignKey =
@ForeignKey(
value = ConstraintMode.PROVIDER_DEFAULT,
name = "fk_collectionaccess_collection_collections_id"))
private Collection collection;
private Integer accessType;
private LocalDateTime expirationAtUtc;
}
给定数据库:
select id, created_by from collection;
+----+------------+
| id | created_by |
+----+------------+
| 40 | ABC123 |
+----+------------+
select * from collection_access;
+----+-------------+----------------------------+---------------+
| id | access_type | expiration_at_utc | collection_id |
+----+-------------+----------------------------+---------------+
| 2 | 0 | 2011-12-03 03:15:30.000000 | 40 |
| 3 | 1 | 2011-12-03 03:15:30.000000 | 40 |
+----+-------------+----------------------------+---------------+
编写此查询会导致 SemanticException:
em.createQuery(
"SELECT t FROM (SELECT c FROM Collection c "
+ "LEFT JOIN c.collectionAccesses ca WHERE c.id = ?1 "
+ "AND (c.createdBy = ?2 OR (ca.accessType = ?3 AND ca.expirationAtUtc <= ?4))) t "
+ "JOIN FETCH t.collectionAccesses ",
Collection.class)
.setParameter(1, id)
.setParameter(2, "ABC123")
.setParameter(3, 1)
.setParameter(4, now)
getSingleResult();
java.lang.IllegalArgumentException: org.hibernate.query.SemanticException: Select item at position 1 in select list has no alias (aliases are required in CTEs and in subqueries occurring in from clause)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:143) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final]
如何在 JPQL/Hibernate 中正确编写
SELECT
查询 FROM
a subselect
?
JPQL 中的 FROM 子句中不能使用子查询。您有 2 个选择:
使用本机查询
尝试重写查询以替换 FROM 子句中的子查询 但是,在分析您的查询后,我不太明白为什么您需要该子选择。 我认为这样做就可以了:
em.createQuery( “从集合 c 中选择 c” +“JOIN FETCH c.collectionAccesses ca WHERE c.id = ?1” + "AND (c.createdBy = ?2 OR (ca.accessType = ?3 AND ca.expirationAtUtc <= ?4)), Collection.class) .setParameter(1, id) .setParameter(2, "ABC123") .setParameter(3, 1) .setParameter(4, now) getSingleResult();
如果我的建议没有达到您的目标,如果您解释一下您需要什么结果,将会有所帮助。