Reputation: 23587
I am trying to use the Class-based Projections to fill the data but seems the Spring JPA does not support the nested projection. Here is my entity class:
public class Category extends BaseEntity<String> {
@Column(unique = true)
private String code;
private String externalCode;
@ManyToOne(cascade = CascadeType.ALL)
private Category parent;
..
}
Here is the DTO class for same:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CategoryDto implements BaseDto, Serializable {
private String code;
private String externalCode;
private CategoryDto parent;
..
}
My CategoryRepository
@Query("select new com.easycart.core.data.category.CategoryDto(c.id,c.code,c.externalCode,c.seoMeta, c.createdAt, c.updatedAt,c.parent) FROM Category c where c.code = :code")
CategoryDto findCategoryByCode(String code);
I can't use the c.parent
as the type is Category
and not the CategoryDto
, also I did not find any option to use the nested projection to fill the parent information for the given entity. Can someone help me with following questions?
Upvotes: 2
Views: 3904
Reputation: 125
In fact, it is possible to create dynamic select queries with spring data jpa and hibernate. It only supports @OneToOne and @ManyToOne queries. Take a look at array usages for each RDBMS to support @OneToMany queries.
You can check out the benchmark test for more details. hibernate-jpa-class-based-nested-projections-and-speed
A simple @ManyToOne example:
table user:
public class User {
@Id
@SequenceGenerator(name = "user_sequence", sequenceName = "sq_user",allocationSize = 1_000)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_sequence")
private Long id;
@Column
private String email;
@Column
private String password;
@ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
@ToString.Include(name = "id")
private Adress adress;
/*
@Override
public String toString() {
return "User [id=" + id + ", email=" + email + ", password=" + password
+ ", adress=" + this.getAdress().getId()
+ "]";
}
*/
}
table adress:
public class Adress {
@ToString.Include
@EqualsAndHashCode.Include
@Id
@SequenceGenerator(name = "adres_sequence", sequenceName = "sq_adres",allocationSize = 1_000)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "adres_sequence")
private Long id;
@Column
private Integer no;
@Column
private String house;
public Adress(Long id) {
this.id = id;
}
}
Dto :
@Data
public class UserDto1 {
private Long id;
private String email;
private String password;
private AdressDTO1 adressDTO;
public UserDto1(Long id, String email, String password, Long adressId, int adressNo, String adressHouse) {
this.id = id;
this.email = email;
this.password = password;
this.adressDTO = new AdressDTO1(adressId, adressNo, adressHouse);
}
}
@Data
@AllArgsConstructor
public class AdressDTO1 {
private Long id;
private int no;
private String house;
}
Repo. and Service Layer :
//Repository Class Method:
public <T> List<T> findBy(Class<T> clazz);
//Service Layer:
userRepository.findBy(UserDto1.class);
output:
select
user0_.id as col_0_0_,
user0_.email as col_1_0_,
user0_.password as col_2_0_,
adress1_.id as col_3_0_,
adress1_.no as col_4_0_,
adress1_.house as col_5_0_
from
user user0_
left outer join
adress adress1_
on user0_.adress_id=adress1_.id
Upvotes: 0
Reputation: 81930
There is no out of the box support for this in Spring Data JPA.
The way to achieve this is to use constructor expressions and ResultTransformer
Upvotes: 3