我在 MySQL 数据库中有三个表。
zone_table
zone_id (PK)
zone_name
transporter_id (FK references the transporter table - unrelated here).
weight
weight_id (PK)
weight
zone_charge
zone_id (FK refernces zone_table) |
weight_id (FK references weight) | composite primary key.
charge | extra column in join.
zone_table
由于和之间的多对多关系weight
由zone_charge
带有额外列(即)的表表示,因此创建了一个表示复合主键charge
的可嵌入类。ZoneChargePK
有了这种关系,我需要检索由三个字段组成的行列表,weight_id
并weight
从weight
表和charge
表zone_charge
中为给定的 zone检索。
本机SQL如下所示。
SELECT w.weight_id, w.weight, zc.charge
FROM weight w
LEFT OUTER JOIN zone_charge zc ON w.weight_id=zc.weight_id
WHERE zc.zone_id=?
ORDER BY w.weight ASC
对应的JPQL如下。
SELECT w.weightId, w.weight, zc.charge
FROM Weight w
LEFT JOIN w.zoneChargeSet zc
WITH zc.zone.zoneId=:id
ORDER BY w.weight
我希望通过 JPA 标准查询来表达同样的事情,因为这个查询又会动态生成。我留下了以下不完整的条件查询。
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple>criteriaQuery=criteriaBuilder.createTupleQuery();
Root<Weight> root = criteriaQuery.from(entityManager.getMetamodel().entity(Weight.class));
SetJoin<Weight, ZoneCharge> join = root.join(Weight_.zoneChargeSet, JoinType.LEFT);
criteriaQuery.multiselect(root.get(Weight_.weightId), root.get(Weight_.weight), join.get(ZoneCharge_.zoneTable));
TypedQuery<Tuple> typedQuery = entityManager.createQuery(criteriaQuery);
List<Tuple> tuples = typedQuery.getResultList();
但这会导致和之间的内连接以及zone_table
和之间的zone_charge
左连接。生成的 SQL 查询如下所示。zone_charge
weight
select
weight0_.weight_id as col_0_0_,
weight0_.weight as col_1_0_,
zonecharge1_.zone_id as col_2_0_,
zonetable2_.zone_id as zone1_34_,
zonetable2_.transporter_id as transpor3_34_,
zonetable2_.zone_name as zone2_34_
from
social_networking.weight weight0_
left outer join
social_networking.zone_charge zonecharge1_
on weight0_.weight_id=zonecharge1_.weight_id
inner join
social_networking.zone_table zonetable2_
on zonecharge1_.zone_id=zonetable2_.zone_id
其实应该是
select
weight0_.weight_id as col_0_0_,
weight0_.weight as col_1_0_,
zonecharge1_.charge as col_2_0_
from
social_networking.weight weight0_
left outer join
social_networking.zone_charge zonecharge1_
on weight0_.weight_id=zonecharge1_.weight_id
除了where
和order by
。那么实际的条件查询会是什么样子呢?
编辑 :
ZoneTable
实体(仅在需要时):
@Entity
@Table(name = "zone_table", catalog = "social_networking", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"zone_id"})})
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "ZoneTable.findAll", query = "SELECT z FROM ZoneTable z"),
@NamedQuery(name = "ZoneTable.findByZoneId", query = "SELECT z FROM ZoneTable z WHERE z.zoneId = :zoneId"),
@NamedQuery(name = "ZoneTable.findByZoneName", query = "SELECT z FROM ZoneTable z WHERE z.zoneName = :zoneName")})
public class ZoneTable implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "zone_id", nullable = false)
private Long zoneId;
@Column(name = "zone_name", length = 45)
private String zoneName;
@JoinColumn(name = "transporter_id", referencedColumnName = "transporter_id")
@ManyToOne(fetch = FetchType.LAZY)
private Transporter transporterId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "zoneTable", fetch = FetchType.LAZY)
private Set<ZoneCharge> zoneChargeSet; //<--------------------------
@OneToMany(mappedBy = "zoneId", fetch = FetchType.LAZY)
private Set<Country> countrySet;
}
Weight
实体:
@Entity
@Table(name = "weight", catalog = "social_networking", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"weight_id"})})
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Weight.findAll", query = "SELECT w FROM Weight w"),
@NamedQuery(name = "Weight.findByWeightId", query = "SELECT w FROM Weight w WHERE w.weightId = :weightId"),
@NamedQuery(name = "Weight.findByWeight", query = "SELECT w FROM Weight w WHERE w.weight = :weight")})
public class Weight implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "weight_id", nullable = false)
private Long weightId;
@Column(name = "weight", precision = 35, scale = 2)
private BigDecimal weight;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "weight", fetch = FetchType.LAZY)
private Set<ZoneCharge> zoneChargeSet; //<-------------------------
}
ZoneCharge
实体:
@Entity
@Table(name = "zone_charge", catalog = "social_networking", schema = "")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "ZoneCharge.findAll", query = "SELECT z FROM ZoneCharge z"),
@NamedQuery(name = "ZoneCharge.findByZoneId", query = "SELECT z FROM ZoneCharge z WHERE z.zoneChargePK.zoneId = :zoneId"),
@NamedQuery(name = "ZoneCharge.findByWeightId", query = "SELECT z FROM ZoneCharge z WHERE z.zoneChargePK.weightId = :weightId"),
@NamedQuery(name = "ZoneCharge.findByCharge", query = "SELECT z FROM ZoneCharge z WHERE z.charge = :charge")})
public class ZoneCharge implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected ZoneChargePK zoneChargePK;
@Column(name = "charge", precision = 35, scale = 2)
private BigDecimal charge;
@JoinColumn(name = "zone_id", referencedColumnName = "zone_id", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private ZoneTable zoneTable;
@JoinColumn(name = "weight_id", referencedColumnName = "weight_id", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Weight weight;
ZoneChargePK
实体:
@Embeddable
public class ZoneChargePK implements Serializable {
@Basic(optional = false)
@Column(name = "zone_id", nullable = false)
private long zoneId;
@Basic(optional = false)
@Column(name = "weight_id", nullable = false)
private long weightId;
}
根据这种关系,如上所示的 JPQL 查询可以正常工作。
这不是一个社交网络项目。这只是最初的打算。故而得名。这是关于一个购物网站。