How to issue one query instead of multiple queries for graph of entities

Viewed 470

I have a Spring Data repository where I'm getting all positions for a set of accounts:

public interface PositionRepository extends JpaRepository<Position, PositionKey> {

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

Position has attributes that are also entities (a few nested levels):

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

I'm always returning the full entity graph of positions as serialized JSON to a client. So, I'm always going to need all attributes and nested attributes. The position instances are 350 max.

Despite using @NamedEntityGraph, I noticed that individual queries are still being issued. For example, I get a query for each unique vendor. It usually takes ~2-3 seconds to get the results from all the individual queries.

How can I tell JPA to issue one query with multiple joins? I can manually write this SQL (using multiple joins) and it returns in just a few milliseconds.

Update

The data is accessed as follows:

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

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

When the list of positions is returned, they are serialized via Jackson. So, it's Jackson that actually accesses the data.

0 Answers
Related