JPA Left Join IS NULL条件不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA Left Join IS NULL条件不起作用相关的知识,希望对你有一定的参考价值。

我在mysql上有User和Employee表,在User表中有employeeId作为外键。

现在我需要找到没有用户的员工。

我在MySQL Workbench中编写这个SQL,这正是我想要的:

SELECT * FROM HUMANRESOURCE.EMPLOYEE E LEFT JOIN AUTHORIZE.USER U 
                                       ON U.EMPLOYEEOBJID = E.OBJID  
                                       WHERE U.EMPLOYEEOBJID is NULL;

但是当我尝试将此SQL实现为JPA查询时,它什么都不返回。这是JPA查询:

Query query = em.createQuery("SELECT e FROM Employee e LEFT JOIN User u 
                                        WHERE u.employee.objid = e.objid 
                                        AND u.employee IS NULL");

这是真正有效的JPA Query,用于获取拥有用户的员工:

Query query = em.createQuery("SELECT e FROM Employee e INNER JOIN User u 
                                       WHERE u.employee.objid = e.objid");

我在这做错了什么?

实体类的更新:

base.Java

package com.kadir.entity;

import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;


@Cacheable
@MappedSuperclass
public abstract class Base {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "OBJID")
    private BigInteger objid;

    @Column(name = "CREATEDBY")
    private String createdby;

    @Column(name = "CREATEDDATE")
    private Timestamp createddate;

    @Version
    @Column(name = "ROWVERSION")
    private Integer rowversion;

    @Column(name = "UPDATEDBY")
    private String updatedby;

    @Column(name = "UPDATEDDATE")
    private Timestamp updateddate;

    @Column(name = "ARCHIVED", columnDefinition = "int default 0")
    private int archived;

    public BigInteger getObjid() {
        return this.objid;
    }

    public void setObjid(BigInteger objid) {
        this.objid = objid;
    }

    public String getCreatedby() {
        return this.createdby;
    }

    public void setCreatedby(String createdby) {
        this.createdby = createdby;
    }

    public Date getCreateddate() {
        return this.createddate;
    }

    public void setCreateddate(Timestamp createddate) {
        this.createddate = createddate;
    }

    public Integer getRowversion() {
        return this.rowversion;
    }

    public void setRowversion(Integer rowversion) {
        this.rowversion = rowversion;
    }

    public String getUpdatedby() {
        return this.updatedby;
    }

    public void setUpdatedby(String updatedby) {
        this.updatedby = updatedby;
    }

    public Timestamp getUpdateddate() {
        return this.updateddate;
    }

    public void setUpdateddate(Timestamp updateddate) {
        this.updateddate = updateddate;
    }

    public int getArchived() {
        return archived;
    }

    public void setArchived(int archived) {
        this.archived = archived;
    }
}

employee.Java

package com.kadir.entity.humanresource;

import com.kadir.entity.corporation.Company;
import com.kadir.entity.Base;

import java.io.Serializable;

import javax.persistence.*;


/**
 * The persistent class for the EMPLOYEE database table.
 * 
 */
@Cacheable
@Entity
@Table(name = "EMPLOYEE", schema = "HUMANRESOURCE")
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")
public class Employee extends Base implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToOne
    @JoinColumn(name = "COMPANYOBJID")
    private Company company;

    @Column(name = "FIRSTNAME")
    private String firstname;

    @Column(name = "GENDER")
    private int gender;

    @Column(name = "EMAIL")
    private String email;

    @Column(name = "PHONE")
    private String phone;

    @Column(name = "LASTNAME")
    private String lastname;

    public Employee() {
    }

    public Company getCompany() {
        return this.company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public String getFirstname() {
        return this.firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public int getGender() {
        return this.gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return this.phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getLastname() {
        return this.lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

}

user.Java

package com.kadir.entity.authorize;

import com.kadir.entity.Employee;
import com.kadir.entity.Base;
import java.io.Serializable;
import javax.persistence.*;


import java.util.List;


/**
 * The persistent class for the USER database table.
 * 
 */
@Cacheable
@Entity
@Table(name="USER", schema="AUTHORIZE")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User extends Base implements Serializable {
    private static final long serialVersionUID = 1L;

    @OneToOne
    @JoinColumn(name="EMPLOYEEOBJID")
    private Employee employee;

    @Column(name="NAME")
    private String name;

    @Column(name="PASSWORD")
    private String password;

    public User() {
    }

    public Employee getEmployee() {
        return this.employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}
答案

EclipseLink支持ON clause,因此请尝试使用

"SELECT e FROM Employee e LEFT JOIN User u on u.employee = e WHERE u.employee IS NULL"

您还可以使用exists和子查询:

"select e from Employee e where not exists (select 1 from User u where u.employee = e)"
另一答案

就我而言,我正在使用Apache OpenJPA。

查询应该是这样的:

SELECT e FROM Employee e LEFT JOIN e.user u WHERE u.employeeId IS NULL

以上是关于JPA Left Join IS NULL条件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LEFT JOIN 创建 JPA NamedQuery

LEFT JOIN FETCH 不起作用 - Spring 数据 JPA

嵌套 CONCAT 中的 LEFT JOIN 和 IS NULL 仅返回 NULL

带有 IS NULL 的 LEFT OUTER JOIN

LEFT OUTER JOIN with 'field IS NULL' in WHERE 用作 INNER JOIN

NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: SQL Server