1

我在 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由于和之间的多对多关系weightzone_charge带有额外列(即)的表表示,因此创建了一个表示复合主键charge的可嵌入类。ZoneChargePK

有了这种关系,我需要检索由三个字段组成的行列表,weight_idweightweight表和chargezone_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_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