Spring Boot — разбивка на страницы для отношений «Многие ко многим» с дополнительным столбцом

#java #spring #hibernate #jpa

#java #spring #переход в спящий режим #jpa

Вопрос:

Я не могу найти чистый и простой способ разбиения на страницы при использовании отношения «многие ко многим» с дополнительным столбцом.

Моя модель выглядит так:

У меня есть пользователь и модель продукта. Каждый пользователь может использовать n продуктов. Каждое потребление будет сохранено в дополнительной таблице, потому что я хочу сохранить дополнительную информацию, такую как дата и т.д. Я реализовал модель следующим образом, и она работает, но я хочу получать данные о потреблении пользователем в виде страницы, а не извлекать весь набор. Каков был бы наилучший способ реализовать это?

 @Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(
            mappedBy = "user",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Consumption> consumptionList = new ArrayList<>(); // never set this attribute

    public List<Consumption> getConsumptionList() {
        return consumptionList;
    }


    public void addConsumption(Product product) {
        Consumption consumption = new Consumption(this, product);
        consumptionList.add(consumption);
        product.getConsumptionList().add(consumption);
    }

    public void removeConsumption(Consumption consumption) {
        consumption.getProduct().getConsumptionList().remove(consumption);
        consumptionList.remove(consumption);
        consumption.setUser(null);
        consumption.setProduct(null);
    }
}
  

 @Entity
@NaturalIdCache
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(
            mappedBy = "product",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Consumption> consumptionList = new ArrayList<>();

    public List<Consumption> getConsumptionList() {
        return consumptionList;
    }
}
  

Это мой класс для хранения потребляемых данных.

 @Entity
public class Consumption {

    @EmbeddedId
    private UserProductId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("userId")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("productId")
    private Product product;

    public Consumption(User user, Product product) {
        this.user = user;
        this.product = product;
        this.id = new UserProductId(user.getId(), product.getId());
    }

}
  

И это мой составной первичный ключ, который.

 @Embeddable
public class UserProductId implements Serializable {

    @Column(name = "user_id")
    private Long userId;

    @Column(name = "product_id")
    private Long productId;

    private UserProductId() {
    }

    public UserProductId(Long userId, Long productId) {
        this.userId = userId;
        this.productId = productId;
    }

}
  

Я хотел бы иметь возможность вызывать такой метод, как «getConsumptionList (страница страницы)», который затем возвращает постраничный.

Я надеюсь, вы сможете мне помочь!

Заранее благодарю вас!

Комментарии:

1. Разве getConsumptionList() метод не должен содержать Pageable объект в качестве параметра и возвращать Page как в public Page<Consumption> getConsumptionList(Pageable pageable) ?

2. Тогда мне пришлось бы самому реализовать разбивку на страницы в классе model, верно? Невозможно просто реализовать метод интерфейса в репозитории pagingandsorting?

Ответ №1:

Что ж, при использовании Spring Boot вы могли бы использовать репозиторий:

 @Repository
public interface ConsumptionRepo extends JpaRepository<Consumption, Long>{
    List<Consumption> findByUser(User user, Pageable pageable);
}
  

Тогда вы можете просто вызвать это

 ConsumptionRepo.findByUser(user, PageRequest.of(page, size);
  

Ответ №2:

Я, наконец, нашел решение своей проблемы благодаря @mtshaikh idea:

Просто реализуйте Paginationservice:

 public Page<Consumption> getConsumptionListPaginated(Pageable pageable) {
        int pageSize = pageable.getPageSize();
        int currentPage = pageable.getPageNumber();
        int startItem = currentPage * pageSize;

        List<Consumption> list;

        if (consumptionList.size() < startItem) {
            list = Collections.emptyList();
        } else {
            int toIndex = Math.min(startItem   pageSize, consumptionList.size());
            list = consumptionList.subList(startItem, toIndex);
        }

        return new PageImpl<>(list, PageRequest.of(currentPage, pageSize), consumptionList.size());

    }
  

Комментарии:

1. Но, тем не менее, он перечисляет все, а затем отправляет подсписок. Нам нужно запретить им вызывать alll