假设有两个实体:
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
@ManyToMany(mappedBy = "authors")
private Set<Book> books;
}
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String fileName;
private String fileType;
@Lob
private byte[] data;
@ManyToMany
@JoinTable(
name = "book_authors",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "author_id"))
private Set<Author> authors;
}
以下 DTO 接口投影用于仅查询需要的列。
public interface AuthorView {
String getFirstName();
String getLastName();
Set<BookView> getBooks();
interface BookView {
String getTitle();
}
}
一个简单的findAllBy
查询方法在存储库中声明:
public interface AuthorRepository extends JpaRepository<Author, Long> {
@EntityGraph(attributePaths = "books")
List<AuthorView> findAllBy();
}
该方法执行以下查询:
select
author0_.id as id1_0_0_,
book2_.id as id1_1_1_,
author0_.first_name as first_na2_0_0_,
author0_.last_name as last_nam3_0_0_,
book2_.data as data2_1_1_,
book2_.file_name as file_nam3_1_1_,
book2_.file_type as file_typ4_1_1_,
book2_.title as title4_1_1_,
books1_.author_id as author_i2_2_0__,
books1_.book_id as book_id1_2_0__
from
author author0_
left outer join
book_authors books1_
on author0_.id=books1_.author_id
left outer join
book book2_
on books1_.book_id=book2_.id
即使投影不包含data
, file_name
, and file_type
属性,它们是从数据库中获取的,这会导致性能问题,尤其是在文件很大的情况下。
问题在于 Spring Data JPA 获取整个实体并使用它们来执行编程映射,根据托尔本·詹森的博客 https://thorben-janssen.com/spring-data-jpa-query-projections/.
除了编写大量查询之外,是否有任何解决方案可以防止在使用基于接口的 DTO 投影时获取整个实体?