首页 > 解决方案 > Spring Boot JPA 关联与普通 SQL 连接

问题描述

我有三张桌子:

  1. 公司:

    +--------------+-------------+------+-----+---------+-------+
    | Field        | Type        | Null | Key | Default | Extra |
    +--------------+-------------+------+-----+---------+-------+
    | company_id   | int(11)     | NO   | PRI | NULL    |       |
    | company_name | varchar(45) | YES  |     | NULL    |       |
    +--------------+-------------+------+-----+---------+-------+

  1. 合法的:
    +-------------+---------+------+-----+---------+----------------+
    | Field       | Type    | Null | Key | Default | Extra          |
    +-------------+---------+------+-----+---------+----------------+
    | id          | int(11) | NO   | PRI | NULL    | auto_increment |
    | company_id  | int(11) | YES  |     | NULL    |                |
    | legal_price | double  | YES  |     | NULL    |                |
    +-------------+---------+------+-----+---------+----------------+
  1. 价格
    +------------+---------+------+-----+---------+----------------+
    | Field      | Type    | Null | Key | Default | Extra          |
    +------------+---------+------+-----+---------+----------------+
    | id         | int(11) | NO   | PRI | NULL    | auto_increment |
    | company_id | int(11) | YES  |     | NULL    |                |
    | price      | int(11) | YES  |     | NULL    |                |
    +------------+---------+------+-----+---------+----------------+

company->legalcompany->之间有两个一对多的关联price。中的公司数据company很少更改。另外两个表中的数据每天都被持久化。对应的实体如下:

@Entity
@Table(name = "company")
public class CompanyEntity {


    @Id
    @Column(name = "company_id", nullable = false)
    private Integer companyID;

    @Column(name = "company_name")
    private String companyName;


     @OneToMany(mappedBy = "company", fetch = FetchType.LAZY,
                cascade = CascadeType.ALL)
    private Set<LegalEntity> legal;

     @OneToMany(mappedBy = "company", fetch = FetchType.LAZY,
                cascade = CascadeType.ALL)
    private Set<PriceEntity> price;

======

@Entity
@Table(name = "legal")
public class LegalEntity {

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

@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "company_id", nullable = false)
private CompanyEntity company;

@Column(name = "legal_price")
private Double legalPrice;

======

@Entity
@Table(name = "price")
public class PriceEntity {

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

@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "company_id", nullable = false)
private CompanyEntity company;

@Column(name = "price")
private Integer price;

legal为了在or中保存新数据,我首先使用 findBycompanyIDprice获取实体中的相应字段:company

    CompanyEntity cmp = crep.findBycompanyID(13);
    LegalEntity leg = new LegalEntity(cmp, 523.5);
    lrep.save(leg);

对于查询数据,我使用 CriteriaBuilder API:

      CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
      CriteriaQuery<LegalEntity> criteriaQuery = criteriaBuilder.createQuery(LegalEntity.class);
      Root<LegalEntity> root = criteriaQuery.from(LegalEntity.class);
      criteriaQuery = criteriaQuery.select(root);
      TypedQuery<LegalEntity> typedQuery = em.createQuery(criteriaQuery);
      List<LegalEntity> results = typedQuery.getResultList();
           for (LegalEntity legalEntity : results) {
                log.info(legalEntity.toString());
                }

这个过程可以通过一个简单的本地 SQL 查询来完成:

SELECT c.company_name, l.legal_price from legal l
JOIN company c
ON l.company_id = c. company_id;

当我调查 Hibernate SQL 命令时,我看到:

Hibernate: 
    select
        legalentit0_.id as id1_1_,
        legalentit0_.company_id as company_3_1_,
        legalentit0_.legal_price as legal_pr2_1_ 
    from
        legal legalentit0_
Hibernate: 
    select
        companyent0_.company_id as company_1_0_0_,
        companyent0_.company_name as company_2_0_0_ 
    from
        company companyent0_ 
    where
        companyent0_.company_id=?
Hibernate: 
    select
        companyent0_.company_id as company_1_0_0_,
        companyent0_.company_name as company_2_0_0_ 
    from
        company companyent0_ 
    where
        companyent0_.company_id=?
Hibernate: 
    select
        companyent0_.company_id as company_1_0_0_,
        companyent0_.company_name as company_2_0_0_ 
    from
        company companyent0_ 
    where
        companyent0_.company_id=?
Hibernate: 
    select
        companyent0_.company_id as company_1_0_0_,
        companyent0_.company_name as company_2_0_0_ 
    from
        company companyent0_ 
    where
        companyent0_.company_id=?

我的问题是,哪种方法更有效?我更喜欢使用 CriteriaBuilder API,因为编码更容易且不易出错,但我必须在每次持久化之前查询公司字段。

标签: spring-bootspring-data-jpahibernate-criteria

解决方案


推荐阅读