最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

IDEA如何自動(dòng)生成Mapper

 更新時(shí)間:2026年03月11日 09:22:51   作者:很倔也很天真  
本文介紹了如何使用Groovy腳本自動(dòng)生成MyBatis的Mapper接口和XML文件,通過(guò)選擇數(shù)據(jù)表實(shí)體和存放mapper的目錄,可以自動(dòng)生成對(duì)應(yīng)的增刪改查方法,腳本可以處理有主鍵和無(wú)主鍵的表,并且支持復(fù)合主鍵

還在為數(shù)據(jù)表太多而煩惱嗎?

No, 我要偷懶, 讓其自動(dòng)創(chuàng)建。

了解到 maven 有插件可以生成mapper, 但那不是我想要的,我想要的是 @注解方式

通過(guò)數(shù)據(jù)表實(shí)體自動(dòng)創(chuàng)建 我從中得到了啟發(fā),那就是 拼接字符串并生成文件,正好可以獲取數(shù)據(jù)表與字段信息

自動(dòng)生成流程

菜單

首先選擇要添加的表,一個(gè)或多個(gè), 右鍵-Scripted Extensions 就有一個(gè)腳本選擇菜單

從中選擇 Generator MyMappers.groovy

選擇實(shí)體類的目錄

選擇存放mapper的目錄

代碼生成完成

package c.test.demo.mapper;
import org.apache.ibatis.annotations.*;
import java.sql.Timestamp;
import c.test.demo.entry.User;
/**
 * 由Groovy自動(dòng)生成 
 * <p>Date: 2019/11/28 下午2:03.</p>
 * Description: null
 * @see User
 * @author Mr.Wang
 */
@Mapper
@CacheNamespace
public interface UserMapper {
	/**
	 * 添加記錄
	 * @param user 要插入的對(duì)象,包含必要信息
	 */
	@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);
	/**
	 * 修改參數(shù)對(duì)象中主鍵字段對(duì)應(yīng)的記錄
	 * @param user 要修改的對(duì)象,此對(duì)象應(yīng)該是被查詢的對(duì)象,并且必須包含主鍵
	 * @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);

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

闡述

生成的要點(diǎn):

  • 沒(méi)試過(guò)復(fù)合主鍵表
  • 有主鍵或無(wú)主鍵都可
  • 無(wú)主鍵的將只有 查找所有和修改所有方法,以及單個(gè)字段的修改
  • 有主鍵的將有 增刪改查, 以及每個(gè)字段的修改方法(以主鍵為條件)
  • 即使添加方法寫了主鍵也無(wú)影響

Generator MyMappers.groovy

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

或者在目錄 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"
]
//選擇實(shí)體類包路徑,選擇的包路徑,用于添加import包語(yǔ)句.
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自動(dòng)生成
  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 {"
  //如果沒(méi)有主鍵的表 則
  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/**"
    //修改對(duì)象屬性對(duì)應(yīng)的所有字段
    out.println "\t * " + unicodeToString("\\u4fee\\u6539\\u5bf9\\u8c61\\u5c5e\\u6027\\u5bf9\\u5e94\\u7684\\u6240\\u6709\\u5b57\\u6bb5")
    //要修改的對(duì)象,此對(duì)象應(yīng)該是經(jīng)過(guò)查詢的對(duì)象
    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 "\")"
    //********此處根據(jù)需要而定, 如果修改超過(guò)一條記錄 因改為 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//判斷是否為循環(huán)第一次,用于控制輸出","等
  //獲取主鍵信息
  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")
  //要插入的對(duì)象,包含必要信息
  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 ") values ("
  first = true
  fields.each(){
    if(first){
      out.print "#{${it.name}}"
      first = false
    } else out.print ",#{${it.name}}"
  }
  out.println ")\")"
  //是否需要將自動(dòng)生成的鍵設(shè)置到對(duì)象中
  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/**"
  //修改參數(shù)對(duì)象中主鍵字段對(duì)應(yīng)的記錄
  out.println "\t * " + unicodeToString("\\u4fee\\u6539\\u53c2\\u6570\\u5bf9\\u8c61\\u4e2d\\u4e3b\\u952e\\u5b57\\u6bb5\\u5bf9\\u5e94\\u7684\\u8bb0\\u5f55")
  //要修改的對(duì)象,此對(duì)象應(yīng)該是被查詢的對(duì)象,并且必須包含主鍵
  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 //主鍵跳過(guò)
    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/**"
  //通過(guò)主鍵 ${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});"
  //類結(jié)束
  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轉(zhuǎn)字符串
 * 用于 文件注釋,由于 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, 因?yàn)橛弥形膩y碼! 我也找不到怎么配置Groovy編譯器編碼, 以上

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • MyBatis Plus like參數(shù)為百分號(hào)%查詢結(jié)果異常原因分析及解決

    MyBatis Plus like參數(shù)為百分號(hào)%查詢結(jié)果異常原因分析及解決

    文章指出在MyBatisPlus使用LIKE查詢時(shí),用戶輸入的%可能導(dǎo)致通配符誤匹配,推薦使用ESCAPE轉(zhuǎn)義功能,將%轉(zhuǎn)換為普通字符,既支持模糊查詢又避免全表匹配,提升準(zhǔn)確性和性能
    2025-09-09
  • JavaAgent實(shí)現(xiàn)http接口發(fā)布方式淺析

    JavaAgent實(shí)現(xiàn)http接口發(fā)布方式淺析

    這篇文章主要介紹了JavaAgent實(shí)現(xiàn)http接口發(fā)布方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-03-03
  • SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流

    SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流

    這篇文章主要介紹了SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java中的DelayQueue源碼解析

    Java中的DelayQueue源碼解析

    這篇文章主要介紹了Java中的DelayQueue源碼解析,一個(gè)實(shí)現(xiàn)PriorityBlockingQueue實(shí)現(xiàn)延遲獲取的無(wú)界隊(duì)列,在創(chuàng)建元素時(shí),可以指定多久才能從隊(duì)列中獲取當(dāng)前元素,只有延時(shí)期滿后才能從隊(duì)列中獲取元素,需要的朋友可以參考下
    2023-12-12
  • RocketMQ的順序消費(fèi)機(jī)制詳解

    RocketMQ的順序消費(fèi)機(jī)制詳解

    這篇文章主要介紹了RocketMQ的順序消費(fèi)機(jī)制詳解,順序消息是指對(duì)于一個(gè)指定的?Topic?,消息嚴(yán)格按照先進(jìn)先出(FIFO)的原則進(jìn)行消息發(fā)布和消費(fèi),即先發(fā)布的消息先消費(fèi),后發(fā)布的消息后消費(fèi),,需要的朋友可以參考下
    2023-10-10
  • Java多線程 Callable、Future 和FutureTask

    Java多線程 Callable、Future 和FutureTask

    這篇文章主要介紹Java多線程中的 Callable、Future 以及FutureTask,下面文章圍繞Java多線程的相關(guān)資料展開(kāi)全文詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-10-10
  • springboot之聯(lián)表查詢方式

    springboot之聯(lián)表查詢方式

    這篇文章主要介紹了springboot之聯(lián)表查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟

    手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟

    這篇文章主要介紹了手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 如何理解Java中基類子對(duì)象的構(gòu)建過(guò)程從

    如何理解Java中基類子對(duì)象的構(gòu)建過(guò)程從"基類向外"進(jìn)行擴(kuò)散的?

    今天小編就為大家分享一篇關(guān)于如何理解Java中基類子對(duì)象的構(gòu)建過(guò)程從"基類向外"進(jìn)行擴(kuò)散的?,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • 淺談Spring Boot 微服務(wù)項(xiàng)目的推薦部署方式

    淺談Spring Boot 微服務(wù)項(xiàng)目的推薦部署方式

    這篇文章主要介紹了淺談Spring Boot 微服務(wù)項(xiàng)目的推薦部署方式,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-09-09

最新評(píng)論

沙雅县| 清流县| 和林格尔县| 缙云县| 化隆| 灵璧县| 台州市| 南丹县| 三明市| 重庆市| 泽普县| 图们市| 乌苏市| 阜康市| 新昌县| 新乡市| 浦东新区| 京山县| 常山县| 柘荣县| 德兴市| 阿合奇县| 合作市| 思茅市| 林周县| 绍兴县| 澄迈县| 特克斯县| 武宁县| 睢宁县| 平江县| 叙永县| 怀安县| 修水县| 龙岩市| 拉萨市| 黎城县| 都昌县| 上蔡县| 佛山市| 墨脱县|