你还在安装mybatis-generator插件?300行自己手写一个Mybatis代码生成工具类吧!
Mybatis如何实现逆向工程,根据表接口直接生成entity类和Mapper文件呢?
之前的做法:
-
打开百度找mybatis-generator,翻找一大堆乱七八糟的教程
-
安装mybatis-generator插件,
-
添加maven依赖
-
搞了一大堆,结果生成的东西还是乱七八糟的。
所以把原理搞懂自己实现一个代码生成类吧。
主要知识点:
JDBC
数据库表字段查询
IO操作
部分地方用到一些反射获取到属性名之类的东西
字符串转换的操作
然后就是一堆的字符串拼接操作。
原理其实很简单,就是读取数据库中的COLUMN_NAME和DATA_TYPE,再拼接成java的类型,和属性名;
最后把拼接的字符串写入到文件中就行了
下面附上详细代码
MybatisUtil.java
package com.bigfire.test.common.utils;
import org.springframework.util.StringUtils;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
- @ IDE :IntelliJ IDEA.
- @ Author :dahuo.
- @ Date :2019/7/23 16:44
- @ Addr :China ShangHai
- @ Email :[email protected]
- @ Desc :
*/
public class MybatisUtil {
private static String url = "";
private static String user = "";
private static String password = "";
private static String driverClass = "com.mysql.jdbc.Driver";
private static String tableName = "";//表名
private static String entityPackName = "";//要生成的entity包名
public static void main(String[] args) {
// System.out.println(generateEntity());//生成实体类
System.out.println(generateMapper(AppFont.class, AppFontDao.class));//生成Mapper
}
//------------------------------------------------下方代码不用修改---------------------------------------------------------
//生成实体类
private static String generateEntity(){
String className = lineToUpCase(tableName);
StringBuilder sb = new StringBuilder();
sb.append("package ").append(entityPackName).append(".").append(className).append("\n\n");
sb.append("import lombok.Data;\n");
sb.append("import lombok.experimental.Accessors;\n");
sb.append("import java.io.Serializable;\n");
List<Entity> entities = getDBColumnMap(tableName);
//生成注释代码
sb.append("/**\n");
sb.append("* @ Date :").append(LocalDate.now()).append(".\n");
sb.append("* auto generate code by MybatisUtil.java.\n");
sb.append("*/\n");
sb.append("@Data\n");
sb.append("public class ").append(className).append(" implements Serializable {\n");
for (int i = 0; i < entities.size(); i++) {
String columnName = entities.get(i).getColumnName();
String dataType = entities.get(i).getDataType();
sb.append(" private ");
if (dataType.equals("varchar")){
sb.append("String ").append(Tran(columnName)).append(";\n");
}else if (dataType.equals("int")){
sb.append("Integer ").append(Tran(columnName)).append(";\n");
}else if (dataType.equals("bigint")){
sb.append("Long ").append(Tran(columnName)).append(";\n");
}else if(dataType.contains("time")){
sb.append("Date ").append(Tran(columnName)).append(";\n");
}else {
sb.append("Date ").append(Tran(columnName)).append(";\n");
}
}
sb.append("\n}\n");
String desktopPath = FileSystemView.getFileSystemView() .getHomeDirectory().getAbsolutePath();
String entityFileName =new StringBuilder(desktopPath).append("/").append(className).append(".java").toString();
writeStringToFile(entityFileName,sb.toString());
return sb.toString();
}
//生成Mapper文件
private static String generateMapper(Class entityClass,Class daoClass){
String className = lineToUpCase(tableName);
String entityNamespace = entityClass.getPackage().getName();
String daoNamespace = daoClass.getPackage().getName();
StringBuilder[] zsbs = new StringBuilder[7];
for (int i=0;i<7;i++){
zsbs[i]=new StringBuilder();
}
List<Entity> entities = getDBColumnMap(tableName);
for (int i = 0; i < entities.size(); i++) {
String columnName = entities.get(i).getColumnName();
zsbs[0].append(" <result column=\"").append(columnName).append("\" property=\"").append(Tran(columnName)).append("\"/>").append("\n");
zsbs[1].append(" ").append(columnName).append(",\n");
zsbs[2].append(" <if test=\"pojo.").append(Tran(columnName)).append(" != null\"> ").append(columnName).append(", </if>\n");
zsbs[3].append(" <if test=\"pojo").append(Tran(columnName)).append(" != null\"> #{pojo.").append(Tran(columnName)).append("}, </if>\n");
zsbs[4].append(" #{pojo.").append(Tran(columnName)).append("},\n");
if (!columnName.equals("id"))
zsbs[5].append(" <if test=\"pojo.").append(Tran(columnName)).append(" != null\"> ").append(columnName).append(" = #{pojo.").append(Tran(columnName)).append("}, </if>\n");
zsbs[6].append(" <if test=\"pojo.").append(Tran(columnName)).append(" != null\"> AND id = #{pojo.").append(Tran(columnName)).append("} </if>\n");
}
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n");
sb.append("<mapper namespace=\"").append(daoNamespace).append("\">\n");
sb.append("\n");
sb.append(" <resultMap id=\"AllColumnMap\" type=\"").append(entityNamespace).append("\">\n");
sb.append(zsbs[0].toString());
sb.append(" </resultMap>\n\n");
sb.append(" <sql id=\"all_column\">\n");
sb.append(zsbs[1].toString());
sb.append(" </sql>\n\n");
//添加
sb.append(" <insert id=\"insert\">\n");
sb.append(" INSERT INTO ").append(tableName).append("\n");
sb.append(" <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
sb.append(zsbs[2].toString());
sb.append(" </trim>\n");
sb.append(" VALUES\n");
sb.append(" <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
sb.append(zsbs[3].toString());
sb.append(" </trim>\n");
sb.append(" </insert>\n\n");
sb.append(" <insert id=\"insertList\">");
sb.append(" INSERT INTO ").append(tableName).append("(\n");
sb.append(" <include refid=\"all_column\"/>\n");
sb.append(" )VALUES\n");
sb.append(" <foreach collection=\"pojos\" item=\"pojo\" index=\"index\" separator=\",\">\n");
sb.append(" (\n");
sb.append(zsbs[4].toString());
sb.append(" )\n");
sb.append(" </foreach>\n");
sb.append(" </insert>\n\n");
//更新
sb.append(" <update id=\"update\">\n");
sb.append(" UPDATE ").append(tableName).append("\n");
sb.append(" <set>\n");
sb.append(zsbs[5].toString());
sb.append(" </set>\n");
sb.append(" WHERE id = #{pojo.id}\n");
sb.append(" </update>\n\n");
//查询
sb.append(" <select id=\"select\" resultMap=\"AllColumnMap\">\n");
sb.append(" SELECT <include refid=\"all_column\"/>");
sb.append(" FROM ").append(tableName).append("\n");
sb.append(" <where>\n");
sb.append(zsbs[6].toString());
sb.append(" </where>\n");
sb.append(" LIMIT 1000\n");
sb.append(" </select>\n\n");
//删除
sb.append(" <delete id=\"delete\">\n");
sb.append(" DELETE FROM ").append(tableName).append(" where id = #{pojo.id}\n");
sb.append(" </delete>\n\n");
//findById
sb.append(" <select id=\"findById\" resultMap=\"AllColumnMap\">\n");
sb.append(" SELECT <include refid=\"all_column\"/>\n");
sb.append(" FROM ").append(tableName).append("\n");
sb.append(" where\n");
sb.append(" id = #{id}\n");
sb.append(" LIMIT 1\n");
sb.append(" </select>\n");
sb.append("</mapper>\n");
String desktopPath = FileSystemView.getFileSystemView() .getHomeDirectory().getAbsolutePath();
String mapperFileName =new StringBuilder(desktopPath).append("/").append(className).append("Mapper").append(".xml").toString();
writeStringToFile(mapperFileName,sb.toString());
return sb.toString();
}
//---------------------------------------------JDBC---------------------------------------------
static{
try {
Properties prop = new Properties();
Class clazz = MybatisUtil.class;
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接方法
public static Connection getConnection(){
try {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//释放资源的方法
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
//释放资源的方法
public static void close(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
close(stmt,conn);
}
//---------------------------------------------获取列名和类型的部分---------------------------------------------
//获取数据库字段和属性
public static List<Entity> getDBColumnMap(String tableName){
Connection conn = MybatisUtil.getConnection();
String sql = "SELECT COLUMN_NAME,DATA_TYPE FROM information_schema.columns WHERE table_name = ?";
try {
PreparedStatement ptmt = conn.prepareStatement(sql);
ptmt.setString(1,tableName);
ResultSet rs = ptmt.executeQuery();
//如果有数据,rs.next()返回true
List<Entity> list = new ArrayList();
while(rs.next()){
list.add(new Entity().setColumnName(rs.getString("COLUMN_NAME")).setDataType(rs.getString("DATA_TYPE")));
}
close(rs,ptmt,conn);
return list;
}catch (Exception e){
e.printStackTrace();
try {
conn.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
return new ArrayList<>();
}
}
//临时存储类
static class Entity {
private String columnName;
private String dataType;
public String getColumnName(){ return this.columnName; }
public String getDataType(){ return this.dataType; }
public Entity setColumnName(String columnName){ this.columnName = columnName; return this; }
public Entity setDataType(String dataType){ this.dataType = dataType; return this; }
@Override
public String toString() { return "["+this.getColumnName()+","+this.getDataType()+"]"; }
}
//------------------------------------------依赖的一些字符串处理方法--------------------------------------------------
//下划线写法转换未驼峰写法
private static String Tran(String columnName){
return toLowerCaseFirst(lineToUpCase(columnName));
}
//首字母转小写
private static String toLowerCaseFirst(String s){
if(Character.isLowerCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
}
//下划线转首字母大写
private static String lineToUpCase(String str){
StringBuilder builder = new StringBuilder();
Arrays.asList(str.split("_")).forEach(temp -> builder.append(StringUtils.capitalize(temp)));
return builder.toString();
}
//首字母转大写
private static String toUpperCaseFirst(String s){
if(Character.isUpperCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
}
//统计字符串出现次数
private static Integer countString(String str,String s) {
int count = 0,len = str.length();
while(str.indexOf(s) != -1) {
str = str.substring(str.indexOf(s) + 1,str.length());
count++;
}
return count;
}
//--------------------------------------IO操作---------------------------------
//字符串写入文件中
public static Boolean writeStringToFile(String path, String resources)
{
FileOutputStream fos;
File f = new File(path);
try
{
fos = new FileOutputStream(f);
fos.write(resources.getBytes());
fos.close();
} catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
}
本人也经常整理一些好用的工具类
相关文章