@Transactional
public void save(T entity) {
baseDAO.save(entity);
}
//根据实体类删除
public void delete(T entity) {
baseDAO.delete(entity);
}
//根据id查询
@Transactional
public void deleteById(ID id) {
baseDAO.deleteById(id);
}
//排序查询所有
public List findAll(Sort sort){
return baseDAO.findAll(sort);
}
//动态条件查询
public List findAll(Specification spec){
return baseDAO.findAll(spec);
}
//分页查询
public Page findAll(Pageable pageable){
return baseDAO.findAll(pageable);
}
//动态条件分页查询
public Page findAll(Specification spec, Pageable pageable){
return baseDAO.findAll(spec,pageable);
}
//动态条件排序查询
public List findAll(Specification spec, Sort sort){
return baseDAO.findAll(spec,sort);
}
}
最后就是控制器的封装了,控制器需要先通过反射机制的工具类GenericsUtils,找到对应的实体类。之后封装一下常用的方法。不同于上面两个类的是,他有三个泛型接口,除了实体类和ID的类型外,他还有一个BaseForm类,BaseForm为公共的Form类,该类中就一个id和一个查询条件。因为这里写数据保存方法的数据接收是很使用的Form接收的,使用Form里边的ID是判断是修改还是新增方法(修改和新增用的一个方法,用id是否为null区分),BaseForm类代码如下。
public class BaseForm {
private ID id;
private String search;
public ID getId() {
return id;
}
public void setId(ID id) {
this.id = id;
}
public String getSearch() {
return search;
}
public void setSearch(String search) {
this.search = search;
}
}
其中search字段是BootstrapTable查询传递参数的属性名,所以写在了公共的Form类中,不需要的可以删除不要。
公共的CommonController控制器代码如下(主要包了数据显示,新增修改页面的跳转,和数据查询和删除的方法)。
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
-
公共Controller
-
@param
-
@param
-
@param
*/
public class CommonController<T, ID, Form extends BaseForm>{
//通过反射工具类GenericsUtils,获得到实体类
@SuppressWarnings(“unchecked”)
private Class clazz = GenericsUtils.getSuperClassGenricType(getClass());
@Autowired
private CommonService<T, ID> baseService;
//数据显示页面
@RequestMapping(value=“/manage”)
public void manage(ModelMap map) {
}
//修改和新增页面,共用的一个页面
@RequestMapping(value=“/edit”)
public void edit(Form form, ModelMap map) throws InstantiationException, IllegalAccessException {
T model=clazz.newInstance();
ID id = form.getId();
if(id!=null) {
model=baseService.findById(id);
}
map.put(“model”, model);
}
//数据保存方法
@RequestMapping(value=“/save”)
@ResponseBody
public Object save(Form form) {
try {
T model=clazz.newInstance();
ID id = form.getId();
if(id!=null) {
model=baseService.findById(id);
}
BeanUtils.copyProperties(form, model,“id”);
baseService.save(model);
return new AjaxResult(“数据保存成功”);
} catch (Exception e) {
return new AjaxResult(false,“数据保存失败”);
}
}
//删除方法
@RequestMapping(value=“/delete”)
@ResponseBody
public Object delete(ID id) {
try {
baseService.deleteById(id);
return new AjaxResult(“数据删除成功”);
} catch (Exception e) {
return new AjaxResult(false,“数据删除失败”);
}
}
//动态查询方法
public Specification buildSpec(Form form){
return null;
}
//分页数据查询
@RequestMapping(value=“/page”)
@ResponseBody
public Object page(TablePageable pageParam,Form form) {
PageRequest pageable = pageParam.bulidPageRequest();
Specification spec = buildSpec(form);
Page page=baseService.findAll(spec, pageable);
return AjaxResult.bulidPageResult(page);
}
}
分页查询中的TablePageable类,是用于接收Bootstraptable传递过来的分页参数,代码如下。
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
/**
- 分页的一个工具类,接收分页信息
*/
public class TablePageable {
private Integer limit; //分页
private Integer offset;//首记录号(从0开始)
private String sort; //排序字段
private String order; //顺序,逆序
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
public Integer getOffset() {
return offset;
}
public void setOffset(Integer offset) {
this.offset = offset;
}
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public String getOrder() {
return order;
}
public void setOrder(String order) {
this.order = order;
}
public PageRequest bulidPageRequest() {
int page=(offset!=null&&limit!=null)?offset/limit:0;
int size=limit!=null?limit:10;
if(sort==null) {
return PageRequest.of(page, size);
}else {
Order order2=new Order(Direction.fromString(order), sort);
Sort sort2= Sort.by(order2);
return PageRequest.of(page,size,sort2 );
}
}
public PageRequest bulidPageable(Sort sort) {
int page=(offset!=null&&limit!=null)?offset/limit:0;
int size=limit!=null?limit:10;
return PageRequest.of(page, size, sort);
}
public Sort bulidSort() {
Order order2=new Order(Direction.fromString(order), sort);
Sort sort2= Sort.by(order2);
return sort2;
}
}
分页查询中返回的AjaxResult类中的bulidPageResult方法是用于转载BootstrapTable表格数据的,根据BootstrapTable接收数据的格式来写。代码如下。
import org.springframework.data.domain.Page;
import java.util.HashMap;
/**
- 方法执行成功后,返回的工具类
*/
public class AjaxResult {
private Boolean success;
private String msg; //提示信息
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public AjaxResult(String msg) {
super();
this.success=true;
this.msg = msg;
}
public AjaxResult(Boolean success, String msg) {
super();
this.success = success;
this.msg = msg;
}
@SuppressWarnings(“rawtypes”)
public static HashMap<String, Object> bulidPageResult(Page page) {
HashMap<String, Object> result=new HashMap<>();
result.put(“total”, page.getTotalElements());
result.put(“rows”, page.getContent());
return result;
}
}
TablePageable类和AjaxResult类,根据自己开发需求来写。
封装文件写完了,下面就需要来写一个案例测试一下了。新建一个User实体类,随便给几个字段,用于测试。代码如下。
import javax.persistence.*;
@Entity
@Table(name = “tb_user”)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; //主键
private String username; //姓名,username
private String loginName; //用户名,
private Integer age; //年龄
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User() {
}
public User(String username, String loginName, Integer age) {
this.username = username;
this.loginName = loginName;
this.age = age;
}
}
实体类新建完成后,新建对应的Form接收类,继承BaseForm类,代码如下。
import com.mcy.springbootdemo.custom.BaseForm;
public class UserForm extends BaseForm {
private String username; //姓名,username
private String loginName; //登录名
private Integer age; //年龄
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
新建对应的UserRepository类,继承公共的CommonRepository类,泛型传递对应的实体类和ID类型,代码如下。
import com.mcy.springbootdemo.custom.CommonRepository;
import com.mcy.springbootdemo.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends CommonRepository<User, Integer> {
}
新建对应的UserService类,继承公共的CommonService类,泛型也是传递对应的实体类和ID类型,代码如下。
import com.mcy.springbootdemo.custom.CommonService;
import com.mcy.springbootdemo.entity.User;
import org.springframework.stereotype.Service;
@Service
public class UserService extends CommonService<User, Integer> {
}
新建对应的控制器UserController,同样继承公共的CommonController类,泛型传递对应的实体类,ID类型和对应的Form。如果对应的方法有需要改动的,可以重写继承的CommonController类中的方法,比如动态查询,就需要重写CommonController类中的buildSpec方法,代码如下。
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;
@Controller
public class UserController extends CommonController<User, Integer, UserForm> {
@Autowired
private UserRepository userRepository;
@RequestMapping(value = {“/”, “index”})
public String index(){
return “manage”;
}
@Override
public Specification buildSpec(UserForm form) {
Specification spec = new Specification() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//本集合用于封装查询条件
List predicates = new ArrayList<>();
if (StringUtils.hasText(form.getSearch())) {
Predicate name = cb.like(root.get(“loginName”), “%” + form.getSearch() + “%”);
Predicate username = cb.like(root.get(“username”), “%” + form.getSearch() + “%”);