以下是我的实体结构。 EmployeeKey是Employee中的EmbeddedId(复合键)。
这是我想使用Spring-Data实现的本机查询。
select DISTINCT(ID), NAME, DEPARTMENT from EMPLOYEE;
我正在尝试使用基于接口和基于类的Spring数据JPA投影,但是这些方法似乎都不起作用。基于接口的预测给出了我无法取消代理的代理列表。在基于类的投影的构造函数中不能使用 DISTINCT 。
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@EmbeddedId
private EmployeeKey key;
@Column(name = "NAME")
private String name;
@Column(name = "DEPARTMENT")
private String department;
@Coulmn(name = "AGE")
private Integer age;
//Getter/Setters/Constructors
}
@Embeddable
public class EmployeeKey {
@Column(name = "ID")
String id;
@Column(name = "REGNO")
String regNo;
//Getter/Setters/Constructors
}
@Repository
public interface EmployeRepository extends JpaRepository<Employee, EmployeeKey>{
@Query(value = "select distinct(emp.key.id), emp.name, emp.department from Employee emp")
List<EmployeeInterfaceProjection> findUsingInterfaceProjection();
@Query(value = "select distinct(emp.key.id) as empId, emp.name as empName, emp.department as empDepartment from Employee emp")
List<EmployeeClassProjection1> findUsingClassProjection1();
@Query(value = "select new com.path.to.EmployeeClassProjection2(emp.key, emp.name, emp.department) from Employee emp")
List<EmployeeClassProjection2> findUsingClassProjection2();
@Query(value = "select distinct(emp.key.id) as empId, emp.name as empName, emp.department as empDepartment from Employee emp")
List<Object[]> findUsingObjectProjection();
}
public interface EmployeeInterfaceProjection{
EmployeeKeyInterfaceProjection getKey();
String getName();
String getDepartment();
interface EmployeeKeyInterfaceProjection{
String getId();
}
}
public class EmployeeClassProjection1{
private String empId;
private String empName;
private String empDepartment;
//Getters/Setters, Constructors, Hashcode, Equals
}
public class EmployeeClassProjection2{
private EmployeeKey key;
private String name;
private String department;
//Getters/Setters, Constructors, Hashcode, Equals
}
每种方法所面临的问题
findUsingInterfaceProjection()
这给出了一个我无法取消获取值的列表。 Hibernate.unproxy / initialize也不起作用。在代理上流式传输并调用getter:getKey(),getName(),getDepartment()时,每个值都为空。
findUsingClassProjection1()
这给出了“找不到能够从类型[org.springframework.data.jpa.repository.query。 AbstractJpaQuery $ TupleConverter $ TupleBackedMap ]转换为[com.path.to.EmployeeClassProjection1]的转换器。 ]”错误。
我知道为了解决这个问题,我需要直接在查询中使用参数化的构造函数。但是这样做禁止我在构造函数中使用 DISTINCT 。
findUsingClassProjection2()
这种方法实际上是获取数据而不是代理,但我需要进行独特的过滤。无法在查询的构造函数内使用DISTINCT。
findUsingObjectProjection()
这很好,但是看起来很粗糙。我希望使用JPA预测。
答案 0 :(得分:1)
@Repository
public interface EmployeRepository extends JpaRepository<Employee, EmployeeKey>{
@Query(value = "select distinct(emp.key.id) as id, emp.name, emp.department from Employee emp")
List<EmployeeInterfaceProjection> findUsingInterfaceProjection();
@Query(value = "select distinct(emp.key.id) as empId, emp.name as empName, emp.department as empDepartment from Employee emp")
List<EmployeeClassProjection1> findUsingClassProjection1();
@Query(value = "select new com.path.to.EmployeeClassProjection2(emp.key, emp.name, emp.department) from Employee emp")
List<EmployeeClassProjection2> findUsingClassProjection2();
@Query(value = "select distinct(emp.key.id) as empId, emp.name as empName, emp.department as empDepartment from Employee emp")
List<Object[]> findUsingObjectProjection();
}
public interface EmployeeInterfaceProjection{
String getId();
String getName();
String getDepartment();
}
public interface EmployeeClassProjection1{
String getEmpId;
String getEmpName;
String getEmpDepartment;
}
如果要获取内部对象:
public interface dto {
@Value("#{target.Object.Id}")
Integer getId();
}
答案 1 :(得分:1)
这终于对我有用。我在查询中使用了列别名,以匹配投影中的getter方法名称(如果投影具有 getName(),则别名为 name )。 无需使用内部接口EmployeeKeyInterfaceProjection 。
public interface EmployeeInterfaceProjection{
String getId();
String getName();
String getDepartment();
}
@Query(value = "select distinct(emp.key.id) as id, emp.name as name, emp.department as department from Employee emp")
List<EmployeeInterfaceProjection> findUsingInterfaceProjection();
基于接口的投影在 AbstractJpaQuery $ TupleConverter $ TupleBackedMap 内部起作用。 Ealier,无需使用列别名,我对getId(),getName(),getDepartment()的每个属性都为null。使用别名可以解决此问题。
感谢@Ho Wai Chan指出正确的方向。