要完成的功能
- 父类的抽取
- 删除功能
- 查询功能
在我们完成这些功能之前 我们还需要做的一件事就是 就是给每一层抽取一个父类
那为什么要抽取一个父类呢
抽取父类有利于我们以后扩展代码 也就是扩展性强。还有就是做相应的规范,哪怕父类一句代码都没有也要写一个父类
父类的抽取
domain的父类抽取
/**
* 泛化(继承) -> 父类
* 告诉JPA,这是一个domain的父类(继承的时候才会用到字段)
* 这个注解不会持久化到表
*/
@MappedSuperclass
public class BaseDomain {
@Id
@GeneratedValue
protected Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
query的父类抽取
public abstract class BaseQuery {
//当前页
private int currentPage = 1;
//每页条数
private int pageSize = 10;
//排序字段名字(如果这个值不存在,就不排序)
private String orderName;
//排序规则 true:升序 false:降序
private boolean orderType = true;
//这里加一个抽象方法,可以保证子类都去实现
public abstract Specification createSpec();
//创建排序对象
public Sort createSort() {
//1.只有orderName不为空,才进行排序
if (StringUtils.isNotBlank(orderName)) {
Sort sort = new Sort(orderType ? Sort.Direction.ASC : Sort.Direction.DESC, orderName);
return sort;
}
return null;
}
public int getCurrentPage() {
return currentPage;
}
//专门为SpringDataJpa的分页(从0开始)
public int getJpaPage() {
return currentPage - 1;
}
由于我们还要集成EasyUI 所以还需要添加一下两个方法
//兼容EasyUI的当前页数据
public void setPage(int page) {
this.currentPage = page;
}
//兼容EasyUI的每页条数
public void setRows(int rows) {
this.pageSize = rows;
}
Repository的父类抽取
/**
* JPA里面,它的domain的id,都必需是实现序列化接口
* 这个BaseRepository是一个父类(无法确定类型的)
* @param <T>
* @param <ID>
* @NoRepositoryBean:告诉Spring,不要去实现这个接口(原因是spring会去实现这个父接口 所以)
*/
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable>
extends JpaRepository<T,ID>, JpaSpecificationExecutor<T> {
}
service的父类抽取
先抽取service的父类接口
/**
* 业务层的父类
* 传一个范型 用来之类具体接收要操作的domain
* 后面的id是继承序列化
*/
public interface IBaseService<T,ID extends Serializable> {
//添加与修改是同一个
void save(T t);
void delete(ID id);
T findOne(ID id);
List<T> findAll();
//1.根据查询条件查找对应的数据
List<T> queryAll(BaseQuery query);
//2.根据查询条件查找到对应的分页数据
Page<T> queryPage(BaseQuery query);
//3.根据JPQL进行查询
/**
* select o.username from Employee o where o.username like ? and o.email like ? ..
*/
List<Object> queryByJpql(String jpql,Object... params);
接着抽取service的实现父类
/**
* 父类的实现类
* @Transactional 事务的注解 以后还是查询多
*
* @param <T>
* @param <ID>
*/
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public abstract class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T, ID > {
//注入父类的dao 实际上是所有子接口的实现
@Autowired
private BaseRepository<T,ID > baseRepository;
/**
* 为了解决扩展的JPQL 因为baseRepository 是没有这个功能的
*
*/
@PersistenceContext
private EntityManager entityManager;
//添加或者修改
@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 List<T> queryAll(BaseQuery query) {
// 拿到排序
Sort sort = query.createSort();
//拿到查询规则
Specification spec = query.createSpec();
//进行查询
List<T> list = baseRepository.findAll(spec, sort);
return list;
}
//分页查询
@Override
public Page<T> queryPage(BaseQuery query) {
//拿到排序和分页
Sort sort = query.createSort();
Pageable pageable = new PageRequest(query.getJpaPage(),query.getPageSize(),sort);
//拿到查询规则
Specification spec = query.createSpec();
//查询数据
Page<T> page = baseRepository.findAll(spec, pageable);
return page;
}
//解决特殊的查询 自己写JQPL
@Override
public List<Object> queryByJpql(String jpql, Object... params) {
//这里应该是拿到query 对象
Query query = entityManager.createQuery(jpql);
//然后把数据放到query 中
for (int i = 0;i<params.length;i++){
query.setParameter(i+1, params[i]);
}
//返回结果集
return query.getResultList();
}
}
最后就是controller的父类抽取
这个里面就是一句代码都没有
public class BaseController {
}
总结父类抽取
当我们把每个层的父类抽取好以后 我们后面实现功能就很快了 那简直就是一帆风顺呀!只需要继承父类就好!
删除功能的完成
集成前台页面
我们把所有公共的引入(css,js) 都放在head.jsp中
以后要使用easyui直接引入即可
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入easyui中的基本的CSS与JS--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<%--图标样式--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
<%--支持风格的包--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/color.css">
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<%--引入国际化的js--%>
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
employee的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--引入公共的jsp--%>
<%@ include file="/WEB-INF/views/head.jsp" %>
<%--引入当前模板对应的js--%>
<script src="/js/model/employee.js"></script>
</head>
<body>
<div id="toolbar">
<%--iconCls:图标 plain:简洁--%>
<a href="javascript:;" data-method="add" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true">添加</a>
<a href="javascript:;" data-method="update" class="easyui-linkbutton" data-options="iconCls:'icon-edit',plain:true">修改</a>
<a href="javascript:;" data-method="delete" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true">删除</a>
</div>
<%--展示数据使用datagrid组件
url:请求路径(数据) fit:自适应父容器
fitColumns:列的自适应 singleSelect:是否单选
pagination:分页工具栏
ctrl+shift+delete
--%>
<table class="easyui-datagrid"
data-options="url:'/employee/page',fitColumns:true,singleSelect:true,fit:true,toolbar:'#toolbar',pagination:true">
<thead>
<tr>
<th data-options="field:'username',width:100">用户名</th>
<th data-options="field:'password',width:100">密码</th>
<th data-options="field:'age',width:100">年龄</th>
<th data-options="field:'email',width:100">邮箱</th>
</tr>
</thead>
</table>
</body>
</html>
employee的js
我们一个模块需要一个功能 所有需要单独建与之对应的js
这里只是集成相关的js 也就是相当于一个模板 然后要完成相应的功能直接写就好
//入口函数:页面读取所有元素再执行
$(function () {
//只要有data-method属性的元素我都要为它注册事件
$("*[data-method]").on("click",function () {
//谁调用,this就指向谁(这个this是普通dom对象)
//$(dom对象) -> 变成jQuery对象,有很多jQuery特有的功能(更加强大)
//console.debug($(this));
//1.拿到当前按键的属性 add,update
//var methodName = $(this).attr("data-method");
//var methodName = $(this).data("method");
//2.执行对应的方法(动态调用)
// itsource.say() == itsource["say"]();
itsource[$(this).data("method")]();
})
//准备了相应的方法功能
itsource = {
add:function(){
alert("add")
},
update:function () {
alert("update")
},
delete:function () {
//1.拿到你选择的那一条数据 (easyui的datagrid中有这个功能)
//2.如果没有拿到数据,给一个提示,让他选中再执行(后面的代码就不运行) Messager alert
//3.如果拿到数据,给一个提示,是否要删除? Messager confirm
//4.如果要删除 -> 发送Ajax请求到后台进行数据删除 $.get/post("/employee/delete",{id:2},function(){....})
// 后台会返回相应的数据 :{success:true/false,msg:xxx}
// 如果成功,刷新datagrid
}
};
})
EmployeeController提供删除功能
/**
* 前台会传一个id过来
* 需要返回:{success:true/false,msg:"xx"}
* 返回这种结构有两种方法:1种是写map, 1种是直接返回对象
*/
@RequestMapping("/delete")
@ResponseBody
public JsonResult delete(Long id){
try {
employeeService.delete(id);
return new JsonResult();
} catch (Exception e) {
e.printStackTrace();
//失败后返回的结果
return new JsonResult(false,e.getMessage());
}
}
employee.js完成删除
delete () {
//1.拿到你选择的那一条数据 (easyui的datagrid中有这个功能)
// row就是你选择的这一行的数据
var row = employeeDataGrid.datagrid("getSelected");
//2.如果没有拿到数据,给一个提示,让他选中再执行(后面的代码就不运行) Messager alert
if(row==null){
//alert("没有货,滚蛋!"); //不建议使用 1.不同浏览器效果不一样 2.它会阻塞进程
$.messager.alert('警告','没有货,滚蛋!',"info");
return;
}
//3.如果拿到数据,给一个提示,是否要删除? Messager confirm
$.messager.confirm('确认','您要狠心的干掉我嘛?',function(r){
if (r){
//4.如果要删除 -> 发送Ajax请求到后台进行数据删除 $.get/post("/employee/delete",{id:2},function(){....})
// 后台会返回相应的数据 :{success:true/false,msg:xxx}
// 如果成功,刷新datagrid
$.get("/employee/delete",{id:row.id},function (result) {
if(result.success){
//删除成功,刷新datagrid
employeeDataGrid.datagrid("reload");
}else{
//删除失败,给出失败提示
$.messager.alert('失败','删除没有成功,原因是:'+result.msg,"error");
}
})
}
});
},
总结
今天的重点就是父类的是抽取!为啥这样说呢!在我们以往写代码都养成了一种惯性的思维,几乎就不会想到每个层去抽取父类。所以 这是一种代码思维的转变,需要好好的理解一番!