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();