我正在使用spring和hibernate将数据存储在MySql数据库中。我正在尝试根据用户请求的过滤器检索行。 我有以下表格/实体:产品和宝石
关系:我正在尝试编写查询,以获取具有宝石A和宝石B以及宝石C ..等的产品。
用例:如果用户要求使用宝石51和46的产品。查询应仅返回产品ID4。
查询: filterGemstones()方法返回用户要将产品过滤到的宝石。使用以下查询,我得到零记录,但是如果我删除HAVING Count(DISTINCT p.product_id) = 2
,我得到的产品ID是4、5
HQL:
createQuery("select p.productId from Product p JOIN p.gemstones g where g in :gemstones group by p having count (distinct p) =" + filterGemstones().size() ).setParameter("gemstones",filterGemstones());
由休眠生成的SQL:
SELECT p.product_id
FROM product p
INNER JOIN gemstone_product gp
ON p.product_id = gp.product_id
INNER JOIN gemstone g
ON gp.gemstone_id = g.gemstone_id
WHERE g.gemstone_id IN ( 51, 46 )
GROUP BY p.product_id
HAVING Count(DISTINCT p.product_id) = 2
@Entity
@Table(name = "product")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "product_id")
private long productId;
@ManyToMany()
@JoinTable(
name = "gemstone_product",
joinColumns = {@JoinColumn(name = "product_id")},
inverseJoinColumns = {@JoinColumn(name = "gemstone_id")}
)
private Set<Gemstone> gemstones = new HashSet<>(0);
// setters and getters
}
@Entity
@Table(name = "gemstone")
public class Gemstone {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "gemstone_id")
private long gemstoneId;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "gemstone_product",
joinColumns = {@JoinColumn(name = "gemstone_id")},
inverseJoinColumns = {@JoinColumn(name = "product_id")}
)
private Set<Product> products = new HashSet<>(0);
// setters and getters
}
答案 0 :(得分:0)
实际上,我们在这里需要的SQL查询非常简单:
SELECT t1.product_id
FROM gemstone_product AS t1
WHERE (t1.gemstone_id IN ?1 ) # (51, 46)
GROUP BY t1.product_id
HAVING (COUNT(t1.gemstone_id) = ?2) # 2 - # of items
使用JPA创建它并不容易,但可以使用FluentJPA(产生上面的查询)来完成,这有点令人沮丧:
public List<Integer> getProductsContainingAllStones(List<Long> gemstoneIds) {
int count = gemstoneIds.size();
FluentQuery query = FluentJPA.SQL((Gemstone gemstone,
JoinTable<Gemstone, Product> gemstoneProduct) -> {
discardSQL(gemstoneProduct.joinBy(gemstone.getProducts()));
long productId = gemstoneProduct.getInverseJoined().getProductId();
long gemstoneId = gemstoneProduct.getJoined().getGemstoneId();
SELECT(productId);
FROM(gemstoneProduct);
WHERE(gemstoneIds.contains(gemstoneId));
GROUP(BY(productId));
HAVING(COUNT(gemstoneId) == count);
});
return query.createQuery(em).getResultList();
}
有关其工作原理的更多详细信息,请参见here。