Oracleには と という2つのテーブルがproduct
ありますproduct_image
。名前が示すように、1 対多の関係がありますproduct
。product_image.
product
エンティティ:
@Entity
@Table(name = "PRODUCT", catalog = "", schema = "WAGAFASHIONDB")
public class Product implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "PROD_ID", nullable = false, precision = 35, scale = 0)
@SequenceGenerator(name = "productIdSequence", sequenceName = "PRODUCT_SEQ", allocationSize=1, initialValue=1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "productIdSequence")
private Long prodId;
@Column(name = "PROD_NAME", length = 50)
private String prodName;
@Column(name = "PROD_CODE", length = 50)
private String prodCode;
@Lob
@Column(name = "PROD_DESC")
private String prodDesc;
@Basic(optional = false)
@Column(name = "MARKET_PRICE", nullable = true, precision = 35, scale = 2)
private BigDecimal marketPrice;
@Basic(optional = false)
@Column(name = "SALE_PRICE", nullable = true, precision = 35, scale = 2)
private BigDecimal salePrice;
@Column(name = "PROD_FEATURED")
private Short prodFeatured;
@Column(name = "EXPRESS_DELIVERY")
private Short expressDelivery;
@Basic(optional = false)
@Column(name = "PROD_WEIGHT", nullable = true, precision = 35, scale = 2)
private BigDecimal prodWeight;
@Column(name = "PROD_OCCASSION", length = 50)
private String prodOccassion;
@Basic(optional = false)
@Column(name = "QTY_AVAILABLE", nullable = true)
private BigInteger qtyAvailable;
@Column(name = "LATEST")
private Short latest;
@Column(name = "VISIBLE")
private Short visible;
@JoinTable(name = "PRODUCT_SIZE", joinColumns = {
@JoinColumn(name = "PROD_ID", referencedColumnName = "PROD_ID")}, inverseJoinColumns = {
@JoinColumn(name = "SIZE_ID", referencedColumnName = "SIZE_ID")})
@ManyToMany(fetch = FetchType.LAZY)
private Set<SizeTable> sizeTableSet;
@ManyToMany(mappedBy = "productSet", fetch = FetchType.LAZY)
private Set<Colour> colourSet;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<Measurement> measurementSet;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<Wish> wishSet;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<Cart> cartSet;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<ProductImage> productImageSet; //<--------
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product", fetch = FetchType.LAZY)
private Set<OrderItem> orderItemSet;
@JoinColumn(name = "SUB_CAT_ID", referencedColumnName = "SUB_CAT_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Subcategory subCatId;
@JoinColumn(name = "FABRIC_ID", referencedColumnName = "FABRIC_ID", nullable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Fabric fabricId;
@JoinColumn(name = "BRAND_ID", referencedColumnName = "BRAND_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Brand brandId;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<Inquiry> inquirySet;
@OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<Rating> ratingSet;
}
ProductImage
エンティティ:
@Entity
@Table(name = "PRODUCT_IMAGE", catalog = "", schema = "WAGAFASHIONDB")
public class ProductImage implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "PROD_IMAGE_ID", nullable = false, precision = 35, scale = 0)
@SequenceGenerator(name = "productIdSequence", sequenceName = "PRODUCT_IMAGE_SEQ", allocationSize=1, initialValue=1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "productIdSequence")
private Long prodImageId;
@Lob
@Column(name = "PROD_IMAGE")
private String prodImage;
@JoinColumn(name = "PROD_ID", referencedColumnName = "PROD_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Product prodId; //<--------------
}
prodId
行の各グループ (実際には製品の各グループ)の最大の行のみをフェッチする必要がありますProductImage
。つまり、グループごとに最大の N です。
Oracle ネイティブ SQL は、次のように構築できます。
SELECT pi.prod_image_id, pi.prod_id, pi.prod_image
FROM product_image pi
INNER JOIN (select max(pi.prod_image_id) AS prod_image_id, pi.prod_id FROM product_image pi GROUP BY pi.prod_id) prod_image
ON pi.prod_image_id=prod_image.prod_image_id
これは意図したとおりに機能しますが、この SQL を HQL に変換できませんでした。createQuery()
メソッドで HQL として直接実行しようとするとQuerySyntexException
、最初の開き括弧で予期しないトークンが発生します。この SQL を HQL に変換するヒントを教えてください。
編集:
次のようないくつかの質問は、実際にはこれを達成するためにまだ答えられていません。
- グループごとのトップ n などの複雑なクエリに hibernate を使用する最良の方法
- 各グループから上位 n を取得する hql クエリ
- MySQL で HQL を使用して、正しいレコードが選択されるようにグループ化する前に結果セットを並べ替えるにはどうすればよいですか?
HQL を介して Hibernate でこれを達成する方法はないと思います。いくつかの DTO クラスを使用して、この SQL を適切な 2 つ以上の HQL ステートメントに分割する必要がある場合があります。上記の SQL のような単一の HQL ステートメントで可能であれば、ここでの回答を忘れないでください。アプリケーションの多くの場所でそのような要件があるためです。