package org.yeshi.utils.generater.mybatis; import java.beans.Transient; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.dom4j.DocumentHelper; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.springframework.data.annotation.Id; import org.yeshi.utils.generater.entity.MybatisColumnData; public class MyBatisMapperUtil { private static String basePath = "D:/mybatis"; static { // 创建工作目录 if (!new File(basePath).exists()) new File(basePath).mkdirs(); } // 获取dao所在的包名 private static String getDaoPackageName(Class bean) { String name = bean.getName(); String[] ns = name.split("\\."); if (ns.length > 2) { String pks = ""; for (int i = 0; i < ns.length - 2; i++) { pks += ns[i] + "."; } return pks + "dao"; } return ""; } private static String getMapperPackageName(Class bean) { String name = bean.getName(); String[] ns = name.split("\\."); if (ns.length > 2) { String pks = ""; for (int i = 0; i < ns.length - 2; i++) { pks += ns[i] + "."; } return pks + "mapper"; } return ""; } private static List createMapperDaoQuery(int importPosition, StringBuffer buffer, Class clz) { List queryColumnData = new ArrayList<>(); buffer.append("public static class DaoQuery{"); buffer.append("\n\t"); Field[] fields = clz.getDeclaredFields(); Set imports = new HashSet<>(); for (Field fd : fields) { String property = fd.getName(); Annotation[] as = fd.getAnnotations(); String columnName = fd.getName(); for (Annotation a : as) { if (a instanceof Transient || a instanceof org.springframework.data.annotation.Transient) { property = null; break; } if (a instanceof Column) { columnName = ((Column) a).name(); } } String type = null; if (property != null) { //加 String genericType = fd.getGenericType().getTypeName(); if (genericType.indexOf(".") > -1) { imports.add(genericType); type = genericType.split("\\.")[genericType.split("\\.").length - 1]; } else { type = genericType; } if (type.equalsIgnoreCase("Date")) { String tempProperty = "min" + property.substring(0, 1).toUpperCase() + property.substring(1); buffer.append(String.format("\tpublic %s %s;", type, tempProperty)); queryColumnData.add(new MybatisColumnData(columnName, tempProperty, type,ColumnParseUtil.getJDBCType(genericType))); buffer.append("\n\t"); tempProperty = "max" + property.substring(0, 1).toUpperCase() + property.substring(1); buffer.append(String.format("\tpublic %s %s;", type, tempProperty)); queryColumnData.add(new MybatisColumnData(columnName, tempProperty, type,ColumnParseUtil.getJDBCType(genericType))); buffer.append("\n\t"); } else { buffer.append(String.format("\tpublic %s %s;", type, property)); queryColumnData.add(new MybatisColumnData(columnName, property, type,ColumnParseUtil.getJDBCType(genericType))); buffer.append("\n\t"); } } } buffer.append("\tpublic long start;"); buffer.append("\n\t"); buffer.append("\tpublic int count;"); buffer.append("\n\t"); buffer.append("\tpublic List sortList;"); buffer.append("\n\t"); buffer.append("}"); buffer.append("\n"); imports.add("org.apache.ibatis.annotations.Param"); for (String im : imports) { buffer.insert(importPosition, "\n" + String.format("import %s;", im)); } return queryColumnData; } public static void createMapper(Class clz) { // 生成mapper java文件 String pks = getDaoPackageName(clz); StringBuffer buffer = new StringBuffer("package " + pks + ";"); int importPosition = buffer.length(); buffer.append("\n\n"); buffer.append("import " + clz.getName() + ";"); buffer.append("\n\n"); buffer.append(String.format("public interface %sMapper extends BaseMapper<%s> {", clz.getSimpleName(), clz.getSimpleName())); buffer.append("\n\n\t"); //TODO 确定ID类型 buffer.append(String.format("%s selectByPrimaryKeyForUpdate(@Param(\"id\") Long id);", clz.getSimpleName())); buffer.append("\n\n\t"); buffer.append(String.format("List<%s> list(@Param(\"query\") DaoQuery query);", clz.getSimpleName())); buffer.append("\n\n\t"); buffer.append("long count(@Param(\"query\") DaoQuery query);"); buffer.append("\n\n\t"); List queryColumnData = createMapperDaoQuery(importPosition, buffer, clz); buffer.append("}"); String daoName = String.format("%sMapper.java", clz.getSimpleName()); String daoPath = basePath + "/dao/" + daoName; try { if (!new File(basePath + "/dao/").exists()) new File(basePath + "/dao/").mkdirs(); if (!new File(daoPath).exists()) new File(daoPath).createNewFile(); FileOutputStream fos = new FileOutputStream(new File(daoPath)); PrintWriter pw = new PrintWriter(fos); pw.write(buffer.toString().toCharArray()); pw.flush(); pw.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } /** * 生成Mapper xml文件 */ // 获取需要映射的列 List keysList = new ArrayList<>(); Field[] fields = clz.getDeclaredFields(); for (Field fd : fields) { Annotation[] as = fd.getAnnotations(); for (Annotation a : as) { if (a instanceof Column) { Column c = (Column) a; keysList.add(new AttributeColumnMap(fd.getName(), c.name(), fd.getType().getName())); } } } String tableName = ""; Annotation[] as = clz.getAnnotations(); for (Annotation a : as) { if (a instanceof Table) { Table t = (Table) a; tableName = t.value(); } } try { String mapperName = String.format("%sMapper.xml", clz.getSimpleName()); String mapperPath = basePath + "/mapper/" + mapperName; org.dom4j.Document document = DocumentHelper.createDocument(); document.addDocType("mapper", "-//mybatis.org//DTD Mapper 3.0//EN", "http://mybatis.org/dtd/mybatis-3-mapper.dtd"); org.dom4j.Element root = document.addElement("mapper"); root.addAttribute("namespace", pks + "." + mapperName.replace(".xml", "")); org.dom4j.Element resultMap = root.addElement("resultMap"); resultMap.addAttribute("id", "BaseResultMap"); resultMap.addAttribute("type", clz.getName()); AttributeColumnMap idKeys = getAttributeColumnMapByAttribute("id", keysList); if (idKeys != null) { org.dom4j.Element id = resultMap.addElement("id"); id.addAttribute("column", idKeys.column); id.addAttribute("property", idKeys.attribute); id.addAttribute("jdbcType", ColumnParseUtil.getJDBCType(idKeys.type)); } for (AttributeColumnMap key : keysList) { if (key.attribute.equalsIgnoreCase(idKeys.attribute) || ColumnParseUtil.getJDBCType(key.type) == null) continue; org.dom4j.Element result = resultMap.addElement("result"); result.addAttribute("column", key.column); result.addAttribute("property", key.attribute); result.addAttribute("jdbcType", ColumnParseUtil.getJDBCType(key.type)); } // 属性值中包含实体 for (AttributeColumnMap key : keysList) { if (ColumnParseUtil.getJDBCType(key.type) == null) { Class propertyClass = Class.forName(key.type); String propertyMapper = getDaoPackageName(propertyClass) + "." + propertyClass.getSimpleName() + "Mapper"; org.dom4j.Element association = resultMap.addElement("association"); association.addAttribute("property", key.attribute); association.addAttribute("column", key.column); association.addAttribute("resultMap", propertyMapper + ".BaseResultMap"); key.attribute = key.attribute + ".id"; key.type = "java.lang.Long"; } } org.dom4j.Element sql = root.addElement("sql"); sql.addAttribute("id", "Base_Column_List"); sql.setText(getColumns(keysList)); org.dom4j.Element select = root.addElement("select"); select.addAttribute("id", "selectByPrimaryKey"); select.addAttribute("resultMap", "BaseResultMap"); select.addAttribute("parameterType", "java.lang.Long"); select.addText("select"); org.dom4j.Element include = select.addElement("include"); include.addAttribute("refid", "Base_Column_List"); select.addText(String.format(" from %s where %s = #{%s,jdbcType=BIGINT}", tableName, idKeys.column, idKeys.attribute)); select = root.addElement("select"); select.addAttribute("id", "selectByPrimaryKeyForUpdate"); select.addAttribute("resultMap", "BaseResultMap"); select.addAttribute("parameterType", "java.lang.Long"); select.addText("select"); include = select.addElement("include"); include.addAttribute("refid", "Base_Column_List"); select.addText(String.format(" from %s where %s = #{%s,jdbcType=BIGINT} for update", tableName, idKeys.column, idKeys.attribute)); //添加sql sql = root.addElement("sql"); sql.addAttribute("id", "listWhereSQL"); for (MybatisColumnData columnData : queryColumnData) { org.dom4j.Element ife = sql.addElement("if"); ife.addAttribute("test", String.format("query.%s!=null", columnData.getProperty())); if (columnData.getType().equalsIgnoreCase("Date")) { if (columnData.getProperty().startsWith("min")) ife.addText(String.format("AND %s >= #{query.%s}", columnData.getColumn(), columnData.getProperty())); else ife.addText(String.format("AND #{query.%s} > %s", columnData.getProperty(), columnData.getColumn())); } else { ife.addText(String.format("AND %s = #{query.%s}", columnData.getColumn(), columnData.getProperty())); } } //批量查询 select = root.addElement("select"); select.addAttribute("id", "list"); select.addAttribute("resultMap", "BaseResultMap"); select.addText("select"); include = select.addElement("include"); include.addAttribute("refid", "Base_Column_List"); select.addText(String.format(" from %s where 1=1", tableName)); include = select.addElement("include"); include.addAttribute("refid", "listWhereSQL"); org.dom4j.Element ife = select.addElement("if"); ife.addAttribute("test", "query.sortList!=null"); org.dom4j.Element foreach = ife.addElement("foreach"); foreach.addAttribute("collection", "query.sortList"); foreach.addAttribute("item", "item"); foreach.addAttribute("open", " order by "); foreach.addAttribute("separator", ","); foreach.addText(" #{item}"); select.addText("limit #{query.start},#{query.count}"); //批量计数 select = root.addElement("select"); select.addAttribute("id", "count"); select.addAttribute("resultType", "java.lang.Long"); select.addText(String.format(" select count(*) from %s where 1=1", tableName)); include = select.addElement("include"); include.addAttribute("refid", "listWhereSQL"); org.dom4j.Element delete = root.addElement("delete"); delete.addAttribute("id", "deleteByPrimaryKey"); delete.addAttribute("parameterType", "java.lang.Long"); delete.setText(String.format("delete from %s where %s = #{%s,jdbcType=BIGINT}", tableName, idKeys.column, idKeys.attribute)); org.dom4j.Element insert = root.addElement("insert"); insert.addAttribute("id", "insert"); insert.addAttribute("parameterType", clz.getName()); insert.addAttribute("useGeneratedKeys", "true"); insert.addAttribute("keyProperty", "id"); StringBuffer text = new StringBuffer(); text.append(String.format("insert into %s (", tableName)); text.append(getColumns(keysList)); text.append(")"); text.append(" values ("); for (AttributeColumnMap acm : keysList) text.append(getKeyPair(acm)).append(","); text.deleteCharAt(text.length() - 1); text.append(")"); insert.setText(text.toString()); org.dom4j.Element insertSelective = root.addElement("insert"); insertSelective.addAttribute("id", "insertSelective"); insertSelective.addAttribute("parameterType", clz.getName()); insertSelective.addAttribute("useGeneratedKeys", "true"); insertSelective.addAttribute("keyProperty", "id"); insertSelective.addText("insert into " + tableName); org.dom4j.Element trim = insertSelective.addElement("trim"); trim.addAttribute("prefix", "("); trim.addAttribute("suffix", ")"); trim.addAttribute("suffixOverrides", ","); for (AttributeColumnMap acm : keysList) { org.dom4j.Element iff = trim.addElement("if"); iff.addAttribute("test", (acm.attribute.indexOf(".") > -1 ? acm.attribute.split("\\.")[0] : acm.attribute) + " != null"); iff.setText(acm.column + ","); } insertSelective.addText("values"); trim = insertSelective.addElement("trim"); trim.addAttribute("prefix", "("); trim.addAttribute("suffix", ")"); trim.addAttribute("suffixOverrides", ","); for (AttributeColumnMap acm : keysList) { org.dom4j.Element iff = trim.addElement("if"); iff.addAttribute("test", (acm.attribute.indexOf(".") > -1 ? acm.attribute.split("\\.")[0] : acm.attribute) + " != null"); iff.setText(getKeyPair(acm) + ","); } // update org.dom4j.Element update = root.addElement("update"); update.addAttribute("id", "updateByPrimaryKey"); update.addAttribute("parameterType", clz.getName()); text = new StringBuffer(String.format("update %s set ", tableName)); for (AttributeColumnMap acm : keysList) { if (acm.attribute.equalsIgnoreCase(idKeys.attribute)) continue; text.append(String.format("%s = #{%s,jdbcType=%s}", acm.column, acm.attribute, ColumnParseUtil.getJDBCType(acm.type))).append(","); } text.deleteCharAt(text.length() - 1); text.append(String.format(" where %s = #{%s,jdbcType=%s}", idKeys.column, idKeys.attribute, ColumnParseUtil.getJDBCType(idKeys.type))); update.setText(text.toString()); // updateSelective org.dom4j.Element updateSelective = root.addElement("update"); updateSelective.addAttribute("id", "updateByPrimaryKeySelective"); updateSelective.addAttribute("parameterType", clz.getName()); updateSelective.addText("update " + tableName); org.dom4j.Element set = updateSelective.addElement("set"); for (AttributeColumnMap acm : keysList) { if (acm.attribute.equalsIgnoreCase(idKeys.attribute)) continue; org.dom4j.Element iff = set.addElement("if"); iff.addAttribute("test", (acm.attribute.indexOf(".") > -1 ? acm.attribute.split("\\.")[0] : acm.attribute) + " != null"); iff.setText(acm.column + "=" + getKeyPair(acm) + ","); } updateSelective.addText(String.format(" where %s = #{%s,jdbcType=%s}", idKeys.column, idKeys.attribute, ColumnParseUtil.getJDBCType(idKeys.type))); // 创建mapper文件 if (!new File(basePath + "/mapper/").exists()) new File(basePath + "/mapper/").mkdirs(); if (!new File(mapperPath).exists()) new File(mapperPath).createNewFile(); XMLWriter writer = new XMLWriter(new FileOutputStream(new File(mapperPath)), OutputFormat.createPrettyPrint()); writer.setEscapeText(false);// 字符是否转义,默认true writer.write(document); writer.close(); } catch (Exception e) { e.printStackTrace(); } } public static String createSQL(Class clz){ List keysList = new ArrayList<>(); Field[] fields = clz.getDeclaredFields(); for (Field fd : fields) { Annotation[] as = fd.getAnnotations(); AttributeColumnMap columnMap=null; for (Annotation a : as) { if (a instanceof Column) { Column c = (Column) a; columnMap = new AttributeColumnMap(fd.getName(), c.name(), fd.getType().getName()); columnMap.length = c.length(); break; } } for (Annotation a : as) { if(a instanceof Id){ // 主键 columnMap.mainKey = true; break; } } if(columnMap!=null){ keysList.add(columnMap); } } String tableName = ""; Annotation[] as = clz.getAnnotations(); for (Annotation a : as) { if (a instanceof Table) { Table t = (Table) a; tableName = t.value(); } } StringBuffer buffer=new StringBuffer(); buffer.append("create table `").append(tableName).append("`(\n"); for(AttributeColumnMap columnMap:keysList){ String mysqlType = ColumnParseUtil.getMysqlType(columnMap.type); buffer.append("\t`").append(columnMap.column).append("`"); if(columnMap.mainKey) { if(mysqlType.equalsIgnoreCase("bigint")) { buffer.append(" bigint(20) "); buffer.append(" unsigned NOT NULL AUTO_INCREMENT "); }else if(mysqlType.equalsIgnoreCase("varchar")){ buffer.append(" varchar(32) "); buffer.append(" NOT NULL "); } buffer.append(",\n"); buffer.append("\tPRIMARY KEY (`"+columnMap.column+"`),\n"); }else{ String lengthStr=null; int length = columnMap.length; switch(mysqlType){ case "varchar": if(length<=0){ length = 32; } lengthStr="("+length+")"; break; case "int": if(length<=0){ length = 11; } lengthStr="("+length+")"; break; case "datetime": lengthStr=""; break; case "decimal": if(length<=0){ length = 8; } lengthStr="("+length+",2)"; break; default: lengthStr=""; } buffer.append(mysqlType).append(lengthStr).append(" DEFAULT NULL,\n"); } } String fs=buffer.toString().trim(); if(fs.endsWith(",")){ fs = fs.substring(0,fs.length()-1); } fs+= "\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; return fs; } private static AttributeColumnMap getAttributeColumnMapByAttribute(String attributeName, List list) { for (AttributeColumnMap acm : list) if (acm.attribute.equalsIgnoreCase(attributeName)) return acm; return null; } private static String getColumns(List list) { String columns = ""; for (AttributeColumnMap map : list) columns += map.column + ","; return columns.length() > 0 ? columns.substring(0, columns.length() - 1) : columns; } private static String getKeyPair(AttributeColumnMap map) { return String.format("#{%s,jdbcType=%s}", map.attribute, ColumnParseUtil.getJDBCType(map.type)); } } class AttributeColumnMap { String attribute; String column; String type; boolean mainKey; int length; public AttributeColumnMap(String attribute, String column, String type) { this.attribute = attribute; this.column = column; this.type = type; } public AttributeColumnMap() { } }