需要帮助将标准sql查询转换为jpa条件查询吗

lzfw57am  于 2021-06-30  发布在  Java
关注(0)|答案(4)|浏览(342)

我有两张table:
雇员

id
firstName
lastName
.
.
.

训练

id
employeeId
trainingName
trainingSuspsnseDate
trainingComplete

在mysql workbench中执行标准sql查询时,如下所示:

SELECT e.id, e.firstName, e.lastName, t.trainingName, t.trainingSuspenseDate, t.trainingComplete
FROM Employee e
JOIN Training t on t.employeeId = e.id
WHERE t.trainingSuspenseDate < CURDATE()
order by t.trainingSuspenseDate;

现在,我想为同一个sql查询创建一个criteria查询,但是连接有问题。这是我在谷歌上尝试过的:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> employeeQuery = builder.createQuery(Employee.class);
Root<Employee> employee = employeeQuery.from(Employee.class);
Join<Employee, Training> training = employee.join(Employee_.ID);
employeeQuery.select(builder.construct(Employee.class,
    employee.get(Employee_.ID),
    employee.get(Employee_.firstName),
    employee.get(Employee_.lastName),
    training.get(Training_trainingName),
    training.get(Training_trainingSuspsnseDate),
    training.get(Training_trainingComplete)));

但是,我得到了一个错误:

incompatible types: inference variable Y has incompatible equality constraints Templates,Integer where Y,X are type-variables:
Y extends Object declared in method <Y>join(SingularAttribute<? super X,Y>)
X extends Object declared in interface From

我试过其他的排列 JOIN ,但我有不同的错误。我似乎找不到创建此查询的确切“秘密”。

Join<Employee, Training> training = training.join(Training_.employeeId);

Join<Employee, Training> training = training.join(Training_.employeeId).join(Employee_.ID);

Join<Training, Employee> training = training.join(Training_.employeeId);

Join<Training, Employee> training = training.join(Training_.employeeId).join(Employee_.ID);

.
.
.

编辑:添加了我的模型类

员工.java

@Entity
@Table(name = "employee")
@XmlRootElement
@NamedQueries(
        {
            @NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e"),
            @NamedQuery(name = "Employee.deleteAll", query = "DELETE FROM Employee e"),
            @NamedQuery(name = "Employee.countAll", query = "SELECT COUNT(e.ID) FROM Employee e")
        })
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @GeneratedValue
    @Column(name = "id")
    private Integer ID;

    @Basic(optional = true)
    @Column(name = "name_first")
    private String firstName;

    @Basic(optional = true)
    @Column(name = "name_last")
    private String lastName;

    @Basic(optional = true)
    @Column(name = "created_date")
    private String employeeDate;

    @Basic(optional = true)
    @Column(name = "personal_type")
    private String personnelType;

    public Employee() {
        ID = 0;
    }

    public Employee(Integer id) {
        this.ID = id;
    }

    public Integer getID() {
        return ID;
    }

    public void setID(Integer id) {
        this.ID = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmployeeDate() {
        return employeeDate;
    }

    public void setEmployeeDate(String employeeDate) {
        this.employeeDate = employeeDate;
    }

    public String getPersonnelType() {
        return personnelType;
    }

    public void setPersonnelType(String personnelType) {
        this.personnelType = personnelType;
    }

}

培训.java

@Entity
@Table(name = "training")
@XmlRootElement
@NamedQueries(
        {
            @NamedQuery(name = "Training.findAll", query = "SELECT t FROM Training t"),
            @NamedQuery(name = "Training.deleteAll", query = "DELETE FROM Training t"),
            @NamedQuery(name = "Training.countAll", query = "SELECT COUNT(t.ID) FROM Training t")
        })
public class Training implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @GeneratedValue
    @Column(name = "ID")
    private Integer ID;

    @Basic(optional = false)
    @Column(name = "employee_id")
    private String employeeId;

    @Basic(optional = false)
    @Column(name = "training_name")
    private String trainingName;

    @Basic(optional = false)
    @Column(name = "training_suspense_date")
    private Date trainingSuspenseDate;

    @Basic(optional = false)
    @Column(name = "training_complete")
    private Boolean trainingComplete;

    public Integer getID() {
        return ID;
    }

    public void setID(Integer ID) {
        this.ID = ID;
    }

    public String getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }

    public void setTrainingName(String trainingName) {
        this.trainingName = trainingName;
    }

    public String getTrainingName() {
        return trainingName;
    }

    public void setTrainingSuspenseDate(Date trainingSuspsenseDate) {
        this.trainingSuspsenseDate = trainingSuspsenseDate;
    }

    public Date getTrainingSuspenseDate() {
        return trainingSuspsenseDate;
    }

    public void setTrainingComplete(Boolean trainingComplete) {
        this.trainingComplete = trainingComplete;
    }

    public Boolean getTrainingComplete() {
        return trainingComplete;
    }
}
yhqotfr8

yhqotfr81#

你可以试试 cross join . 本机sql有点不同,但结果与预期的一样

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> employeeQuery = builder.createQuery(Employee.class);
Root<Employee> employee = employeeQuery.from(Employee.class);
Root<Employee> training= employeeQuery.from(Training.class);

employeeQuery.select(builder.construct(Employee.class,
    employee.get(Employee_.ID),
    employee.get(Employee_.firstName),
    employee.get(Employee_.lastName),
    training.get(Training_.trainingName),
    training.get(Training_.trainingSuspsnseDate),
    training.get(Training_.trainingComplete)))
.where(builder.equal(employee.get(Employee_.ID), training.get(Training_.employeeId)));
6qqygrtg

6qqygrtg2#

此错误消息-不兼容类型:推断变量y具有不兼容的相等约束-表示您需要仔细检查要加入的列的数据类型。对于性能和高速比较,=两侧的数据类型应该相同。

gxwragnw

gxwragnw3#

从模型类来看,实体并不是直接相关的(即使 employeeIdTraining 应该是外键,但在实体关系中没有这样定义。因此,如果您希望在不改变现有实体的情况下与现有实体合作,您需要以下内容-
根据select子句Map属性的pojo(例如empres)。criteriaquery应在此pojo上初始化为- CriteriaQuery<EmpRes> criteriaQuery = builder .createQuery(EmpRes.class); 由于实体不相关,生成的查询将具有交叉连接。
代码看起来像-

criteriaQuery.select(builder.construct(EmpRes.class, employee
        .get(Employee_.getAttribute("ID").getName()), employee
        .get(Employee_.getAttribute("firstName").getName()), employee
        .get(Employee_.getAttribute("lastName").getName()), training
        .get(Training_.getAttribute("trainingName").getName()),
        training.get(Training_.getAttribute("trainingSuspenseDate")
                .getName()), training.get(Training_.getAttribute(
                "trainingComplete").getName())));

        criteriaQuery.where(builder.equal(employee.get("ID"), training.get("employeeId")));
        List<EmpRes> employees = entityManager.createQuery(criteriaQuery).getResultList();

但是,如果实体可以更改(这应该是理想的设计),则员工需要接受培训。所以,一个 @OneToMany 员工和培训模型类之间的关系应定义如下-
员工.java @OneToMany(mappedBy="employee") private Set<Training> trainings = new HashSet<>(); 培训.java @ManyToOne @JoinColumn(name = "employeeId") private Employee employee; 准则查询相关代码-

Join<Employee, Training> trainingJoin = employee.join(Employee_.getAttribute("trainings").getName());
criteriaQuery.select(builder.construct(EmpRes.class, employee
        .get(Employee_.getAttribute("ID").getName()), employee
        .get(Employee_.getAttribute("firstName").getName()), employee
        .get(Employee_.getAttribute("lastName").getName()),
        trainingJoin.get(Training_.getAttribute("trainingName")
                .getName()), trainingJoin.get(Training_.getAttribute(
                "trainingSuspenseDate").getName()), trainingJoin
                .get(Training_.getAttribute("trainingComplete")
                        .getName())));

然后可以根据您的需求添加额外的where子句。这里是对criteriaapi的一个很好的参考。

64jmpszr

64jmpszr4#

我可以看出您已经为您的查询生成了一个元模型。因此,最好的方法是扩展实体定义,如下所示:
您必须在 Training 班级:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employeeId")
private Employee employee;

然后在你的 Employee 类添加站点引用:

@OneToMany(mappedBy = "employee")
private Set<Training> trainings = new HashSet<>();

然后将条件查询更改为:

Join<Employee, Training> training = employee.join(Employee_.trainings);

相关问题