Spring 标准Api泛型太多连接
实体:Spring 标准Api泛型太多连接,spring,hibernate,criteria-api,Spring,Hibernate,Criteria Api,实体: @Entity @Table(name = "shop") public class Shop implements Serializable{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String address;
@Entity
@Table(name = "shop")
public class Shop implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
@OneToMany(mappedBy = "shop")
private List<Product> product = new ArrayList<>();
public Shop() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
@Entity
@Table(name = "product")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "disc_col")
public class Product implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private BigDecimal price;
@ManyToOne
private Shop shop;
public Product() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Shop getShop() {
return shop;
}
public void setShop(Shop shop) {
this.shop = shop;
}
}
@Entity
@DiscriminatorValue("loose")
public class LooseProduct extends Product {
private BigDecimal weight;
public LooseProduct() {
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
this.weight = weight;
}
}
@Entity
@DiscriminatorValue("liquid")
public class LiquidProduct extends Product {
private BigDecimal volume;
public LiquidProduct() {
}
public BigDecimal getVolume() {
return volume;
}
public void setVolume(BigDecimal volume) {
this.volume = volume;
}
}
它是InheritanceType.SINGLE_TABLE
策略,所以它不应该创建三个联接,因为数据库中只有一个表产品。有没有办法优化这个
来自org.hibernate.query.criteria.internal.CriteriaBuilderImpl类的代码:
@SuppressWarnings("unchecked")
private <X, T, V extends T, K extends JoinImplementor> K treat(
Join<X, T> join,
Class<V> type,
BiFunction<Join<X, T>, Class<V>, K> f) {
final Set<Join<X, ?>> joins = join.getParent().getJoins();
final K treatAs = f.apply( join, type );
joins.add( treatAs );
return treatAs;
}
@SuppressWarnings(“未选中”)
私人请客(
加入,,
类类型,
双函数(f){
final Set joins=join.getParent().getJoins();
最终K处理=f.应用(连接,类型);
添加(treatAs);
退货处理;
}
treat方法从现有连接创建新连接。它每次都发生,与继承类型无关。
下一步,hibernate生成查询,不检查联接中的重复项。
当我们使用treat方法时,您知道如何防止生成额外的连接吗
我找到了错误报告:
如果使用JPA 2.1以后的版本,您可以如下更改查询:
select shop0_.id as id1_1, shop0_.address as address2_1, shop0_.name as name3_1
from shop shop0
left join product product1 on shop0_.id=product1_.shop_id
and (
(product1.disc_col = 'loose' and product1.weight = weight_var)
or (product1.disc_col = 'liquid' and product1.volume = volume_var)
);
对于实现,您需要添加disc_col列到产品实体的映射
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Shop> cq = cb.createQuery(Shop.class);
Root<Shop> root = cq.from(Shop.class);
Join<Shop, Product> product = root.join("product", JoinType.LEFT);
//add other conditions
product.on(
cb.and(
cb.or(
cb.and(cb.equal(product.get("discCol"),"liquid"),cb.equal(product.get("volume"),volumeVar)),
cb.and(cb.equal(product.get("discCol"),"loose"),cb.equal(product.get("weight"),weightVar))
)
)
);
Query q = em.createQuery(cq);
return q.getResultList();
CriteriaBuilder cb=entityManager.getCriteriaBuilder();
CriteriaQuery cq=cb.createQuery(Shop.class);
Root=cq.from(Shop.class);
Join product=root.Join(“product”,JoinType.LEFT);
//添加其他条件
产品介绍(
cb.和(
cb.or(
cb.和(cb.equal(产品获取(“discCol”),“液体”)、cb.equal(产品获取(“体积”)、volumeVar)),
cb.和(cb.相等(product.get(“discCol”),“loose”)、cb.相等(product.get(“weight”)、weightVar))
)
)
);
查询q=em.createQuery(cq);
返回q.getResultList();
请包含您的查询代码我的问题第一部分末尾有findShops方法。
select shop0_.id as id1_1, shop0_.address as address2_1, shop0_.name as name3_1
from shop shop0
left join product product1 on shop0_.id=product1_.shop_id
and (
(product1.disc_col = 'loose' and product1.weight = weight_var)
or (product1.disc_col = 'liquid' and product1.volume = volume_var)
);
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Shop> cq = cb.createQuery(Shop.class);
Root<Shop> root = cq.from(Shop.class);
Join<Shop, Product> product = root.join("product", JoinType.LEFT);
//add other conditions
product.on(
cb.and(
cb.or(
cb.and(cb.equal(product.get("discCol"),"liquid"),cb.equal(product.get("volume"),volumeVar)),
cb.and(cb.equal(product.get("discCol"),"loose"),cb.equal(product.get("weight"),weightVar))
)
)
);
Query q = em.createQuery(cq);
return q.getResultList();