MySQL データベースに 3 つのテーブルがあります。
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
この関係を使用して、3 つのフィールドで構成される行のリストを、テーブルから、weight_id
および特定のゾーンのテーブルから取得する必要があります。weight
weight
charge
zone_charge
ネイティブ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
との間の内部結合が発生します。生成された SQL クエリは次のようになります。zone_charge
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 クエリは正しく機能します。
これはソーシャル ネットワーキング プロジェクトではありません。それはもともと意図されていたものです。したがって、それはそのように命名されました。ショッピングサイトについてです。