JPQL-带过滤器的JOIN查询

时间:2019-02-28 08:37:35

标签: java mysql hibernate jpa jpql

我有实体:

第一

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Technic implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String gosNumber;

    private String invNumber;

    private String shassisNumber;

    private String engineNumber;

    @Column(length = 100)
    private String yearOfMake;

    @ManyToOne
    private Farm farm;

    @JsonManagedReference
    @ManyToOne
    private TechGroup techGroup;

    @JsonManagedReference
    @ManyToOne
    private TechType techType;

    @JsonManagedReference
    @ManyToOne
    private TechMark techMark;

    @JsonIgnore
    @CreationTimestamp
    @Column(name = "creation_date", updatable = false)
    private LocalDateTime createdDate;

    @JsonIgnore
    @Column(name = "updated_date")
    @UpdateTimestamp
    private LocalDateTime updatedDate;

    @JsonIgnore
    @Column(columnDefinition = "Bool default false")
    private Boolean isDel;


    @JsonManagedReference
    @OneToMany(mappedBy = "technic")
    private List<TechnicStatus> technicStatusList = new ArrayList<>();

    public List<TechnicStatus> getTechnicStatusList() {
        return technicStatusList;
    }

    public void setTechnicStatus(TechnicStatus technicStatus) {
        this.technicStatusList = new ArrayList<>();
        this.technicStatusList.add(technicStatus);
    }

第二:

@Entity
@Getter
@Setter
@NoArgsConstructor
public class TechnicStatus implements Serializable  {



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

    @JsonBackReference
    @ManyToOne
    private Technic technic;

    @JsonManagedReference
    @ManyToOne
    private Status status;

    private Boolean isGarantia;

    private Boolean isLizing;

    private LocalDate visitedDate;

    private LocalDate notWorkDate;

    private String description;

    @JsonIgnore
    private boolean isActive;

    @JsonIgnore
    @CreationTimestamp
    @Column(name = "creation_date", updatable = false)
    private LocalDateTime createdDate;
}

我想从包含每个对象Technic中的List的数据库中获取结果,我有List technicStatusList = new ArrayList <>(),其中我只想拥有一个TechnicStatus,其值为isActive = true。

为此,我正确执行相同的JPQL查询:

TypedQuery<Technic> query = em.createQuery("Select t  from Technic t join TechnicStatus ts on t.id = ts.technic.id where t.isDel=false and ts.isActive=true and t.farm.id=:farmId order by t.techGroup.name, t.techType.name, t.techMark.name", Technic.class);

但是得到一个包含TechnicStatus的结果,该结果将返回带有true和false(TechnicStatus.isActive = true,TechnicStatus.isActive = false)的TechnicStatus。

我想通过本机查询获得结果:

SELECT 
    *
FROM
    technic
        JOIN
    technic_status ON technic.id = technic_status.technic_id
WHERE
    technic.is_del = FALSE
        AND technic_status.is_active = TRUE
        AND technic.farm_id = 1722

2 个答案:

答案 0 :(得分:0)

与技术人员相关联的TechnicalStatus列表将始终是您的映射所定义的完整列表。

基本上,您有2个选择。如果您只对状态为Active的TechnicalStatus感兴趣,则可以在关联上使用非便携式的,特定于Hibernate的@Where子句。

@JsonManagedReference
@OneToMany(mappedBy = "technic")
@Where("active = 1")
private List<TechnicStatus> technicStatusList = new ArrayList<>();

https://dzone.com/articles/hibernate-where-clause

否则,您要做的就是从查询方法中返回技术状态列表,这不是您想要的,而是您所拥有的全部。

答案 1 :(得分:0)

无法在查询条件中过滤相关集合。您可以通过对TechnicalStatus进行选择来获得它:select ts from TechnicStatus ts join Technic t where ...

我注意到的其他事情:

添加新状态时,您正在覆盖现有状态列表:

public void setTechnicStatus(TechnicStatus technicStatus) {
     this.technicStatusList = new ArrayList<>();
     this.technicStatusList.add(technicStatus);
}

在字段声明中初始化technicStatusList。技术中的添加方法:

public void addTechnicStatus(TechnicStatus technicStatus) {
    getTechnicStatusList().add(technicStatus);
    technicStatus.setTechnic(this);
}

我注意到的其他事情:

使用连接时,请勿使用on t.id = ts.technic.id。 JPA会在您编写以下内容时创建正确的本机SQL:join TechnicStatus ts WHERE ...