首页 > 解决方案 > 如何针对实体图发出一个查询而不是多个查询

问题描述

我有一个 Spring Data 存储库,我在其中获取一组帐户的所有职位:

public interface PositionRepository extends JpaRepository<Position, PositionKey> {

    @EntityGraph(value = "Position.all", type = EntityGraphType.LOAD)
    List<Position> findByAccountIn(Set<Account> accounts);
    
}

Position具有也是实体的属性(一些嵌套级别):

@Entity
@NamedEntityGraph(name = "Position.all",
attributeNodes = {@NamedAttributeNode("account", subgraph = "Account.all"),
    @NamedAttributeNode("product", subgraph = "Product.all")
})

@Data
public class Position {

    @EmbeddedId
    private PositionKey positionKey; 

    @MapsId("accountId")
    @ManyToOne
    @JoinColumn(name = "accountId")
    private Account account;
    
    @MapsId("productId")
    @ManyToOne
    @JoinColumn(name = "productId")
    private Product product;           
}

@Embeddable
@Data
public class PositionKey implements Serializable {

    @Column(name = "accountId")
    private Long accountId;
    
    @Column(name = "productId")
    private Long productId;
}


@Entity
@NamedEntityGraph(includeAllAttributes = true, name = "Product.all",
    attributeNodes = {@NamedAttributeNode(value = "vendor", subgraph = "Vendor.all"),
                      @NamedAttributeNode(value = "type", subgraph = "ProductType.all")}
)
@Data
public class Product {

    @Id
    @Column(name = "id")
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "typeId")
    private ProductType type;
    
    @ManyToOne
    @JoinColumn(name = "vendorCode")
    private Vendor vendor;
    
}

@Entity
@NamedEntityGraph(name = "Account.all")
@Data
public class Account {

    @Id
    @Column(name = "accountId")
    private Long id;
    
}

我总是将位置的完整实体图作为序列化的 JSON 返回给客户端。所以,我总是需要所有属性和嵌套属性。位置实例最多为 350 个。

尽管使用@NamedEntityGraph了 ,但我注意到仍在发出个别查询。例如,我获取每个唯一供应商的查询。从所有单个查询中获取结果通常需要大约 2-3 秒。

如何告诉 JPA 发出一个带有多个连接的查询?我可以手动编写这个 SQL(使用多个连接),它会在几毫秒内返回。

更新

数据访问如下:

@RestController
@RequestMapping("/position")
@RequiredArgsConstructor
public class PositionController {

    private final PositionRepository positionRepo;
    
    @GetMapping
    public List<Position> getAllPositions(Set<Account> accounts) {
        return positionRepo.findByAccountIn(account);
    }
    
}

当位置列表返回时,它们通过 Jackson 序列化。因此,实际访问数据的是杰克逊。

标签: javaspringhibernatejpaspring-data-jpa

解决方案


推荐阅读