1,Dao创建父类,创建BaseRepsitory
@NoRepositoryBean:让Spring管理的时候不要为它创建实现
注意泛型:源代码咋写的,就咋写,这接口用来做扩展的,兼容
/**
* 公共的父Repository
* @param <T>
* @param <ID>
*/
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
}
2,service层
①,IBaseService:父接口,扩展功能
/**
- Service的父接口(所有service都有CRUD)
*/
public interface IBaseService<T, ID extends Serializable> {
//添加或者修改
void save(T t);
//删除
/**
* 联合主键
* 在JPA中,要求主键必需实现Serializable接口
* @param id
*/
void delete(ID id);
//根据id查询一条数据
T findOne(ID id);
//查询所有数据
List<T> findAll();
//1.根据查询条件(query对象)查询对应的数据
List<T> queryAll(BaseQuery query);
//2.根据查询条件(query对象)查询对应的分页(排序)数据
Page<T> queryPage(BaseQuery query);
//3.根据JPQL进行查询
/**
*
* @param jpql select o.username,o.age from ... where username like ? and email like ?
* @param params
* @return
*/
List findByJpql(String jpql,Object... params);
}
②,BaseServiceImpl:父实现
/**
* 抽象的类是无法创建对象的(只能做父类)
* 实现类无法确定接口中泛型的类型
* @param <T>
* @param <ID>
*/
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public abstract class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T,ID> {
/**
* Spring会把相应的BaseRepository<T,ID>实现对象注入进来
* BaseRepository -> EmployeeRepository<Employee,Long>
* DepartmentRepository<Department,Long>
* RoleRepository<Role,Long>
* 我们怎么确定注入的是哪一个对象呢? -> 当用的时候自然就知道了!!
* EmployeeServiceImpl extends BaseServiceImpl<Employee,Long>
* new EmployeeServiceImpl().save();
*/
@Autowired
private BaseRepository<T,ID> 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();
}
//根据查询条件(query对象)查询对应的数据
@Override
public List<T> queryAll(BaseQuery query) {
//1.拿到规则
Specification spec = query.createSpec();
//2.根据规则进行查询
return baseRepository.findAll(spec);
}
//根据查询条件(query对象)查询对应的分页数据
@Override
public Page<T> queryPage(BaseQuery query) {
//1.拿到规则
Specification spec = query.createSpec();
//2.拿到排序对象
Sort sort = query.createSort();
//3.拿到分页对象
Pageable pageable = new PageRequest(query.getJpaPage(),query.getPageSize(),sort);
//4.返回分页对象
return baseRepository.findAll(spec,pageable);
}
//执行jpql,就必需要EntityManager对象
/**
* @param jpql select o.username,o.age from ... where username like ? and email like ?
* @param params 对应的是?的值 -> 可变参数就是数组
* @return
*/
@Override
public List findByJpql(String jpql, Object... params) {
//1.获取query对象
Query query = entityManager.createQuery(jpql);
//2.循环params参数(对应的是?的值)
for (int i = 0; i < params.length; i++) {
//这里设置值是从1开始的
query.setParameter(i+1,params[i]);
}
//3.返回数据
return query.getResultList();
}
}
③,IEmployeeService
/**
* 现在没有代码,不代表以后没有!以后会有一些关于员工的特有的功能,IBaseService<Employee,Long>子类确定类型参数
*/
public interface IEmployeeService extends IBaseService<Employee,Long> {
}
④,EmployeeServiceImpl
@Service
public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long>
implements IEmployeeService {
}
3,SpringMVC的集成
①applicationContext-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!--1.扫描相应的web层-->
<context:component-scan base-package="cn.itsource.aisell.web" />
<!--2.静态资源放行-->
<mvc:default-servlet-handler />
<!--3.mvc的注解支持-->
<mvc:annotation-driven />
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!--5.上传解析器 CommonsMultipartResolver-->
<!-- 注意:上传解析器的id必需:multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>10485760</value>
</property>
</bean>
</beans>
②web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<!--SpringMVC的配置和Spring的配置要单独读取,否则后面集成其它框架会出问题-->
<!--运行与读取spring的配置-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置mvc的核心控制器-->
<servlet>
<servlet-name>dispatchServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--读取mvc配置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!--tomcat启动用创建-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatchServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--编码过滤-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
③UIPage
由于我们前面要集成Easyui,返回的是不是easyui的想要的分页格式,所以,没有数据,
有两种方式:Map集合键值对形式,put(“total”,获取条数)put(“rows”,获取每页行数)
Easyui在分页时想要的数据结构{total:xx,rows:[…]}
准备UIPage来匹配这个结构
public class UIPage<T> {
private Long total; //总条数
private List<T> rows; //每页数据
public UIPage(Page page) {
this.total = page.getTotalElements();
this.rows = page.getContent();
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
④Controller
@Controller
@RequestMapping("/employee")
public class EmployeeController extends BaseController {
@Autowired
private IEmployeeService employeeService;
@RequestMapping("/index")
public String index(){
return "employee/index";
}
@RequestMapping("/findAll")
@ResponseBody
public List<Employee> findAll(){
return employeeService.findAll();
}
/**
* 准备分页方法
* @param query
* @return
*/
@RequestMapping("/page")
@ResponseBody
public UIPage page(EmployeeQuery query){
//return employeeService.queryPage(query);
return new UIPage(employeeService.queryPage(query));
}
}
4,EasyUI的集成
准备head.jsp
我们把所有公共的引入(css,js) 都放在head.jsp中
以后要使用easyui直接引入即可
```javascript
<%@ 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>
3.2 employee的jsp代码
```javascript
<%@ 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>
3.2 employee.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
}
};
})
5,高级查询
① ,准备分页条 pagination:true
<table class="easyui-datagrid" id="employeeDataGrid"
data-options="... pagination:true">
②,后台返回分页数据
需要返回的结构:{total:23,rows:[...]}
准备相应的UIPage类
public class UIPage<T> {
private Long total; //总条数
private List<T> rows; //每页数据
public UIPage(Page page) {
total = page.getTotalElements();
rows = page.getContent();
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
EmployeeController中添加返回UIPage的方法
/**
* 准备分页方法
* @param query
* @return
*/
@RequestMapping("/page")
@ResponseBody
public UIPage page(EmployeeQuery query){
//return employeeService.queryPage(query);
return new UIPage(employeeService.queryPage(query));
}
③,后台接收分页数据
我们必需保证前台传的数据(当前页与每页条数)和咱们后台的
Query中的名称相同 BaseQuery中做修改
//兼容easyui的分页 ctrl+f9
public void setPage(int currentPage) {
this.currentPage = currentPage;
}
public void setRows(int pageSize) {
this.pageSize = pageSize;
}