Jacob :
When I am implementing the Criteria API join for my spring boot study, I tried joining 2 classes and fetching the result. But when I am implementing and running I am getting the following error,
Unable to locate appropriate constructor on class [com.spacestudy.model.Investigator]. Expected arguments are: com.spacestudy.model.Employee
[cause=org.hibernate.PropertyNotFoundException: no appropriate constructor in class: com.spacestudy.model.Investigator]
And my Employee.java class like the following,
@Entity
@Table(name="employee")
public class Employee implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "employee_seq_generator")
@SequenceGenerator(name = "employee_seq_generator", sequenceName = "employee_seq",allocationSize=1)
@Column(name="nemp_id",columnDefinition="serial")
public Integer nEmpId;
@Column(name="semp_name")
public String sEmpName;
@Column(name="sdesignation")
public String sDesignation;
@Column(name="ninst_id")
public Integer nInstId;
@Column(name="ndept_id")
public Integer nDeptId;
@Column(name="sclient_emp_id")
public String sClientEmpId;
@Column(name="ntemp_emp_id")
public Integer nTempEmpId;
@Column(name="bis_paid")
public boolean bIsPaid=true;
@Column(name="sunpaid_comment")
public String sUnpaidComment;
@ManyToOne(optional=true)
@JoinColumn(name="ndept_id", insertable = false, updatable = false)
public Department department;
@OneToMany(cascade = CascadeType.ALL,mappedBy="nEmpId")
public Set<Investigator> employeeInvestigatorJoinMapping;
public Employee() {
}
public Employee(Integer nEmpId, String sEmpName, String sDesignation, Integer nInstId, Integer nDeptId,
String sClientEmpId, Integer nTempEmpId, boolean bIsPaid, String sUnpaidComment, Department department,
Set<Investigator> employeeInvestigatorJoinMapping) {
super();
this.nEmpId = nEmpId;
this.sEmpName = sEmpName;
this.sDesignation = sDesignation;
this.nInstId = nInstId;
this.nDeptId = nDeptId;
this.sClientEmpId = sClientEmpId;
this.nTempEmpId = nTempEmpId;
this.bIsPaid = bIsPaid;
this.sUnpaidComment = sUnpaidComment;
this.department = department;
this.employeeInvestigatorJoinMapping = employeeInvestigatorJoinMapping;
}
}
And my second class Investigator.java,
@Entity
@Table(name = "investigator")
@JsonInclude(JsonInclude.Include.NON_NULL) // avoiding null values
public class Investigator implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "investigator_seq_generator")
@SequenceGenerator(name = "investigator_seq_generator", sequenceName = "investigator_seq")
@Column(name="ninvestigator_id")
public Integer nInvestigatorId;
@Column(name="sinvestigator_name")
public String sInvestigatorName;
@Column(name="ninst_id")
public Integer nInstId;
@Column(name="stitle")
public String sTitle;
@Column(name="ntemp_investigator_id")
public Integer nTempInvestigatorId;
@ManyToOne(optional = false)
@JoinColumn(name="nemp_id",referencedColumnName="nemp_id")
public Employee nEmpId;
// Default Constructor.
public Investigator()
{
}
public Investigator(Integer nInvestigatorId, String sInvestigatorName, Integer nInstId, String sTitle,
Integer nTempInvestigatorId, Employee nEmpId) {
super();
this.nInvestigatorId = nInvestigatorId;
this.sInvestigatorName = sInvestigatorName;
this.nInstId = nInstId;
this.sTitle = sTitle;
this.nTempInvestigatorId = nTempInvestigatorId;
this.nEmpId = nEmpId;
}
}
And Implemented the Criteria API joining like the following,
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Investigator> cq = cb.createQuery(Investigator.class);
Root<Employee> rootInvestigator = cq.from(Employee.class);
Join<Employee ,Investigator> resultEmployeeMappingObj
= rootInvestigator.join("employeeInvestigatorJoinMapping");
cq.multiselect(rootInvestigator);
cq.where(cb.equal(resultEmployeeMappingObj.get("nEmpId"), 21638));
List<Investigator> results = em.createQuery(cq).getResultList();
return results;
Where did I go wrong?
Evgeniy Khyst :
Criteria API
You have a few mistakes in the Criteria API query.
The working one looks like this
@Transactional(readOnly = true)
public List<Investigator> findByEmployeeId(int employeeId) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Investigator> query = criteriaBuilder.createQuery(Investigator.class);
Root<Investigator> investigator = query.from(Investigator.class);
Join<Investigator, Employee> employees = investigator.join("nEmpId");
query.select(investigator)
.where(criteriaBuilder.equal(employees.get("nEmpId"), employeeId));
TypedQuery<Investigator> typedQuery = em.createQuery(query);
List<Investigator> investigators = typedQuery.getResultList();
log.debug("Investigators: {}", investigators);
return investigators;
}
Spring Data JPA
Also, if your application is based on Spring Framework after renaming a few fields you can use Spring Data JPA and do not write query at all.
Employee
entity:
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "employee_seq_generator")
@SequenceGenerator(name = "employee_seq_generator", sequenceName = "employee_seq", allocationSize = 1)
@Column(name = "nemp_id", columnDefinition = "serial")
public Integer id;
//...
@OneToMany(cascade = CascadeType.ALL, mappedBy = "employee")
public Set<Investigator> investigators = new HashSet<>();
//...
}
Investigator
entity:
@Entity
@Table(name = "investigator")
@JsonInclude(JsonInclude.Include.NON_NULL) // avoiding null values
public class Investigator implements Serializable {
//...
@ManyToOne(optional = false)
@JoinColumn(name = "nemp_id", referencedColumnName = "nemp_id")
public Employee employee;
//...
}
Spring Data JPA repository interface:
public interface InvestigatorRepository extends JpaRepository<Investigator, Integer> {
List<Investigator> findByEmployeeId(int employeeId);
}
That's it. Now you can simply inject the repository and use it:
@Autowired
private InvestigatorRepository investigatorRepository;
public void testQuery() {
investigatorRepository.findByEmployeeId(employee.getId()));
}
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=336745&siteId=1