1

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_chargechargeZoneChargePK

この関係を使用して、3 つのフィールドで構成される行のリストを、テーブルから、weight_idおよび特定のゾーンのテーブルから取得する必要があります。weightweightchargezone_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_chargezone_chargeweight

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

と を除いwhereorder 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 クエリは正しく機能します。

これはソーシャル ネットワーキング プロジェクトではありません。それはもともと意図されていたものです。したがって、それはそのように命名されました。ショッピングサイトについてです。

4

0 に答える 0