groovy定义变量获取当前时间_IDEA不愧为神器,结合Groovy脚本,简直无敌!
作者:人間哪有四月天
segmentfault.com/a/1190000020189801
導(dǎo)語
如今,有許許多多的插件或者編輯器都支持根據(jù)數(shù)據(jù)表自動(dòng)生成數(shù)據(jù)實(shí)體類了, 比如IDEA, 各種MyBatis的代碼生成工具, 等等. 本篇介紹一下如何使用IDEA的groovy腳本文件生成帶JPA注解的實(shí)體類
一, 使用IDEA連接數(shù)據(jù)庫
需注意:
正式版IDEA才有此功能, 社區(qū)版木有
演示圖片使用的IDEA版本為2018.3, 不同版本界面可能有細(xì)小差別
創(chuàng)建新的數(shù)據(jù)連接
如果沒有, 可以上方菜單欄: 視圖-工具窗口-Database打開
新建Oracle數(shù)據(jù)庫也是相同操作
配置數(shù)據(jù)連接
填寫一個(gè)連接名,隨便填什么都行
不用選擇,默認(rèn)就行
填寫數(shù)據(jù)庫連接的 IP地址,比如本地?cái)?shù)據(jù)庫可以填寫:localhost或者127.0.0.1
填寫數(shù)據(jù)庫開放的端口號(hào),一般沒設(shè)置的話默認(rèn)都是3306
填寫你需要連接的數(shù)據(jù)庫名
填寫數(shù)據(jù)庫的用戶名
填寫數(shù)據(jù)庫密碼
這里會(huì)有一個(gè)驅(qū)動(dòng)需要點(diǎn)擊下載,圖中是已經(jīng)下載好了
填寫自己的數(shù)據(jù)庫連接url,然后可以點(diǎn)擊9所在按鈕進(jìn)行測(cè)試連接,本地連接失敗檢查是否開啟了mysql服務(wù)
二, IDEA自帶的兩種創(chuàng)建實(shí)體類的方法
(1), 如果只是創(chuàng)建簡單的, 只有屬性, getter, setter的實(shí)體類, 而不需要JPA/Hibernate的實(shí)體類注解
單擊打開剛剛創(chuàng)建的數(shù)據(jù)連接
打開schemas, 找到自己需要?jiǎng)?chuàng)建實(shí)體類的表(可以使用ctrl或shift多選)
右鍵: Scripted Extensions - Generate POJOs.groovy
選擇生成路徑就OK了
需注意
生成的包名可能有問題, 默認(rèn)是package com.sample, 需要自己手動(dòng)修改
(2), 使用了Hibernate/Jpa框架, 需要的是有注解的實(shí)體類, Idea也提供了相應(yīng)的方法
推薦:100期面試題匯總
添加JPA模塊
打開項(xiàng)目結(jié)構(gòu)
打開模塊, 點(diǎn)擊+號(hào)添加模塊
選擇JPA
點(diǎn)擊右下角確定后, 關(guān)閉項(xiàng)目結(jié)構(gòu)
使用Persistence工具生成帶注解的實(shí)體類-1
如果上一步?jīng)]問題的話, IDEA左下角側(cè)邊欄會(huì)出現(xiàn)Persistence工具欄
打開Persistence工具欄, 右鍵項(xiàng)目: Generate Persistence Mapping - By Database Schema
使用Persistence工具生成帶注解的實(shí)體類-2
選擇數(shù)據(jù)庫連接
選擇生成類所在包
選擇要生成的表
選擇要生成的字段(選擇表后字段默認(rèn)除了外鍵全選)
修改要生成的屬性名
修改要生成的屬性類型
勾上即為生成帶注解的實(shí)體類
生成的類實(shí)例如下
三, 更進(jìn)一步, 使用自己的Groovy生成帶注解的實(shí)體類
上面介紹了兩個(gè)使用IDEA生成實(shí)體類的方法, 各有優(yōu)缺點(diǎn)
生成不帶注解的實(shí)體類簡單高效, 但缺點(diǎn)就是如果使用的是Jpa/Hibernate框架就不適合
生成帶注解的實(shí)體類能生成注解實(shí)體類, 但缺點(diǎn)就是生成的實(shí)體類的注解可能不太符合我們的注解, 只能生成到當(dāng)前項(xiàng)目包下, 面對(duì)一些復(fù)雜的數(shù)據(jù)庫如Oracle會(huì)顯示很多系統(tǒng)表而且表空間切換不太方便
我們知道Idea生成不帶注解的實(shí)體類是通過Groovy腳本文件生成的, 我們也能找到這個(gè)文件, 那我們能不能修改這個(gè)文件, 讓它生成帶注解的實(shí)體類呢?
(1), 使用自己的Groovy生成帶注解的實(shí)體類的好處
在Database工具欄里, 操作簡單方便
可以自己對(duì)腳本進(jìn)行一些編輯, 使生成的實(shí)體類達(dá)到自己的定制需求
對(duì)Oracle這樣的數(shù)據(jù)庫生成實(shí)體類時(shí), 避免了系統(tǒng)表的影響, 可以自己選擇表空間進(jìn)行操作
可以生成在電腦上的任何位置, 不受限制
(2), 使用自己的Groovy生成帶注解的實(shí)體類的不足
@author 作者名需要自己修改腳本
@Table(Schema="") 的表空間名不能讀取, 需要自己修改腳本, 設(shè)定表空間名(mysql可以直接刪除這個(gè)屬性的定義)(IDEA的Persistence工具可以讀取(Schema=""屬性并生成, 但我們不知道它是怎么獲取的)
@Id的主鍵生成方式不可知, 需要生成后自己確定(mysql用戶可以直接修改腳本設(shè)定主鍵生成方式, 但Oracle用戶需要生成實(shí)體類后再逐個(gè)確認(rèn))
(3), 使用自己的Groovy生成帶注解的實(shí)體類可以繼續(xù)完善的地方
1, 如果需要hashcode()和equals()方法, 也修改腳本, 使其自動(dòng)生成
(4), 新建一個(gè)Groovy腳本文件
Database工具欄里, 右鍵右鍵: Scripted Extensions - Go to Scripts Directory
在目錄下新建一個(gè)Generate MyPOJOs.groovy
添加里面的內(nèi)容
修改idea為自己名字 的地方可以修改作者名字為自己的
schema = \"后面添加自己的表空間名稱(mysql可以不添加, 不用這個(gè)schema屬性也行) 這里可以根據(jù)提示修改
import?com.intellij.database.model.ObjectKind
import?com.intellij.database.util.Case
import?com.intellij.database.util.DasUtil
import?java.text.SimpleDateFormat
/*
?*?Available?context?bindings:
?*???SELECTION???Iterable
?*???PROJECT?????project
?*???FILES???????files?helper
?*/
packageName?=?""
typeMapping?=?[
????????(~/(?i)tinyint|smallint|mediumint/)??????:?"Integer",
????????(~/(?i)int/)?????????????????????????????:?"Long",
????????(~/(?i)bool|bit/)????????????????????????:?"Boolean",
????????(~/(?i)float|double|decimal|real/)???????:?"Double",
????????(~/(?i)datetime|timestamp|date|time/)????:?"Date",
????????(~/(?i)blob|binary|bfile|clob|raw|image/):?"InputStream",
????????(~/(?i)/)????????????????????????????????:?"String"
]
FILES.chooseDirectoryAndSave("Choose?directory",?"Choose?where?to?store?generated?files")?{?dir?->
????SELECTION.filter?{?it?instanceof?DasTable?&&?it.getKind()?==?ObjectKind.TABLE?}.each?{?generate(it,?dir)?}
}
def?generate(table,?dir)?{
????def?className?=?javaName(table.getName(),?true)
????def?fields?=?calcFields(table)
????packageName?=?getPackageName(dir)
????PrintWriter?printWriter?=?new?PrintWriter(new?OutputStreamWriter(new?FileOutputStream(new?File(dir,?className?+?".java")),?"UTF-8"))
????printWriter.withPrintWriter?{?out?->?generate(out,?className,?fields,?table)?}
//????new?File(dir,?className?+?".java").withPrintWriter?{?out?->?generate(out,?className,?fields,table)?}
}
//?獲取包所在文件夾路徑
def?getPackageName(dir)?{
????return?dir.toString().replaceAll("\\\\",?".").replaceAll("/",?".").replaceAll("^.*src(\\.main\\.java\\.)?",?"")?+?";"
}
def?generate(out,?className,?fields,?table)?{
????out.println?"package?$packageName"
????out.println?""
????out.println?"import?javax.persistence.Column;"
????out.println?"import?javax.persistence.Entity;"
????out.println?"import?javax.persistence.Table;"
????out.println?"import?javax.persistence.Id;"
????out.println?"import?javax.persistence.GeneratedValue;"
????out.println?"import?java.io.Serializable;"
????Set?types?=?new?HashSet()
????fields.each()?{
????????types.add(it.type)
????}
????if?(types.contains("Date"))?{
????????out.println?"import?java.util.Date;"
????}
????if?(types.contains("InputStream"))?{
????????out.println?"import?java.io.InputStream;"
????}
????out.println?""
????out.println?"/**\n"?+
????????????"?*?@Description??\n"?+
????????????"?*?@Author??idea\n"?+?//1.?修改idea為自己名字
????????????"?*?@Date?"?+?new?SimpleDateFormat("yyyy-MM-dd").format(new?Date())?+?"?\n"?+
????????????"?*/"
????out.println?""
????out.println?"@Entity"
????out.println?"@Table?(?name?=\""?+?table.getName()?+?"\"?,?schema?=?\"\")"?//2.?schema?=?\"后面添加自己的表空間名稱(mysql可以不添加,?不用這個(gè)schema屬性也行)
????out.println?"public?class?$className??implements?Serializable?{"
????out.println?""
????out.println?genSerialID()
????fields.each()?{
????????out.println?""
????????//?輸出注釋
????????if?(isNotEmpty(it.commoent))?{
????????????out.println?"\t/**"
????????????out.println?"\t?*?${it.commoent.toString()}"
????????????out.println?"\t?*/"
????????}
????????if?((it.annos+"").indexOf("[@Id]")?>=?0)?out.println?"\t@Id"
????????if?(it.annos?!=?"")?out.println?"???${it.annos.replace("[@Id]",?"")}"
????????//?輸出成員變量
????????out.println?"\tprivate?${it.type}?${it.name};"
????}
????//?輸出get/set方法
????fields.each()?{
????????out.println?""
????????out.println?"\tpublic?${it.type}?get${it.name.capitalize()}()?{"
????????out.println?"\t\treturn?this.${it.name};"
????????out.println?"\t}"
????????out.println?""
????????out.println?"\tpublic?void?set${it.name.capitalize()}(${it.type}?${it.name})?{"
????????out.println?"\t\tthis.${it.name}?=?${it.name};"
????????out.println?"\t}"
????}
????//?輸出toString方法
????out.println?""
????out.println?"\t@Override"
????out.println?"\tpublic?String?toString()?{"
????out.println?"\t\treturn?\"TpApiConfig{\"?+"
????fields.each()?{
????????out.println?"\t\t\t\t\"${it.name}='\"?+?${it.name}?+?'\\''?+"
????}
????out.println?"\t\t\t\t'}';"
????out.println?"\t}"
????out.println?""
????out.println?"}"
}
def?calcFields(table)?{
????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
????????def?comm?=?[
????????????????colName?:?col.getName(),
????????????????name????:?javaName(col.getName(),?false),
????????????????type????:?typeStr,
????????????????commoent:?col.getComment(),
????????????????annos???:?"\t@Column(name?=?\""?+?col.getName()?+?"\"?)"]
????????if?("id".equals(Case.LOWER.apply(col.getName())))
????????????comm.annos?+=?["@Id"]
????????fields?+=?[comm]
????}
}
//?已經(jīng)修改為使用javaName,?如果有需要可以在def?className?=?javaName(table.getName(),?true)中修改為javaClassName
//?處理類名(這里是因?yàn)槲业谋矶际且詔_命名的,所以需要處理去掉生成類名時(shí)的開頭的T,
//?如果你不需要那么請(qǐng)查找用到了?javaClassName這個(gè)方法的地方修改為?javaName?即可)
def?javaClassName(str,?capitalize)?{
????def?s?=?com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
????????????.collect?{?Case.LOWER.apply(it).capitalize()?}
????????????.join("")
????????????.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/,?"_")
????//?去除開頭的T??http://developer.51cto.com/art/200906/129168.htm
????s?=?s[1..s.size()?-?1]
????capitalize?||?s.length()?==?1???s?:?Case.LOWER.apply(s[0])?+?s[1..-1]
}
def?javaName(str,?capitalize)?{
//????def?s?=?str.split(/(?<=[^\p{IsLetter}])/).collect?{?Case.LOWER.apply(it).capitalize()?}
//????????????.join("").replaceAll(/[^\p{javaJavaIdentifierPart}]/,?"_")
//????capitalize?||?s.length()?==?1??s?:?Case.LOWER.apply(s[0])?+?s[1..-1]
????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
}
static?String?changeStyle(String?str,?boolean?toCamel)?{
????if?(!str?||?str.size()?<=?1)
????????return?strif?(toCamel)?{
????????String?r?=?str.toLowerCase().split('_').collect?{?cc?->?Case.LOWER.apply(cc).capitalize()?}.join('')
????????return?r[0].toLowerCase()?+?r[1..-1]
????}?else?{
????????str?=?str[0].toLowerCase()?+?str[1..-1]
????????return?str.collect?{?cc?->?((char)?cc).isUpperCase()???'_'?+?cc.toLowerCase()?:?cc?}.join('')
????}
}
static?String?genSerialID()?{
????return?"\tprivate?static?final?long?serialVersionUID?=??"?+?Math.abs(new?Random().nextLong())?+?"L;"
}
表上右鍵, 選擇自己寫的腳本生成實(shí)體類
效果如下:
另
瑣碎時(shí)間想看一些技術(shù)文章,可以去公眾號(hào)菜單欄翻一翻我分類好的內(nèi)容,應(yīng)該對(duì)部分童鞋有幫助。同時(shí)看的過程中發(fā)現(xiàn)問題歡迎留言指出,不勝感謝~。另外,有想多了解哪些方面內(nèi)容的可以留言(什么時(shí)候,哪篇文章下留言都行),附菜單欄截圖(PS:很多人不知道公眾號(hào)菜單欄是什么)
END
我知道你 “在看”
總結(jié)
以上是生活随笔為你收集整理的groovy定义变量获取当前时间_IDEA不愧为神器,结合Groovy脚本,简直无敌!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 删除机器人 异星工厂_10个视频,它们是
- 下一篇: 对象存储使用案例_连云数据都有“对象存储