我正在尝试使用基于类的投影来填充数据,但 Spring JPA 似乎不支持嵌套投影。这是我的实体类:
public class Category extends BaseEntity<String> {
@Column(unique = true)
private String code;
private String externalCode;
@ManyToOne(cascade = CascadeType.ALL)
private Category parent;
..
}
这是相同的 DTO 类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CategoryDto implements BaseDto, Serializable {
private String code;
private String externalCode;
private CategoryDto parent;
..
}
我的
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);
我无法使用
c.parent
,因为类型是 Category
而不是 CategoryDto
,而且我没有找到任何使用嵌套投影来填充给定实体的父信息的选项。有人可以帮我解决以下问题吗?
Spring Data JPA 中没有对此提供开箱即用的支持。 实现此目的的方法是使用 构造函数表达式 和
ResultTransformer
事实上,可以使用 spring data jpa 和 hibernate 创建动态选择查询。它仅支持@OneToOne和@ManyToOne查询。查看每个 RDBMS 的数组用法以支持 @OneToMany 查询。
您可以查看基准测试以了解更多详细信息。 hibernate-jpa-基于类的嵌套投影和速度
一个简单的@ManyToOne示例:
表用户:
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()
+ "]";
}
*/
}
餐桌地址:
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;
}
}
D :
@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;
}
回购。和服务层:
//Repository Class Method:
public <T> List<T> findBy(Class<T> clazz);
//Service Layer:
userRepository.findBy(UserDto1.class);
输出:
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