Spring JPA 基于类的投影和嵌套投影

问题描述 投票:0回答:2

我正在尝试使用基于类的投影来填充数据,但 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
,而且我没有找到任何使用嵌套投影来填充给定实体的父信息的选项。有人可以帮我解决以下问题吗?

  1. 有没有办法使用基于类的投影来实现这一点?
  2. 我需要回退到单独填写父级信息的选项(在初始加载中我不需要父级的大量信息。)。
  3. 还有其他方法可以实现这一目标吗?我不想使用基于接口的投影作为初始测试,表明与基于类的投影相比,它非常慢。
spring-data-jpa jpa-2.0 jpa-2.1
2个回答
3
投票

Spring Data JPA 中没有对此提供开箱即用的支持。 实现此目的的方法是使用 构造函数表达式

ResultTransformer


0
投票

事实上,可以使用 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
© www.soinside.com 2019 - 2024. All rights reserved.