深入浅出的加强对 springdata jpa的理解《分页以及高级查询的简单实现》
书接上回,上一篇博客简单的介绍Spring jpa的结构并实现了jpa对数据库的简单增删改查以及 jpa-spec插件
如果有不了解的可以去我上一篇博客看一下
传送门 要学习Java 必须要研究的spring jpa
正文开始
集成spring mvc与springdatajpa
各种配置省略
书写service层
2.2.创建IBaseService
import cn.itsource.pss.domain.Employee;
import cn.itsource.pss.query.BaseQuery;
import org.springframework.data.domain.Page;
import java.io.Serializable;
import java.util.List;
public interface IBaseService<T,ID extends Serializable>{
//添加与修改数据
void save(T t);
//根据id删除一条数据
void delete(ID id);
//根据id查询到一条数据
T findOne(ID id);
//查询所有数据
List<T> findAll();
//根据Query拿到分页对象(分页)
Page findPageByQuery(BaseQuery baseQuery);
//根据Query拿到对应的所有数据(不分页)
List<T> findByQuery(BaseQuery baseQuery);
//根据jpql与对应的参数拿到数据
List findByJpql(String jpql,Object... values);
}
2.3.创建BaseServiceImpl
import cn.itsource.pss.query.BaseQuery;
import cn.itsource.pss.repository.BaseRepository;
import cn.itsource.pss.service.IBaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.List;
import static org.springframework.transaction.annotation.Propagation.SUPPORTS;
@Transactional(readOnly = true,propagation = SUPPORTS)
public class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T,ID>{
//注意:Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用
@Autowired
private BaseRepository<T,ID> baseRepository;
@Override
@Transactional(
public void save(T t) {
baseRepository.save(t);
}
@Override
@Transactional(
public void delete(ID id) {
baseRepository.delete(id);
}
@Override
public T findOne(ID id) {
return baseRepository.findOne(id);
}
@Override
public List<T> findAll() {
return baseRepository.findAll();
}
@Override
public Page findPageByQuery(BaseQuery baseQuery) {
return baseRepository.findPageByQuery(baseQuery);
}
@Override
public List<T> findByQuery(BaseQuery baseQuery) {
return baseRepository.findByQuery(baseQuery);
}
@Override
public List findByJpql(String jpql, Object... values) {
return baseRepository.findByJpql(jpql, values);
}
}
2.4.创建IEmployeeService
import cn.itsource.pss.domain.Employee;
//注:在开发中,业务后期是有很多功能的(不只是我们最简单的CRUD)
public interface IEmployeeService extends IBaseService<Employee,Long> {
}
2.5.创建EmployeeServiceImpl
package cn.itsource.pss.service.impl;
import cn.itsource.pss.domain.Employee;
import cn.itsource.pss.service.IEmployeeService;
import org.springframework.stereotype.Service;
@Service
public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long> implements IEmployeeService {
}
2.6.功能测试
2.6.1.BaseServiceTest
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class BaseServiceTest {
}
2.6.2.EmployeeServiceTest
import cn.itsource.pss.domain.Employee;
import cn.itsource.pss.repository.BaseServiceTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
public class EmployeeServiceTest extends BaseServiceTest {
@Autowired
private IEmployeeService employeeService;
@Test
public void findAll(){
System.out.println(employeeService);
System.out.println(employeeService.getClass());
List<Employee> employees = employeeService.findAll();
for (Employee employee : employees) {
System.out.println(employee);
}
}
@Test
public void save(){
Employee employee = new Employee();
employee.setUsername("用户名称");
employeeService.save(employee);
}
}
上面测试完成后可以进行下一环节
准备jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%@include file="/WEB-INF/views/head.jsp" %>
<script type="text/javascript" src="/js/model/employee.js"></script>
</head>
<body>
<table id="employeeGrid" class="easyui-datagrid" data-options="fit:true,fixed:true,fitColumns:true,toolbar:'#tb',singleSelect:true";
url="/employee/page"
iconCls="icon-save"
rownumbers="true" pagination="true">
<thead>
<tr>
<th width="20" field="username" >用户名</th>
<th width="20" field="password">密码</th>
<th width="20" field="email">邮件</th>
<th width="20" field="age" align="right">年龄</th>
</tr>
</thead>
</table>
</body>
</html>
使用easyui
写一个接口去继承
JpaSpecificationExecutor接口或者使用spec插件写查询方法
具体实现见开头链接
另外使用查询将数据传到页面上可以使用注解@ResponseBody
自动将数据转为json
在前台页面展示出来
这里使用easyui
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%@include file="/utils/head.jsp" %>
<script src="/js/employee.js"></script>
<script>
$(function () {
var searchForm = $("#searchForm");
var employeeGrid = $("#employeeGrid");
//只要a标签中有data-method属性,咱们就给它添加事件
// 执行对应的itsource中的事件
$("a[ck]").on("click",function () {
var method = $(this).attr("ck")
itsource[method]();
})
var itsource={
search:function search() {
var params = searchForm.serializeObject();
employeeGrid.datagrid('load',params);
}
}
})
</script>
<title>Title</title>
</head>
<body>
<div id="tb" style="padding:5px;height:auto">
<div style="margin-bottom:5px">
<a href="#" class="easyui-linkbutton" iconCls="icon-add" plain="true"></a>
<a href="#" class="easyui-linkbutton" iconCls="icon-edit" plain="true"></a>
<a href="#" class="easyui-linkbutton" iconCls="icon-save" plain="true"></a>
<a href="#" class="easyui-linkbutton" iconCls="icon-cut" plain="true"></a>
<a href="#" class="easyui-linkbutton" iconCls="icon-remove" plain="true"></a>
</div>
<div>
<form id="searchForm" action="/employee/pagelist" method="post">
用户名: <input name="username" class="easyui-textbox" style="width:80px">
邮箱: <input name="email" class="easyui-textbox" style="width:80px">
部门:
<input name="department" class="easyui-combobox" style="width:100px"
url="/util/departmentlist"
valueField="id" textField="name">
<a ck="search" class="easyui-linkbutton" iconCls="icon-search">Search</a>
</form>
</div>
</div>
<table id="employeeGrid" class="easyui-datagrid" style="width:100%;"
toolbar='#tb'
data-options="url:'/employee/pagelist',pagination:true,fitColumns:true,singleSelect:true,fit:true ">
<thead>
<tr>
<th data-options="field:'headImage',width:100,formatter:formatImage" >头像</th>
<th data-options="field:'username',width:100">用户名</th>
<th data-options="field:'email',width:100">邮箱</th>
<th data-options="field:'age',width:100,align:'right'">年龄</th>
<th data-options="field:'department',width:100,align:'right' ,formatter:formatdepartment">部门</th>
</tr>
</thead>
</table>
</body>
</html>
高级查询与分页
将前台查询条件传入后台使用上面的查询插件进行处理查找再转为json格式来展示
注意请求的参数名称与后台需要匹配,如果不一致可以对set方法进行包装
如`
//分页用到到的两个方法
public void setPage(Integer currentPage){
this.currentPage = currentPage;
}
//分页用到到的两个方法
public void setRows(Integer pageSize) {
this.pageSize = pageSize;
}
分页代码如下
@Override
public Sort getSort() {
Sort sort = null;
//如果排序字段不为null即排序
if (this.getOrderbyName() != null) {
Pageable pageable = null;
Sort.Direction direction = null;
//判断排序类型
if ("DESC".equalsIgnoreCase(this.getOrderbyType())) {
direction = Sort.Direction.DESC;
} else {
direction = Sort.Direction.ASC;
}
sort = new Sort(direction, this.getOrderbyName());
}
return sort;
}
package cn.itsouce.aisell.repository.Impl;
import cn.itsouce.aisell.query.BaseQuery;
import cn.itsouce.aisell.repository.BaseRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;
/**
* 实现父类中的三个方法
* @param <T>
* @param <ID>
*/
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {
private final EntityManager entityManager;
//必需要实现父类的这个构造器
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager = em;
}
@Override
public Page findPageByQuery(BaseQuery baseQuery) {
//第一步:拿到所有高级查询条件
Specification spec = baseQuery.getSpecifications();
//第二步:拿到排序的值
Sort sort = baseQuery.getSort();
//第三步:根据条件查询分页数据并且返回
Pageable pageable = new PageRequest(baseQuery.getJPACurrent(), baseQuery.getPageSize(),sort);
Page<T> page = super.findAll(spec, pageable);
return page;
}
@Override
public List<T> findByQuery(BaseQuery baseQuery) {
//第一步:拿到所有高级查询条件
Specification spec = baseQuery.getSpecifications();
//第二步:拿到排序的值
Sort sort = baseQuery.getSort();
//第三步:拿到数据返回
return findAll(spec, sort);
}
@Override
public List findByJpql(String jpql, Object... values) {
//第一步:创建Query对象
Query query = entityManager.createQuery(jpql);
//第二步:把值设置到Query对象中去
if (values!=null) {
for (int i = 0; i < values.length; i++) {
query.setParameter(i + 1, values[i]);
}
}
//第三步:返回数据
return query.getResultList();
}
这样我们就很简单的实现了分页与高级查询,后续我还会更新更多的关于spring的知识
欢迎关注持续跟进学习,有问题可以找我解决