Java 需要帮助将标准SQL查询转换为JPA条件查询吗
我有两张桌子: 员工Java 需要帮助将标准SQL查询转换为JPA条件查询吗,java,mysql,jpa,criteria-api,Java,Mysql,Jpa,Criteria Api,我有两张桌子: 员工 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 Emplo
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;
或
编辑:添加了我的模型类 Employee.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;
}
}
@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;
}
}
Training.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;
}
}
@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;
}
}
我可以看出,您已经为您的查询生成了一个元模型。 因此,最好的方法是扩展实体定义,如下所示: 您必须在
培训
课程中添加映射:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employeeId")
private Employee employee;
然后在您的Employee
类中添加站点引用:
@OneToMany(mappedBy = "employee")
private Set<Training> trainings = new HashSet<>();
@OneToMany(mappedBy=“employee”)
私有集=新HashSet();
然后将条件查询更改为:
Join<Employee, Training> training = employee.join(Employee_.trainings);
Join training=employee.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)));
CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery employeeQuery=builder.createQuery(Employee.class);
Root employee=employeeQuery.from(employee.class);
Root 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\uu.trainingName),
培训。获取(培训\培训USPSN镇静),
培训。获取(培训完成)
.where(builder.equal(employee.get(employee.ID)),training.get(training.employeeId));
查看您的模型类,实体没有直接关联(即使培训中的employeeId
应该是外键,但在实体关系中没有定义为外键。因此,如果您希望在不更改现有实体的情况下使用现有实体,您需要以下内容-
根据select子句映射属性的POJO(例如EmpRes)。应将此POJO上的criteriaQuery初始化为-
CriteriaQuery 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();
然后,您可以根据自己的需求添加额外的where子句。
标准API的一个很好的参考是。此错误消息-不兼容类型:推理变量Y具有不兼容的等式约束-表明您需要仔细检查要加入的列的数据类型。在=的两侧,数据类型应该是相同的,以便进行性能和高速比较。是否可以w员工和培训实体?@SB我已经添加了我的模型类。谢谢。只有一名员工需要培训的培训?什么是私有集
?我没有用户类。应该是Training@Brian您是否发现数据类型存在差异并提高了性能?
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employeeId")
private Employee employee;
@OneToMany(mappedBy = "employee")
private Set<Training> trainings = new HashSet<>();
Join<Employee, Training> training = employee.join(Employee_.trainings);
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)));
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();
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())));