最近搭建了一个ssm的项目,结果发现每个模块对应的xml文件都要写一堆insert/update之类的重复性代码,区别就是表和字段不一样而已,于是我开始了对其封装。
这里大概说一下思路:
一、向service的实现类impl类的insert方法中传入参数List<entity>,在该方法中调用在service的公共类中封装的转换方法convertList
二、convertList方法将List<entity>转换为了Map<String,Object>,并从中得到了entity的字段名称与主键、每个enttiy的值等信息。
三、dao接口接受Map<String,Object>参数
四、创建一个公共xml文件,里面对findOne / findAll / insert / update / delete 等常用方法进行封装。
五、在对应模块的xml文件中,通过sql标签声明表名与主键,然后通过include标签调用公共xml文件中对应sql。
特别提示,这里用到了一个包,我主要用这个包确定entity中的主键。
<!-- 用于java反射获取entity中的注解 -->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
下面是满满的干货,拿走,别客气!!!
一、模板xml文件:GenericMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="GenericMapper">
<sql id="findOne">select main.* from <include refid="tableName"/> main where main.<include refid="primaryKey"/> = #{mainId}</sql>
<sql id="findAll">select main.* from <include refid="tableName"/> main</sql>
<sql id="insert">
INSERT INTO <include refid="tableName"/> (<foreach collection="map.fields" index="key" item="value" separator=",">${value}</foreach>) VALUES
<foreach collection="map.list" item="item" separator=",">
(<foreach collection="item" item="value" separator=",">#{value}</foreach>)
</foreach>
</sql>
<sql id="update">
update <include refid="tableName"/>
<set>
<foreach collection="map.fields" item="name" separator=",">
${name} = case <include refid="primaryKey"/>
<foreach collection="map.list" item="item">
<foreach collection="item" index="key" item="val" >
<if test="key == map.primaryKey"> when ${"'"}${val}${"'"} then </if><if test="key == name"> #{val} </if>
</foreach>
</foreach>
end
</foreach>
</set>
where <include refid="primaryKey"/> in (<foreach collection="map.mainIds" item="value" separator=",">#{value}</foreach>)
</sql>
<sql id="delete">delete main from <include refid="tableName"/> main where main.<include refid="primaryKey"/>=#{mainId}</sql>
<sql id="deleteByMainIds">
delete main from <include refid="tableName"/> main where main.<include refid="primaryKey"/> in
<foreach collection="list" item="item" open="(" separator="," close=")" >
#{item}
</foreach>
</sql>
<sql id="deleteAll">delete main from <include refid="tableName"/> main</sql>
</mapper>
二、某个模块的xml文件中的部分代码:CoreMenuUrlInfoDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="model.core.menuurl.dao.CoreMenuUrlInfoDao">
<!--表名-->
<sql id="tableName">core_menu_url_info</sql>
<!--主键-->
<sql id="primaryKey">URL_ID</sql>
<select id="findOne" resultType="CoreMenuUrlInfoEntity" parameterType="String">
<include refid="GenericMapper.findOne"/>
</select>
<insert id="insert" >
<include refid="GenericMapper.insert"/>
</insert>
<update id="update">
<include refid="GenericMapper.update"/>
</update>
<delete id="delete" parameterType="String">
<include refid="GenericMapper.delete"/>
</delete>
</mapper>
三、dao文件:CoreMenuUrlInfoDao.java
import model.core.menuurl.entity.CoreMenuUrlInfoEntity;
import org.apache.ibatis.annotations.Param;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public interface CoreMenuUrlInfoDao {
CoreMenuUrlInfoEntity findOne(@Param("mainId") String mainId);
int insert(@Param("map") Map<String,Object> map);
int update(@Param("map") Map<String,Object> map);
int delete(@Param("mainId") String mainId);
}
四、entity:CoreMenuUrlInfoEntity.java
import javax.persistence.*;
import java.sql.Timestamp;
@Entity
@Table(name = "core_menu_url_info")
public class CoreMenuUrlInfoEntity {
private String urlId;
private String title;
private String code;
private String url;
private String parameter;
private Timestamp sysTime;
@Id
@Column(name = "URL_ID")
public String getUrlId() {
return urlId;
}
public void setUrlId(String urlId) {
this.urlId = urlId;
}
@Basic
@Column(name = "TITLE")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Basic
@Column(name = "CODE")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Basic
@Column(name = "URL")
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Basic
@Column(name = "PARAMETER")
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
@Basic
@Column(name = "SYS_TIME")
public Timestamp getSysTime() {
return sysTime;
}
public void setSysTime(Timestamp sysTime) {
this.sysTime = sysTime;
}
}
五、实现类:CoreMenuUrlServiceImpl.java
import model.core.menuurl.dao.CoreMenuUrlInfoDao;
import model.core.menuurl.entity.CoreMenuUrlInfoEntity;
import model.core.menuurl.service.CoreMenuUrlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.context.ApplicationContext;
import util.datamanage.GenericService;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
@Service
public class CoreMenuUrlServiceImpl extends GenericService<CoreMenuUrlInfoEntity> implements CoreMenuUrlService {
@Autowired
private CoreMenuUrlInfoDao dao;
@Override
public CoreMenuUrlInfoEntity findOne(String primaryId) {
return dao.findOne(primaryId);
}
@Override
@Transactional
public int insert(CoreMenuUrlInfoEntity entity){
return dao.insert(convertList(entity));
}
@Override
@Transactional
public int insert(List<CoreMenuUrlInfoEntity> list) {
return dao.insert(convertList(list));
}
@Override
@Transactional
public int update(CoreMenuUrlInfoEntity entity) {
return dao.update(convertList(entity));
}
@Override
@Transactional
public int update(List<CoreMenuUrlInfoEntity> list) {
return dao.update(convertList(list));
}
@Override
@Transactional
public int delete(String primaryId) {
return dao.delete(primaryId);
}
}
六、接口:CoreMenuUrlService.java
import model.core.menuurl.entity.CoreMenuUrlInfoEntity;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CoreMenuUrlService {
CoreMenuUrlInfoEntity findOne(String mainId);
int insert(CoreMenuUrlInfoEntity entity);
int insert(List<CoreMenuUrlInfoEntity> list);
int update(CoreMenuUrlInfoEntity entity);
int update(List<CoreMenuUrlInfoEntity> list);
int delete(String mainId);
}
七、service的一个公共类:GenericService.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.CommonUtil;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.util.*;
public class GenericService<T>{
public Logger logger = LoggerFactory.getLogger(this.getClass());
public Map<String,Object> convertList(T obj){
List<T> list = new ArrayList<>();
list.add(obj);
return convertList(list);
}
public Map<String,Object> convertList(List<T> list){
String primaryKey = "";
List<String> fields = new ArrayList<>();
List<LinkedHashMap<String,Object>> reList = new ArrayList<>();
List<Object> mainIds = new ArrayList<>();
try{
if(list == null || list.size() < 1){
throw new Exception("对象转换失败!");
}
int i = 0;
for(Object obj : list){
LinkedHashMap<String,Object> valMap = new LinkedHashMap<>();
Class c = obj.getClass();
for(Field field : c.getDeclaredFields()){
//设置为可访问
field.setAccessible(true);
String name = humpToUnderline(field.getName().toString());
Object val = field.get(obj);
boolean isMain = false;
//通过该字段的get方法判断其是否存在@Id注解
if(c.getMethod(underlineToHump("GET_" + name)).isAnnotationPresent(Id.class)){
mainIds.add(val);
isMain = true;
}
if(i == 0){
if(isMain){
primaryKey = name;
}
fields.add(name);
}
valMap.put(name,val);
}
reList.add(valMap);
i++;
}
}catch (Exception e){
e.printStackTrace();
}
Map<String,Object> map = new HashMap<>();
//将驼峰命名的字段名转为下划线
map.put("primaryKey", primaryKey);
map.put("mainIds", mainIds);
map.put("fields", fields);
map.put("list", reList);
return map;
}
public Map<String,Object> entityToMap(T obj){
Map<String,Object> map = new HashMap<>();
Class c = obj.getClass();
try{
for(Field field : c.getDeclaredFields()){
//设置为可访问
field.setAccessible(true);
map.put(field.getName().toString(),field.get(obj));
}
}catch (Exception e){
e.printStackTrace();
}
return map;
}
//将list中map的key按照驼峰命名法进行转换,如:MENU_ID > menuId
public List<Map<String,Object>> underlineToHump(List<Map<String,Object>> list){
List<Map<String,Object>> listNew = new ArrayList<>();
for(Map<String,Object> map : list){
Map<String,Object> mapNew = new HashMap<>();
for(Map.Entry<String,Object> m : map.entrySet()){
mapNew.put(CommonUtil.lineToHump(m.getKey()),m.getValue() == null ? "" : m.getValue());
}
listNew.add(mapNew);
}
return listNew;
}
public String underlineToHump(String field){
return CommonUtil.lineToHump(field);
}
//驼峰命名转为下划线命名,如:menuId > MENU_ID
public String humpToUnderline(String field){
StringBuilder sb=new StringBuilder(field);
int temp=0;//定位
if (!field.contains("_")) {
for(int i=0;i<field.length();i++){
if(Character.isUpperCase(field.charAt(i))){
sb.insert(i+temp, "_");
temp+=1;
}
}
}
return sb.toString().toUpperCase();
}
}
八、其实到第七步就可以了,不过为了完整性,还是把后面部分放出来。CoreMenuUrlController.java
import model.core.menuurl.entity.CoreMenuUrlInfoEntity;
import model.core.menuurl.service.CoreMenuUrlService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import util.datamanage.GenericController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Controller
@RequestMapping("/core/menuurl")
public class CoreMenuUrlController extends GenericController{
@Autowired
private CoreMenuUrlService mainService;
@RequestMapping("saveMain")
@ResponseBody
public String saveMain(HttpServletRequest request, HttpServletResponse response)throws Exception{
String primaryId = request.getParameter("urlId");
String title = request.getParameter("title");
String code = request.getParameter("code");
String url = request.getParameter("url");
String parameter = request.getParameter("parameter");
CoreMenuUrlInfoEntity entity = new CoreMenuUrlInfoEntity();
if(StringUtils.isBlank(primaryId)){
entity.setUrlId(UUID.randomUUID().toString());
}else{
entity = mainService.findOne(primaryId);
}
entity.setTitle(title);
entity.setCode(code);
entity.setUrl(url);
entity.setParameter(parameter);
entity.setSysTime(new Timestamp(System.currentTimeMillis()));
try{
if(StringUtils.isBlank(primaryId)){
mainService.insert(entity);
}else{
mainService.update(entity);
}
}catch (Exception e){
e.printStackTrace();
return returnFaild();
}
return returnSuccess();
}
@RequestMapping("deleteMain")
@ResponseBody
public String deleteMain(HttpServletRequest request, HttpServletResponse response)throws Exception{
String primaryId = request.getParameter("primaryId");
try {
mainService.delete(primaryId);
return returnSuccess();
}catch (Exception e){
e.printStackTrace();
return returnFaild();
}
}
}
九、Controller的公共方法:GenericController.java
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Controller中的通用方法
*/
public class GenericController {
public Logger logger = LoggerFactory.getLogger(this.getClass());
//将查询的数据转换成字符串返回
public static String getTable(Object list,int count){
Map<String, Object> table = new HashMap<String, Object>();
table.put("code", 0);
table.put("msg", "查询成功");
table.put("count", count);
table.put("data", list);
JSONObject jsonObject = JSONObject.fromObject(table);
return jsonObject.toString();
}
public static String returnStringByMap(Object obj) {
return JSONObject.fromObject(obj).toString();
}
public static String returnStringByList(Object obj) {
return JSONArray.fromObject(obj).toString();
}
//操作成功的返回
public static String returnSuccess(String msg) {
JSONObject re = new JSONObject();
if(StringUtils.isBlank(msg)){
msg="操作成功!";
}
re.put("error", false);
re.put("msg", msg);
return re.toString();
}
//操作失败的返回
public static String returnFaild(String msg) {
JSONObject re = new JSONObject();
if(StringUtils.isBlank(msg)){
msg="操作失败!";
}
re.put("error", true);
re.put("msg", msg);
return re.toString();
}
}