【问题标题】:Java - Criteria API - Unidirectional OneToManyJava - 标准 API - 单向 OneToMany
【发布时间】:2020-08-05 22:48:03
【问题描述】:

我正在尝试通过标准 API 从流程表中的人员那里获取许可证号。 基本上来自Process -> Person -> License

但是,Person 表与表 License 具有单向 OneToMany 关系。

所以我有以下实体:

@Entity
@Table(name = "Process")
public class Process {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "person_id")
    Person person;
}

@Entity
@Table(name = "Person")
public class Person {
    @Id
    @Column(name = "id",columnDefinition="INTEGER")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;
    
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
    List<License> licenses;
}

@Entity
@Table(name = "License")
public class License {
    @Id
    @Column(name = "id",columnDefinition="INTEGER")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;
    
    @JoinColumn(name = "person_id")
    @ManyToOne(fetch = FetchType.LAZY)
    Person person;
    
    String licenseNumber;
}

在本机查询中,我想要完成的结果是:

  select lic.license_number, * from Process process
  left join Person p on process.person_id = p.id
  left join License lic on lic.person_id = p.id;

我已经尝试过加入:

final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Process> criteria = builder.createQuery(Process.class);
final Root<Process> rootSelect = criteria.from(Process.class);

//I don't really know how to join rootSelect (Process table), with License table... having the table Person in middle..
Join<Process, Person> personJoin = rootSelect.join("person");
Join<License, Person> licenseJoin = rootSelect.join("person");

也考虑使用子查询:

final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Process> criteria = builder.createQuery(Process.class);
final Root<Process> rootSelect = criteria.from(Process.class);

Subquery sub = criteria.subquery(String.class);
Root subRoot = sub.from(License.class);
//How to select just the field 'license_number' below?
sub.select(subRoot);
sub.where(builder.equal(rootSelect.get("person").get("id"), subRoot.get("person")));

我将需要 license_number 用于最后的过滤器(位置)。

考虑到我的根表是 Process,执行这种过滤器的最佳方法是什么?

【问题讨论】:

    标签: java spring hibernate criteria-api


    【解决方案1】:

    严格来说,你不必加入带有许可证的流程表,你必须加入带有个人和许可证的过程,如下所示:

    Join<Process, Person> personJoin = rootSelect.join("person",JoinType.INNER);
    Join<Person, License> licenseJoin = personJoin.join("licenses",JoinType.INNER);
    

    建议使用元模型和实体,它们的连接如下(元模型由EntityName_表示):

    Join<Process, Person> personJoin = rootSelect.join(Process_.person,JoinType.INNER);
    Join<Person, License> licenseJoin = personJoin.join(Person_.licences,JoinType.INNER);
    

    对我来说最明显的好处是您可以自动完成元模型的属性,放置一个字符串会增加我们出错的机会。

    我们添加过滤条件

    cq.where(cb.equal(licenceseJoin.get("licenseNumber"),LICENSE_NUMBER));
    //cq.where(cb.equal(licenceseJoin.get(License_.licenseNumber),LICENSE_NUMBER));
    

    【讨论】:

      猜你喜欢
      • 2021-03-04
      • 2014-06-27
      • 2013-08-30
      • 1970-01-01
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      • 2013-11-20
      相关资源
      最近更新 更多