首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring数据JPA如何在使用get("property")链和Join时指定连接类型或获取模式

Spring数据JPA如何在使用get("property")链和Join时指定连接类型或获取模式
EN

Stack Overflow用户
提问于 2021-09-24 23:44:54
回答 1查看 326关注 0票数 1

我有两个(基于Hibernate的) Spring域类,一个是Customer.class:

代码语言:javascript
复制
@Entity
@Table(name = "sys_customer")
@Data
public class Customer implements Serializable {
    @Id
    @Column(name = "cust_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "cust_name")
    private String customerName;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "customer")
    private Set<Order> orders;

}

还有“多”边Order.class:

代码语言:javascript
复制
@Entity
@Table(name = "sys_order")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {

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

    @Column(name = "order_name")
    private String orderName;

    @ManyToOne
    @JoinColumn(name = "order_cust_id", referencedColumnName = "cust_id")
    private Customer customer;

    public Order( String orderName) {
        this.orderName = orderName;
    }

    public Order(String orderName, Customer customer) {
        this.orderName = orderName;
        this.customer = customer;
    }
}

我有OrderRepository接口,它扩展了JpaRepository接口和JpaSpecificationExecutor接口:

代码语言:javascript
复制
public interface OrderRepository extends JpaRepository<Order, Long>, JpaSpecificationExecutor<Order> {
}

我有一个带有静态方法OrderSpecification.class的searchByCustomerName

代码语言:javascript
复制
public class OrderSpecification {
    public static Specification<Order> searchByCustomerName(String customerName) {
        return new Specification<Order>() {
            @Override
            public Predicate toPredicate(Root<Order> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Join<Order, Customer> join = root.join("customer");
                return criteriaBuilder.like(join.get("customerName"), "%" + customerName + "%");
                //return criteriaBuilder.like(root.get("customer").get("customerName"), "%" + customerName + "%");
            }
        };
    }
} 

为了找出get("property")链和Join之间的区别,我编写了一个简单的测试方法,并注释掉了上面的OrderSpecificatin.class代码。

代码语言:javascript
复制
    @Test
    @Transactional
    public void testFindOrderByCustomerName(){
        String name = "adam";
        List<Order> orders = orderRepository.findAll(OrderSpecification.searchByCustomerName(name));
        for(Order order: orders){
            Customer customer = order.getCustomer();
            log.info(new StringBuilder().append(customer.getId()).append(" ").append(customer.getCustomerName()).toString());

        }
    }

我发现: get("property")链使用交叉连接(这是非常糟糕的性能),而联接使用内部连接(因为默认情况下ManyToOne()是Fetch= FetchType.EAGER)。

/* get("property")链: Hibernate:选择order0_.order_id作为order_id1_1_,order0_.order_cust_id选择order_cu3_1_,order0_.order_name作为order_na2_1_从sys_order order0_ 交叉加入 sys_customer customer1_,其中order0_.order_cust_id=customer1_.cust_id和(customer1_.cust_name like ?)Hibernate:选择customer0_.cust_id作为cust_id1___,选择customer0_.cust_name作为cust_nam2___,从sys_customer customer0_选择customer0_.cust_id=?*/

/** *“联接”:* Hibernate:选择order0_.order_id作为order_id1_1_,order0_.order_cust_id作为order_cu3_1_,order0_.order_name作为order_na2_1_从sys_order order0_ 内部连接 sys_customer customer1_ on order0_.order_cust_id=customer1_.cust_id?* Hibernate:选择customer0_.cust_id作为cust_id1___,customer0_.cust_name as cust_nam2___ as sys_customer customer0_ customer0_.cust_id=?*/

我的问题是:

在使用cross-join?

  • What链方法以避免场景/最佳实践时,
    1. 是否可以指定连接类型(内部,所有三个外部)或Fetch类型(懒惰,急切)?应该使用get(" chain ")还是始终保持在Join中?
    2. 使用静态方法是否符合良好的OOP设计模式?
EN

回答 1

Stack Overflow用户

发布于 2021-10-13 09:05:16

不能为路径指定联接类型。默认情况下,它将使用内部连接语义,这是JPA规范要求的。如果希望使用不同的联接类型,则必须显式创建联接。使用get呈现为交叉连接是Hibernate旧查询模型的一个限制,但Hibernate 6.0将修复这个问题。但是语义是相同的,数据库的查询规划师应该能够以相同的方式处理这两个查询。也许你只需要更新你的数据库版本?

没有“最佳实践”,也就是说,这取决于你的需要。显式联接就是显式的。因此,对join的多次调用将在SQL中创建多个联接。

至于面向对象的问题,我认为这很好,是的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69322050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档