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

iovurdzv  于 11个月前  发布在  Spring
关注(0)|答案(2)|浏览(207)

我尝试使用基于类的投影来填充数据,但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.有没有一种方法可以使用基于类的投影来实现这一点?
1.我是否需要回退到单独填充父信息的选项(在初始加载中,我不需要父信息的大量信息。)
1.还有其他的方法吗?我不想使用基于接口的投影作为初始测试,因为与基于类的投影相比,它非常慢。

dxxyhpgq

dxxyhpgq1#

Spring Data JPA中没有对此的开箱即用支持。实现此功能的方法是使用constructor expressionsResultTransformer

x8goxv8g

x8goxv8g2#

事实上,可以使用spring data jpa和hibernate创建动态选择查询。它只支持@OneToOne和@ManyToOne查询。看看每个RDBMS支持@OneToMany查询的数组用法。
您可以查看基准测试以了解更多详细信息。hibernate-jpa-class-based-nested-projections-and-speed
一个简单的@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;
 }
}


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;
}


回购和服务层:

//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

相关问题