Spring -data-jpa eager fetch с соединением и использованием разбивки на страницы не работает

Я новичок в спящем режиме и Spring -data-jpa. Все, что я хотел сделать, - это получить сущность и все связанные с ней объекты с использованием разбивки на страницы (существует около 40 миллионов записей). Один из запросов, позволяющий получать как корневые объекты, так и все их сопоставленные объекты/сбор = 1 запрос

Но у меня есть проблема (n + 1): один запрос для корневых сущностей + один запрос для связанной сопоставленной сущности/коллекции каждого корневого объекта = (n + 1) запросов Это действительно влияет на производительность.

Я также хотел бы знать, правильны ли мои отображения в объектах.

Может кто-нибудь, пожалуйста, проведет меня. Благодаря

Стек приложения:

<java-version>1.7</java-version>
<spring.framework.version>4.0.2.RELEASE</spring.framework.version>
<hibernate-core>4.3.4.Final</hibernate-core>
<hibernate-validator>5.1.0.Final</hibernate-validator>
<hibernate-entitymanager>4.3.4.Final</hibernate-entitymanager>
<spring-data-jpa>1.5.1.RELEASE</spring-data-jpa>

У меня есть 2 класса сущностей (Customer and Order):

Объект клиента

@Entity
@Table(name = "view_customerOrders_to_process") 
public class Customer implements Serializable {

private Long id;
private List<Order> Orders;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "customer_id", updatable = false)
public Long getId() {
   return id;
}

........

@NotFound(action = NotFoundAction.IGNORE)
@OneToMany(fetch = FetchType.EAGER, mappedBy = "customer") 
//Do not cascade any changes to child entities.
@Where(clause = "order_status = 'PENDING'")
public List<Order> getOrders() {
    return order;
}
}

Пробовал использовать batchSize, но по какой-то причине его не работает (такая же проблема n + 1).
  // @Fetch(FetchMode.SELECT)
  // @BatchSize (размер = 25)

Объект заказа:

@Table(name = "tbl_orders") 
public class Order implements Serializable {

    private Long id;
    private int customerId;    
    private Customer customer;
    private OrderType orderType;

    ..........

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "order_id", updatable = false)
    public Long getId() {
        return this.id;
    }

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "order_type", nullable = true, unique = false, updatable = false)
    public OrderType getOrderType() {
        return this.orderType;
    }

    @NotFound(action = NotFoundAction.IGNORE)
    @ManyToOne(fetch = FetchType.LAZY, optional = true, targetEntity = Customer.class)
    @Fetch(FetchMode.JOIN)
    @JoinColumns({
        @JoinColumn(updatable = false, insertable = false,
            name="customer_id", referencedColumnName = "customer_id", nullable=false),
      . . . . .
    })
    public Customer getCustomer() {
        return customer;
    }
}

Класс обслуживания:

@Service
public class MetsGeneratorService {

    . . .

    @Autowired
    private CustomerRepository customerRepository;

    public List<Customer> run() {
        PageRequest pageRequest = new PageRequest(0, batchSize);        
        List<Customer> customers = customerRepository.findOrdersUnprocessed(pageRequest);
        return customers;
    }

    . . .
}

Repository:

public interface CustomerRepository extends JpaRepository<Customer, Long> {

    @Query("SELECT e FROM Customer e")
    List<Customer> findOrdersUnprocessed(Pageable pageable);

    //Tried using the below one which seems to eliminate paging
    //and understandably getting out of memory.
    //@Query(value = "SELECT e FROM Customer e left join fetch e.orders")       

}

Попробовал перейти на

@Query(value = "SELECT e FROM Customer e left join fetch e.orders",
        countQuery = "select count(e) from Customer e")
List<Customer> findOrdersUnprocessed(Pageable pageable);

если вы видите, что он обрабатывает журнал, делая "select *" вместо пейджинга.

Сообщение журнала WARN org.hibernate.hql.internal.ast.QueryTranslatorImpl - HHH000104: firstResult/maxResults, указанные с помощью коллекции; применение в памяти!

Ответ 1

Вы можете использовать

@Fetch(FetchMode.SUBSELECT)

чтобы удалить (n + 1) проблему запроса.