【问题标题】:Spring Data Projection loads additional FieldsSpring Data Projection 加载额外的字段
【发布时间】:2019-05-15 22:03:09
【问题描述】:

我有一个小问题。 假设我有这个实体:

import lombok.Data;
import javax.persistence.*;
import java.util.Set;

@Data
@Entity
public class Person {

    enum SEX {F, M}

    @Id
    @GeneratedValue
    private Long id;

    @OrderBy
    @Enumerated(EnumType.STRING)
    @ElementCollection(fetch = FetchType.EAGER)
    private Set<SEX> sexes;

    private String firstName;
    private String lastName;
}

因为在某些时候我不想加载名字和姓氏,所以我使用 Projections (https://docs.spring.io/spring-data/jpa/docs/1.10.2.RELEASE/reference/html/#projections): 我定义了这个接口:

import java.util.Set;

public interface PersonSlim {

    String getId();
    Set<Person.SEX> getSexes();
}

现在看看这个存储库:

import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface PersonRepo extends CrudRepository<Person, Long> {

    List<PersonSlim> getAllBy();
}

如果您启用 SQL 日志记录 (logging.level.org.hibernate.SQL: DEBUG) 并执行调用 personRepo.getAllBy();,您将看到:

2018-12-14 16:36:36.808 DEBUG 14227 --- [           main] org.hibernate.SQL                        : select person0_.id as id1_0_, person0_.first_name as first_na2_0_, person0_.last_name as last_nam3_0_ from person person0_

所以基本上,Spring 会加载所有字段。如果在 PersonSlim 接口中排除 getSexes() 方法,Spring 只会加载 id:

2018-12-14 16:38:03.977 DEBUG 14382 --- [           main] org.hibernate.SQL                        : select person0_.id as col_0_0_ from person person0_

如果我的投影包含 ElementCollection,则 Spring 会加载所有字段。

为什么会有这样的问题?
我使用带有几何字段的 PostGIS-DB,几何可能非常大。因此,如果我加载许多实体,它会变得很慢。在某些情况下,我不想加载此字段。

【问题讨论】:

    标签: java spring spring-data-jpa spring-data


    【解决方案1】:

    似乎当投影包含非原始类型时,所有列都会包含在查询中。

    这里已经有问题了https://jira.spring.io/browse/DATAJPA-1218 ,从这个问题上听起来,目前还无法通过预测来解决。

    这对你很有用https://github.com/Blazebit/blaze-persistence ,记录在这里Entity Views

    它使用与投影类似的实现。

    【讨论】:

      【解决方案2】:

      在这样的上下文中,我会选择创建一个单独的实体,它包含我关心的所有字段,而不是依赖于投影,因为没有默认的保证投影对象将只返回投影中您想要的字段。

      相信它在实际对象本身上添加了一层抽象,因为它可能检索所有列,但仅暴露 一把。

      鉴于实体驱动查询大部分部分,创建一个单独的实体仅拉回您想要的列可能是最方便的方法。当您想在一两个地方使用完全水合的实体时,这也将引导您远离投射到 Person 的诱惑。

      【讨论】:

        猜你喜欢
        • 2017-03-04
        • 2018-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-14
        • 1970-01-01
        • 2016-10-16
        • 2018-11-25
        • 1970-01-01
        相关资源
        最近更新 更多