hibernate 在Spring中使用实体管理器实现分页

s4n0splo  于 2023-04-06  发布在  Spring
关注(0)|答案(3)|浏览(129)

如何在Spring + hibernate项目中实现分页?下面是代码。我将获得PageRequest对象,我想返回项目的Page

@Repository
    public class ItemRepository {

      @PersistenceContext
      EntityManager entityManager;

      public Page<Item> findItems(PageRequest pageRequest) {
        // TODO: Implement me
        return new Page<>(new ArrayList<>(), 0, 0);
      }
    }

    public class PageRequest {

      private final int count;
      private final int pageNumber;

      public PageRequest(int pageNumber, int count) {
        assert pageNumber >= 0;
        assert count > 0;

        this.pageNumber = pageNumber;
        this.count = count;
      }

      public int getCount() {
        return count;
      }

      public int getPageNumber() {
        return pageNumber;
      }
    }
uidvcgyl

uidvcgyl1#

我找到解决办法了

public Page<Item> findItems(PageRequest pageRequest) {

    Query query = entityManager.createQuery("From Item");
    int pageNumber =pageRequest.getPageNumber();
    int pageSize = pageRequest.getCount();
    query.setFirstResult((pageNumber) * pageSize);
    query.setMaxResults(pageSize);
    List <Item> fooList = query.getResultList();

    Query queryTotal = entityManager.createQuery
            ("Select count(f.id) From Item f");
    long countResult = (long)queryTotal.getSingleResult();
    int i=(int)countResult;
    return new Page<>(fooList, pageRequest.getPageNumber(),i);
  }

我不得不查询两次数据库一次获得记录,然后获得所有的计数

jfgube3f

jfgube3f2#

一种方法是在PageRequest类中添加逻辑,根据Pageable方法参数对传入列表进行“切片”,并将其作为org.springframework.data.domain.PageImpl返回。
下面是一个可以在PageRequest类中使用的静态方法:

public static <E> Page<E> returnPagedList(Pageable pageable, List<E> listOfEntities) {
    List<E> listToReturn = listOfEntities;
    if (pageable.isPaged()) {
        int pageSize = pageable.getPageSize();
        int currentPage = pageable.getPageNumber();
        int startItem = currentPage * pageSize;
        if (listOfEntities.size() < startItem) {
            listToReturn = Collections.emptyList();
        } else {
            int toIndex = Math.min(startItem + pageSize, listOfEntities.size());
            listToReturn = listOfEntities.subList(startItem, toIndex);
        }
    }
    return new PageImpl<>(listToReturn, pageable, listOfEntities.size());
}

然后在你的仓库中,你可以这样做(注意你收到了一个Pageable对象):

public Page<Item> findItems(Pageable pageable) {
   EntityManager em = getEntityManager();
   List<Item> list = ... // get list of all Items
   return PageRequest.pagedList(pageable, list);
    }
  }
roejwanj

roejwanj3#

在使用Spring Data JPA的项目中,您可以非常有效地使用EntityManager实现分页,因为它允许您直接将结果集值Map到DTO,跳过冗余的实体到DTOMap:

@Service
public class ItemService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional(readOnly = true)
    public Page<ItemDTO> getItemsPage(Pageable page) {
        var itemList = entityManager
                .unwrap(Session.class)
                .createNamedQuery("Item.availableItems", Object[].class)
                .setFirstResult(page.getPageNumber() * page.getPageSize())
                .setMaxResults(page.getPageSize())
                .setTupleTransformer((tuples, aliases) -> {
                    var item = new ItemDTO();
                    item.setId((Long) tuples[0]);
                    item.setName((String) tuples[1]);
                    //...
                    return item;
                })
                .getResultList();

        long totalCount = itemList.size() < page.getPageSize()
                ? page.getPageSize()
                : entityManager
                    .createQuery("SELECT count(i) FROM Item i", Long.class)
                    .getSingleResult();

        return new PageImpl<>(itemList, page, totalCount);
    }
}

在本例中,查询在Item实体类中定义:

@NamedQuery(
        name = "Items.availableItems",
        query = "SELECT i.id, i.name FROM Item i"
)
@Entity
@Table(name = "items")
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    // ...
}

这样你就可以很容易地返回分页的结果:

public ResponseEntity<List<ItemDTO>> getAvailableItems(
        @Min(0) @Valid @RequestParam(value = "pageNumber", defaultValue = "0") Integer pageNumber,
        @Min(1) @Valid @RequestParam(value = "pageSize",  defaultValue = "10") Integer pageSize) {
    Page<ItemDTO> items = itemService.getAvailableItemsPage(PageRequest.of(pageNumber, pageSize));
    return ResponseEntity
            .ok()
            .header("x-total-count", String.valueOf(items.getTotalElements()))
            .header("x-page-number", String.valueOf(pageNumber))
            .header("x-page-size", String.valueOf(pageSize))
            .body(items.toList());
}

相关问题