IDEA 自動生成Mapper

還在爲數據表太多而煩惱嗎?
No, 我要偷懶, 讓其自動創建。
瞭解到 maven 有插件可以生成mapper, 但那不是我想要的,我想要的是 @註解方式
通過數據表實體自動創建 我從中得到了啓發,那就是 拼接字符串並生成文件,正好可以獲取數據表與字段信息
自動生成流程

菜單

首先選擇要添加的表,一個或多個, 右鍵-Scripted Extensions 就有一個腳本選擇菜單
從中選擇 Generator MyMappers.groovy
在這裏插入圖片描述

選擇實體類的目錄

在這裏插入圖片描述

選擇存放mapper的目錄

在這裏插入圖片描述

代碼生成完成

package c.test.demo.mapper;
import org.apache.ibatis.annotations.*;
import java.sql.Timestamp;
import c.test.demo.entry.User;
/**
 * 由Groovy自動生成 
 * <p>Date: 2019/11/28 下午2:03.</p>
 * Description: null
 * @see User
 * @author Mr.Wang
 */
@Mapper
@CacheNamespace
public interface UserMapper {
	/**
	 * 添加記錄
	 * @param user 要插入的對象,包含必要信息
	 */
	@Insert("insert into user(id,username,password,sex,birthday) value (#{id},#{username},#{password},#{sex},#{birthday})")
	@Options(useGeneratedKeys = true, keyProperty = "id")
	void addUser(User user);

	/**
	 * 刪除記錄
	 * @param id 【主鍵】
	 * @return true/false 是否有記錄被修改
	 */
	@Delete("delete from user where id = #{id}")
	boolean deleteUserById(Integer id);
	/**
	 * 修改參數對象中主鍵字段對應的記錄
	 * @param user 要修改的對象,此對象應該是被查詢的對象,並且必須包含主鍵
	 * @return true/false 是否有記錄被修改
	 */
	@Update("update user set id=#{id},username=#{username},password=#{password},sex=#{sex},birthday=#{birthday} where id = #{id}")
	boolean updateUser(User user);

	/**
	 * 修改字段 username
	 * @param id 
	 * @param username 
	 * @return true/false 是否有記錄被修改
	 */
	@Update("update user set username=#{username} where id = #{id}")
	boolean updateFieldUsername(@Param("id") Integer id,@Param("username") String username);

	/**
	 * 修改字段 password
	 * @param id 
	 * @param password 
	 * @return true/false 是否有記錄被修改
	 */
	@Update("update user set password=#{password} where id = #{id}")
	boolean updateFieldPassword(@Param("id") Integer id,@Param("password") String password);

	/**
	 * 修改字段 sex
	 * @param id 
	 * @param sex 
	 * @return true/false 是否有記錄被修改
	 */
	@Update("update user set sex=#{sex} where id = #{id}")
	boolean updateFieldSex(@Param("id") Integer id,@Param("sex") Boolean sex);

	/**
	 * 修改字段 birthday
	 * @param id 
	 * @param birthday 
	 * @return true/false 是否有記錄被修改
	 */
	@Update("update user set birthday=#{birthday} where id = #{id}")
	boolean updateFieldBirthday(@Param("id") Integer id,@Param("birthday") Timestamp birthday);

	/**
	 * 通過主鍵 id查詢
	 * @param id 【主鍵】
	 * @return object or null
	 */
	@Select("select * from user where id = #{id}")
	User getUser(Integer id);
}

闡述

生成的要點:

  1. 沒試過複合主鍵表
  2. 有主鍵或無主鍵都可
  3. 無主鍵的將只有 查找所有和修改所有方法,以及單個字段的修改
  4. 有主鍵的將有 增刪改查, 以及每個字段的修改方法(以主鍵爲條件)
  5. 即使添加方法寫了主鍵也無影響

Generator MyMappers.groovy

參考第一張圖, 選擇 “Go to Scripts Directory” 跳轉到腳本目錄, 將文件放入其中就可以選擇.

或者在目錄 C:\Users\用戶名.IntelliJIdea~\config\extensions\com.intellij.database\schema 文件夾

import com.intellij.database.model.DasTable
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

import java.text.SimpleDateFormat

/*
 * Available context bindings:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

packageName = ""
etityPackageName = ""
tableComment = ""
hasPrimaryKey = false
typeMapping = [
        (~/(?i)int/)                      : "Integer",
        (~/(?i)float|double|decimal|real/): "Double",
        (~/(?i)datetime|timestamp/)       : "Timestamp",
        (~/(?i)date/)                     : "Date",
        (~/(?i)time/)                     : "java.sql.Time",
        (~/(?i)bit/)                      : "Boolean",
        (~/(?i)/)                         : "String"
]
//選擇實體類包路徑,選擇的包路徑,用於添加import包語句.
FILES.chooseDirectoryAndSave(unicodeToString("\\u9009\\u62e9\\u5b9e\\u4f53\\u7c7b\\u5305\\u8def\\u5f84")
        , unicodeToString("\\u9009\\u62e9\\u7684\\u5305\\u8def\\u5f84\\u002c\\u7528\\u4e8e\\u6dfb\\u52a0\\u0069\\u006d\\u0070\\u006f\\u0072\\u0074\\u5305\\u8bed\\u53e5\\u002e")) { dir ->
  generate(dir)
}
//選擇Mapper存放的包路徑,選擇的目錄將生成Mapper文件
FILES.chooseDirectoryAndSave(unicodeToString("\\u9009\\u62e9\\u004d\\u0061\\u0070\\u0070\\u0065\\u0072\\u5b58\\u653e\\u7684\\u5305\\u8def\\u5f84")
        , unicodeToString("\\u9009\\u62e9\\u7684\\u76ee\\u5f55\\u5c06\\u751f\\u6210\\u004d\\u0061\\u0070\\u0070\\u0065\\u0072\\u6587\\u4ef6")) { dir ->
  SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) }
}
def generate(dir){
  etityPackageName = dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "")
}
def generate(table, dir) {
  def className = javaName(table.getName(), true)
  def tableName = table.getName()
  def fields = calcFields(table)
  packageName = getPackageName(dir)
  //文件名的拼接
  PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, className + "Mapper.java")), "UTF-8"))
  printWriter.withPrintWriter {out -> generate(out, className, tableName, fields)}
}

// 獲取包所在文件夾路徑
def getPackageName(dir) {
  return (dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";");//.substring(1)
}

def generate(out, className, tableName, fields) {
  out.println "package $packageName"
  out.println "import org.apache.ibatis.annotations.*;"
  Set types = new HashSet()
  fields.each() {
    types.add(it.type)
  }
  if (types.contains("Timestamp")) {
    out.println "import java.sql.Timestamp;"
  }
  if (types.contains("Date")) {
    out.println "import java.util.Date;"
  }
  out.println "import $etityPackageName.${className};"
  out.println "/**"
  Locale.setDefault(Locale.CHINA)
  sdf = new SimpleDateFormat()
  //由Groovy自動生成
  out.println " * ${unicodeToString('\\u7531\\u0047\\u0072\\u006f\\u006f\\u0076\\u0079\\u81ea\\u52a8\\u751f\\u6210')} "
  out.println " * <p>Date: " + sdf.format(new java.util.Date()) + ".</p>"
  out.println " * Description: $tableComment"
  out.println " * @see $className"
  out.println " * @author Mr.Wang"
  out.println " */"
  out.println "@Mapper"
  out.println "@CacheNamespace"
  out.println "public interface ${className}Mapper {"
  //如果沒有主鍵的表 則
  if(!hasPrimaryKey){
    //查找
    out.println "\t/**"
    //查找所有記錄
    out.println "\t * " + unicodeToString("\\u67e5\\u627e\\u6240\\u6709\\u8bb0\\u5f55")
    out.println "\t * @return object or null"
    out.println "\t */"
    out.println "\t@Select(\"select * from $tableName\")"
    out.println "\t$className find$className();"
    out.println ""
    //修改
    out.println "\t/**"
    //修改對象屬性對應的所有字段
    out.println "\t * " + unicodeToString("\\u4fee\\u6539\\u5bf9\\u8c61\\u5c5e\\u6027\\u5bf9\\u5e94\\u7684\\u6240\\u6709\\u5b57\\u6bb5")
    //要修改的對象,此對象應該是經過查詢的對象
    out.println "\t * @param ${javaName(className, false)} " + unicodeToString("\\u8981\\u4fee\\u6539\\u7684\\u5bf9\\u8c61\\uff0c\\u6b64\\u5bf9\\u8c61\\u5e94\\u8be5\\u662f\\u7ecf\\u8fc7\\u67e5\\u8be2\\u7684\\u5bf9\\u8c61")
    //是否有記錄被修改
    out.println "\t * @return true/false " + unicodeToString("\\u662f\\u5426\\u6709\\u8bb0\\u5f55\\u88ab\\u4fee\\u6539")
    out.println "\t */"
    out.print "\t@Update(\"update $tableName "
    first = true
    fields.each(){
      if(first){
        out.print "set ${it.colName}=#{${it.name}}"
        first = false
      } else out.print ",${it.colName}=#{${it.name}}"
    }
    out.println "\")"
    //********此處根據需要而定, 如果修改超過一條記錄 因改爲 int , 同理 刪除的地方也是************//
    out.println "\tboolean update$className($className ${javaName(className, false)});"
    //單字段修改
    out.println ""
    fields.each(){
      out.println "\t/**"
      //修改字段
      out.println "\t * ${unicodeToString('\\u4fee\\u6539\\u5b57\\u6bb5')} ${it.name}"
      out.println "\t * @param ${it.name} ${it.comment}"
      //是否有記錄被修改
      out.println "\t * @return true/false " + unicodeToString("\\u662f\\u5426\\u6709\\u8bb0\\u5f55\\u88ab\\u4fee\\u6539")
      out.println "\t */"
      out.println "\t@Update(\"update $tableName set ${it.colName}=#{${it.name}}\")"
      out.println "\tboolean updateFiled${javaName(it.name,true)}(${it.type} ${it.name});"
      out.println ""
    }
    out.println "}"

    return
  }
  boolean first = false//判斷是否爲循環第一次,用於控制輸出","等
  //獲取主鍵信息
  def pk = [:]
  fields.each() {
    if(it.isPk) {
      pk.put("name", it.name)
      pk.put("colName", it.colName)
      pk.put("type", it.type)
      pk.put("comment", it.comment)
    }
    return false
  }
  //增
  out.println "\t/**"
  //添加記錄
  out.println "\t * " + unicodeToString("\\u6dfb\\u52a0\\u8bb0\\u5f55")
  //要插入的對象,包含必要信息
  out.println "\t * @param ${javaName(className, false)} " + unicodeToString("\\u8981\\u63d2\\u5165\\u7684\\u5bf9\\u8c61\\u002c\\u5305\\u542b\\u5fc5\\u8981\\u4fe1\\u606f")
  out.println "\t */"
  out.print "\t@Insert(\"insert into $tableName("
  first = true
  fields.each(){
    if(first){
      out.print "${it.colName}"
      first = false
    } else out.print ",${it.colName}"
  }
  out.print ") value ("
  first = true
  fields.each(){
    if(first){
      out.print "#{${it.name}}"
      first = false
    } else out.print ",#{${it.name}}"
  }
  out.println ")\")"
  //是否需要將自動生成的鍵設置到對象中
  out.println "\t@Options(useGeneratedKeys = true, keyProperty = \"${pk.name}\")"
  out.println "\tvoid add$className($className ${javaName(className, false)});"
  out.println ""

  //刪 @Delete("delete from admin_role where id = #{roleId}")
  out.println "\t/**"
  //刪除記錄
  out.println "\t * " + unicodeToString("\\u5220\\u9664\\u8bb0\\u5f55")
  //【主鍵】
  out.println "\t * @param ${pk.name} ${pk.comment}" + unicodeToString("\\u3010\\u4e3b\\u952e\\u3011")
  //是否有記錄被修改
  out.println "\t * @return true/false " + unicodeToString("\\u662f\\u5426\\u6709\\u8bb0\\u5f55\\u88ab\\u4fee\\u6539")
  out.println "\t */"
  out.println "\t@Delete(\"delete from $tableName where ${pk.colName} = #{${pk.name}}\")"
  out.println "\tboolean delete${className}ById(${pk.type} ${pk.name});"

  //改
  out.println "\t/**"
  //修改參數對象中主鍵字段對應的記錄
  out.println "\t * " + unicodeToString("\\u4fee\\u6539\\u53c2\\u6570\\u5bf9\\u8c61\\u4e2d\\u4e3b\\u952e\\u5b57\\u6bb5\\u5bf9\\u5e94\\u7684\\u8bb0\\u5f55")
  //要修改的對象,此對象應該是被查詢的對象,並且必須包含主鍵
  out.println "\t * @param ${javaName(className, false)} " + unicodeToString("\\u8981\\u4fee\\u6539\\u7684\\u5bf9\\u8c61\\uff0c\\u6b64\\u5bf9\\u8c61\\u5e94\\u8be5\\u662f\\u88ab\\u67e5\\u8be2\\u7684\\u5bf9\\u8c61\\uff0c\\u5e76\\u4e14\\u5fc5\\u987b\\u5305\\u542b\\u4e3b\\u952e")
  //是否有記錄被修改
  out.println "\t * @return true/false " + unicodeToString("\\u662f\\u5426\\u6709\\u8bb0\\u5f55\\u88ab\\u4fee\\u6539")
  out.println "\t */"
  out.print "\t@Update(\"update $tableName "
  first = true
  fields.each(){
    if(first){
      out.print "set ${it.colName}=#{${it.name}}"
      first = false
    } else out.print ",${it.colName}=#{${it.name}}"
  }
  out.println " where ${pk.colName} = #{${pk.name}}\")"
  out.println "\tboolean update$className($className ${javaName(className, false)});"
  out.println ""
  //單字段修改
  fields.each(){
    if(it.isPk) return //主鍵跳過
    out.println "\t/**"
    //修改字段
    out.println "\t * ${unicodeToString('\\u4fee\\u6539\\u5b57\\u6bb5')} ${it.name}"
    out.println "\t * @param ${pk.name} ${pk.comment}"
    out.println "\t * @param ${it.name} ${it.comment}"
    //是否有記錄被修改
    out.println "\t * @return true/false " + unicodeToString("\\u662f\\u5426\\u6709\\u8bb0\\u5f55\\u88ab\\u4fee\\u6539")
    out.println "\t */"
    out.println "\t@Update(\"update $tableName set ${it.colName}=#{${it.name}} where ${pk.colName} = #{${pk.name}}\")"
    out.println "\tboolean updateField${javaName(it.name,true)}(@Param(\"${pk.name}\") ${pk.type} ${pk.name},@Param(\"${it.name}\") ${it.type} ${it.name});"
    out.println ""
  }
  //查
  out.println "\t/**"
  //通過主鍵 ${pk.name} 查詢
  out.println "\t * ${unicodeToString('\\u901a\\u8fc7\\u4e3b\\u952e')} ${pk.name}" + unicodeToString("\\u67e5\\u8be2")
  out.println "\t * @param ${pk.name} ${pk.comment}" + unicodeToString("\\u3010\\u4e3b\\u952e\\u3011")
  out.println "\t * @return object or null"
  out.println "\t */"
  out.println "\t@Select(\"select * from $tableName where ${pk.colName} = #{${pk.name}}\")"
  out.println "\t$className get$className(${pk.type} ${pk.name});"
  //類結束
  out.println "}"
}

def calcFields(table) {
  hasPrimaryKey = DasUtil.getPrimaryKey(table) == null ? false : true
  tableComment = table.getComment()
  DasUtil.getColumns(table).reduce([]) { fields, col ->
    def spec = Case.LOWER.apply(col.getDataType().getSpecification())
    def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
    fields += [
            colName : col.getName(),
            name :  javaName(col.getName(), false),
            type : typeStr,
            comment: getComment(col.getComment()),
            isPk : DasUtil.isPrimary(col),
            isFk : DasUtil.isIndexColumn(col)
    ]
  }
}

def javaName(str, capitalize) {
  def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
          .collect { Case.LOWER.apply(it).capitalize() }
          .join("")
          .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
  capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
  return content != null && content.toString().trim().length() > 0
}
//獲取註釋
def getComment(comment){
  if (isNotEmpty(comment)) {
    return comment.toString()
  }
  return ""
}
/**
 * unicode轉字符串
 * 用於 文件註釋,由於 groovy 編譯器不支持中文
 * @param unicode 編碼爲Unicode的字符串
 * @return 解碼字符串
 */
def String unicodeToString(String unicode) {
  StringBuffer sb = new StringBuffer();
  String[] hex = unicode.split("\\\\u");
  for (int i = 1; i < hex.length; i++) {
    int index = Integer.parseInt(hex[i], 16);
    sb.append((char) index);
  }
  return sb.toString();
}


至於爲何用Unicode, 因爲用中文亂碼! 我也找不到怎麼配置Groovy編譯器編碼, 以上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章