【问题标题】:Spring JPA EntityGraph fetches all lazy loaded propertiesSpring JPA EntityGraph 获取所有延迟加载的属性
【发布时间】:2018-02-06 04:33:42
【问题描述】:

我使用过 Spring 和 Hibernate。现在看看 Spring Data JPA (2.0.3) 和 JPA 2.2

AgencyTicketType

@Entity
@Table(name = "agency_ticket_type", catalog = "test")
public class AgencyTicketType implements java.io.Serializable {
   private Long id;
   private String name;
   private Agency agency;
   private Set<AgencyTicketCategory> agencyTicketCategories = new HashSet<AgencyTicketCategory>(0);

   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Long getId() {
     return this.id;
   }
   public void setId(Long id) {
    this.id = id;
   }
   @Column(name = "name", nullable = false, length = 100)
   public String getName() {
    return this.name;
   }
   public void setName(String name) {
    this.name = name;
   }
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "agency_id", nullable = false)
   public Agency getAgency() {
     return this.agency;
   }
   public void setAgency(Agency agency) {
     this.agency = agency;
   }
   @OneToMany(fetch = FetchType.LAZY, mappedBy = "agencyTicketType")
   public Set<AgencyTicketCategory> getAgencyTicketCategories() {
      return this.agencyTicketCategories;
   }
   public void setAgencyTicketCategories(Set<AgencyTicketCategory> agencyTicketCategories) {
      this.agencyTicketCategories = agencyTicketCategories;
   }
}

AgencyTicketCategory

@Entity
@Table(name = "agency_ticket_category", catalog = "waytest")
public class AgencyTicketCategory implements java.io.Serializable {
    private Long id;
    private AgencyTicketType agencyTicketType;
    private String name;
    private BigDecimal price;
    private Set<TripTicket> tripTickets = new HashSet<TripTicket>(0);

    @Id
    @GeneratedValue(strategy = IDENTITY)

    @Column(name = "id", unique = true, nullable = false)
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "agency_ticket_type_id", nullable = false)
    public AgencyTicketType getAgencyTicketType() {
        return this.agencyTicketType;
    }
    public void setAgencyTicketType(AgencyTicketType agencyTicketType) {
        this.agencyTicketType = agencyTicketType;
    }
    @Column(name = "name", nullable = false, length = 100)
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Column(name = "price", nullable = false, precision = 8)
    public BigDecimal getPrice() {
        return this.price;
    }
    public void setPrice(BigDecimal price) {
        this.price = price;
    }
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "agencyTicketCategory")
    public Set<TripTicket> getTripTickets() {
        return this.tripTickets;
    }
    public void setTripTickets(Set<TripTicket> tripTickets) {
        this.tripTickets = tripTickets;
    }
}

存储库

public interface TicketTypeRepository extends JpaRepository<AgencyTicketType, Long> {

  @EntityGraph(attributePaths={ "agencyTicketCategories" }, type=EntityGraphType.LOAD)
  @Query("select type from AgencyTicketType type where type.agency.code=?1")
  List<AgencyTicketType> findByAgency(String agencyCode);
}

服务

@Service
public class TicketServiceImpl implements TicketService {       
    @Autowired private TicketTypeRepository ticketType;

    @Transactional(readOnly=true)
    @Override
    public List<AgencyTicketType> findByName(String code) {
        return ticketType.findByAgency(code);
    }    
}

在服务上调试时,查询似乎急切地获取所有延迟加载的属性 - 代理、代理TicketCategories - 以及所有内部延迟加载的属性,这会导致 JSON 序列化错误。

只需要获取这些

AgencyTicketTypes [
                   {
                     id, name,
                     agencyTicketCategories [
                                              {id,name,price},....
                                            ]
                   },.....    
                 ]

我可以用@EntityGraph 做到这一点吗?我错过了什么?

【问题讨论】:

    标签: spring jpa spring-data-jpa entitygraph jpa-2.2


    【解决方案1】:

    指定延迟加载只是对 JPA 提供者的提示。根据您使用的提供程序(Hibernate、EclipseLink 等),它可能会被完全忽略,并且可能会急切地获取依赖项。

    您需要做的是配置您的类如何映射到 json。假设您使用的是 Jackson,您可能需要使用 @JsonIgnore@JsonView 之类的注释。您还可以映射仅包含您需要的字段的类。

    【讨论】:

    • 我使用 Hibernate 作为提供者。在模型类中使用@JsonIgnore 会使其始终不可用,对吧?
    【解决方案2】:

    您可以使用 Jackson 注释 @JsonBackReference/@JsonManagedReference。它们解决了对象模型中具有双向链接的无限递归问题。据我了解,这是你的情况。

    更多信息请参见http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

    【讨论】:

    • 感谢@AntonyTupy 主要问题是它从数据库而不是杰克逊序列化中获取不必要的数据
    • 在这种情况下,\@JsonView 适合你,正如@Apokralipsa 所写
    【解决方案3】:

    要指出的一点是,在事务打开时进行调试(触摸集合)会导致它被加载,即使它不会实时加载.. 另一件事是,正如@Apokralipsa 提到的那样,延迟加载是只是一个可以完全忽略的提示,不应该依赖于您使用的任何技术

    【讨论】:

    • 您对“触摸收藏”的评论对我来说是新的。会调查它,如果这是我的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 2013-05-21
    • 2013-11-02
    • 2022-09-29
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多