Ниже приведена структура моей сущности. EmployeeKey - это EmbeddedId (составной ключ) внутри Employee.
Это собственный запрос, который я хочу реализовать с помощью Spring-Data.
select DISTINCT(ID), NAME, DEPARTMENT from EMPLOYEE;
Я пытаюсь использовать Проекции JPA для данных на основе интерфейса и на основе классов , но ни один из подходов не работает. Проекции на основе интерфейса дают список прокси, которые я не могу отменить прокси. Использование DISTINCT в конструкторе проекций на основе классов невозможно, AFAIK.
@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 () выдает null для каждого.
findUsingClassProjection1 ()
Это дает "Не найден конвертер, способный конвертировать из типа [org.springframework.data.jpa.repository.query. AbstractJpaQuery $ TupleConverter $ TupleBackedMap ] в тип [com.path.to.EmployeeClassProjection1] " ошибка.
Я знаю, что для решения этой проблемы мне нужно использовать параметризованный конструктор непосредственно в запросе. Но это запрещает мне использовать DISTINCT в конструкторе.
findUsingClassProjection2 ()
Этот подход на самом деле получает данные, а не прокси, но мне нужна отдельная фильтрация. Не удается использовать DISTINCT внутри конструктора в запросе.
findUsingObjectProjection ()
Это отлично работает, но выглядит как очень грубый подход. Я надеялся использовать проекции JPA.