JPQL 从一对一关系查询到 select 实体,其中它的相关字段具有匹配特定条件的字段
JPQL Query to select entity from one-to-one relationship where it's relative has a field matching a certain condition
我有三个实体:EntityA
映射到 table_a
,EntityB
映射到 table_b
,Catalog
映射到 catalog
。在数据库中,table_b
和catalog
、b_catalog_xref
之间存在多对多table。 EntityB
有一个字段:Long aId
和一个字段:List<Catalog> catalogs
。 Catalog 实体有一个字段:String name
。给定 EntityB 的 ID 列表和表示目录名称的字符串,我需要检索所有出现的 EntityA,其 ID 与 EntityB 的 aId
匹配,并且给定的目录名称与 EntityB 的目录之一匹配.
我已经通过常规 SQL 成功获取了正确的数据,但我很难在 JPQL 中重新创建查询。这是 SQL 查询:
SQL:
SELECT
*
FROM
table_a a
WHERE
a.table_a_id in (
SELECT
b.table_a_id
FROM
table_b b
INNER JOIN b_catalog_xref bcx ON bcx.table_b_id = b.table_b_id
INNER JOIN catalog c ON c.catalog_id = bcx.catalog_id
WHERE
c.catalog_name = 'Example Catalog Name'
);
Java:
@Entity
@Table(name = "table_a")
public class EntityA {
@Id
@Column(name = "table_a_id")
private Long aId;
...
}
@Entity
@Table(name = "table_b")
public class EntityA {
@Id
@Column(name = "table_b_id")
private Long bId;
@Column(name = "table_a_id")
private Long aId;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.DETACH})
@JoinTable(name = "b_catalog_xref",
joinColumns = {@JoinColumn(name = "table_b_id")},
inverseJoinColumns = {@JoinColumn(name = "catalog_id")})
@Fetch(FetchMode.SELECT)
@OrderBy("name ASC")
List<Catalog> catalogs
...
}
@Entity
@Table(name = "catalog")
public class Catalog {
@Id
@Column(name = "catalog_id")
private Long catalogId;
@Column(name = "catalog_name")
private String name;
...
}
是的,你可以使用类似
的东西
TypedQuery<TableA> q = entityManager.createQuery
("Select a from TableA a where a.aId in(Select b.aId from TableB b " +
"join b.catalogs c where c.name=:name)", TableA.class);
q.setParameter("name", "some2");
我建议您考虑在 table 的 A 和 B 之间创建关系,而不是将 table A 的密钥复制到 table B
@Entity
@Table(name = "table_b")
public class EntityB {
...
// @Column(name = "table_a_id")
// private Long aId;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "table_a_id")
private TableA tableA;
...
}
那么 JPQL 将如下所示:
TypedQuery<TableA> q = entityManager.createQuery
("Select distinct b.tableA from TableB b join b.catalogs c " +
"where c.name=:name", TableA.class);
q.setParameter("name", "some2");
注意关键字distinct,它会删除结果列表中的所有重复项。
除非绝对必要,否则不要使用 FetchType.EAGER
,请使用 FetchType.LAZY
。
我有三个实体:EntityA
映射到 table_a
,EntityB
映射到 table_b
,Catalog
映射到 catalog
。在数据库中,table_b
和catalog
、b_catalog_xref
之间存在多对多table。 EntityB
有一个字段:Long aId
和一个字段:List<Catalog> catalogs
。 Catalog 实体有一个字段:String name
。给定 EntityB 的 ID 列表和表示目录名称的字符串,我需要检索所有出现的 EntityA,其 ID 与 EntityB 的 aId
匹配,并且给定的目录名称与 EntityB 的目录之一匹配.
我已经通过常规 SQL 成功获取了正确的数据,但我很难在 JPQL 中重新创建查询。这是 SQL 查询:
SQL:
SELECT
*
FROM
table_a a
WHERE
a.table_a_id in (
SELECT
b.table_a_id
FROM
table_b b
INNER JOIN b_catalog_xref bcx ON bcx.table_b_id = b.table_b_id
INNER JOIN catalog c ON c.catalog_id = bcx.catalog_id
WHERE
c.catalog_name = 'Example Catalog Name'
);
Java:
@Entity
@Table(name = "table_a")
public class EntityA {
@Id
@Column(name = "table_a_id")
private Long aId;
...
}
@Entity
@Table(name = "table_b")
public class EntityA {
@Id
@Column(name = "table_b_id")
private Long bId;
@Column(name = "table_a_id")
private Long aId;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.DETACH})
@JoinTable(name = "b_catalog_xref",
joinColumns = {@JoinColumn(name = "table_b_id")},
inverseJoinColumns = {@JoinColumn(name = "catalog_id")})
@Fetch(FetchMode.SELECT)
@OrderBy("name ASC")
List<Catalog> catalogs
...
}
@Entity
@Table(name = "catalog")
public class Catalog {
@Id
@Column(name = "catalog_id")
private Long catalogId;
@Column(name = "catalog_name")
private String name;
...
}
是的,你可以使用类似
的东西TypedQuery<TableA> q = entityManager.createQuery
("Select a from TableA a where a.aId in(Select b.aId from TableB b " +
"join b.catalogs c where c.name=:name)", TableA.class);
q.setParameter("name", "some2");
我建议您考虑在 table 的 A 和 B 之间创建关系,而不是将 table A 的密钥复制到 table B
@Entity
@Table(name = "table_b")
public class EntityB {
...
// @Column(name = "table_a_id")
// private Long aId;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "table_a_id")
private TableA tableA;
...
}
那么 JPQL 将如下所示:
TypedQuery<TableA> q = entityManager.createQuery
("Select distinct b.tableA from TableB b join b.catalogs c " +
"where c.name=:name", TableA.class);
q.setParameter("name", "some2");
注意关键字distinct,它会删除结果列表中的所有重复项。
除非绝对必要,否则不要使用 FetchType.EAGER
,请使用 FetchType.LAZY
。