[英]HQL or SQL query to get data from many to many related entities
I am using spring with hibernate to store data in MySql database. 我正在使用spring和hibernate将数据存储在MySql数据库中。 I am trying to retrieve rows based on filters requested by the user.
我正在尝试根据用户请求的过滤器检索行。 I have the following tables/entities : Product and Gemstone
我有以下表格/实体:产品和宝石
I am trying to write a query to get products that have Gemstone A and Gemstone B and Gemstone C.. and so on. 我正在尝试编写查询以获取具有宝石A,宝石B和宝石C ..等的产品。
If user is asking for a product with gemstones 51 and 46. Query should only return product id 4. 如果用户要求使用宝石51和46的产品。查询应仅返回产品ID 4。
filterGemstones() method return the gemstone user wants to filter products to. filterGemstones()方法返回用户要将产品过滤到的宝石。 Using the below query I get zero records but if I remove
HAVING Count(DISTINCT p.product_id) = 2
I get product id 4, 5 使用以下查询,我得到零记录,但是如果我删除
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 generate by hibernate : 由休眠生成的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 }
Actually the SQL query that we need here is pretty simple: 实际上,我们这里需要的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
It's a bit frustrating that it's not easy to create it with JPA, but it can be done with FluentJPA (produces the query above): 使用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();
}
More details on how it works can be found here . 有关其工作原理的更多详细信息,请参见此处 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.