如果您使用的是 Spring MyBatis,您可以使用 2 个 MyBatis 查询和有用的 SpringPage
和Pageable
接口手动实现分页。
您创建一个更高级别的DAO
接口,例如UploadDao
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface UploadDao {
Page<Upload> search(UploadSearch uploadSearch, Pageable pageable);
}
...其中Upload
映射到一个upload
表并且UploadSearch
是一个参数 POJO 例如
@Data // lombok
public class UploadSearch {
private Long userId;
private Long projectId;
...
}
UploadDao
(注入 MyBatis映射器)的实现UploadMapper
如下:
public class DefaultUploadDao implements UploadDao {
@Autowired
private UploadMapper uploadMapper;
public Page<Upload> searchUploads(UploadSearch uploadSearch, Pageable pageable) {
List<Upload> content = uploadMapper.searchUploads(uploadSearch, pageable);
Long total = uploadMapper.countUploads(uploadSearch);
return new PageImpl<>(content, pageable, total);
}
}
DAO 实现调用 2 个方法UploadMapper
。这些是:
UploadMapper.searchUploads
- 根据搜索参数 ( UploadSearch
) 和Pageable
参数(包含偏移量/限制等)返回一页结果。
UploadMapper.countUploads
- 返回总计数,再次基于搜索参数UploadSearch
。注意 -Pageable
这里不需要参数,因为我们只是确定搜索参数过滤到的总行数,而不关心页码/偏移量等。
注入的UploadMapper
界面看起来像......
@Mapper
public interface UploadMapper {
List<Upload> searchUploads(
@Param("search") UploadSearch search,
@Param("pageable") Pageable pageable);
long countUploads(
@Param("search") UploadSearch search);
}
...并且包含动态 SQL 的映射器 XML 文件例如upload_mapper.xml
包含...
<mapper namespace="com.yourproduct.UploadMapper">
<select id="searchUploads" resultType="com.yourproduct.Upload">
select u.*
from upload u
<include refid="queryAndCountWhereStatement"/>
<if test="pageable.sort.sorted">
<trim prefix="order by">
<foreach item="order" index="i" collection="pageable.sort" separator=", ">
<if test="order.property == 'id'">id ${order.direction}</if>
<if test="order.property == 'projectId'">project_id ${order.direction}</if>
</foreach>
</trim>
</if>
<if test="pageable.paged">
limit #{pageable.offset}, #{pageable.pageSize}
</if>
<!-- NOTE: PostgreSQL has a slightly different syntax to MySQL i.e.
limit #{pageable.pageSize} offset #{pageable.offset}
-->
</select>
<select id="countUploads" resultType="long">
select count(1)
from upload u
<include refid="queryAndCountWhereStatement"/>
</select>
<sql id="queryAndCountWhereStatement">
<where>
<if test="search != null">
<if test="search.userId != null"> and u.user_id = #{search.userId}</if>
<if test="search.productId != null"> and u.product_id = #{search.productId}</if>
...
</if>
</where>
</sql>
</mapper>
注意 -<sql>
块(连同<include refid=" ... " >
)在这里非常有用,可以确保您count
和select
查询对齐。此外,在排序时,我们使用条件,例如<if test="order.property == 'projectId'">project_id ${order.direction}</if>
映射到列(并停止 SQL 注入)。是安全的${order.direction}
,因为 SpringDirection
类是enum
.
然后UploadDao
可以从例如 Spring 控制器注入和使用:
@RestController("/upload")
public UploadController {
@Autowired
private UploadDao uploadDao; // Likely you'll have a service instead (which injects DAO) - here for brevity
@GetMapping
public Page<Upload>search (@RequestBody UploadSearch search, Pageable pageable) {
return uploadDao.search(search, pageable);
}
}