SpringData jpa一对多集合属性过滤

Spring data jpa @OneToMany 在一的一端进行查询对集合属性设置条件查询

转自https://my.oschina.net/daidaitianhe/blog/519750

业务场景: 一个商品对应多个仓存,需要查询商品在某个或某几个库存中存在时,查询出来.

实体类 ,商品Goods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entity
@Table(name = "es_goods")
public class Goods {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "goods_id")
private Integer id;

private String name;

//仓库集合
@OneToMany(mappedBy = "goods", cascade = CascadeType.ALL)
private List<ProductStore> productStores;
}

实体类,仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Entity
@Table(name = "es_product_store")
public class ProductStore {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;

//商品
@ManyToOne
@JoinColumn(name="goods_id")
private Goods goods;

//仓库名,理论上应该使用一个关联,此处为了简便就只用的一个String
private String name;
}

当使用spring data jpa 的@query简单查询时,需要在HQL 中使用 join

Repository中的方法

1
2
3
// @Query("select  g from Goods g  where g.productStores.name = ?1 ") 错误写法,启动报错
@Query("select DISTINCT g from Goods g left join g.productStores as p where p.name = ?1")//正确
public List<Goods> findGoodsByProductStoreName(String name);

以上是固定查询时的用法,很多时候我们使用了Spring data jpa 的动态查询 即Specification类,此时的业务代码如下

1
2
3
4
5
6
7
8
9
10
new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
//话说这方法找了好久好久...如果用寻常path,亦会抛异常
Join join = root.join(root.getModel().getList("productStores", ProductStore.class),JoinType.LEFT);

return builder.equeal(join.get("id"),<仓库id>)

}
};