首先是项目引入JPA
然后配置idea对应的mysql数据源
上面两步教程很多,搜一下就好了,比较简单
网上生成Q文件总有各种配置,其实Q文件是有自己的规则的,自己生成即可,idea的数据库映射实体生成刚好可以做到同步生成Q文件,我修改了自带的groovy文件,可以同时生成映射实体和Q文件,直接给代码了,
生成方式如下图,右键选择一张数据库表,也可以选多张表,右键列表执行groovy脚本,这个脚本生成的不对,使用我下面修改过的替换一下即可
下面是Generate POJOs.groovy文件的代码,可以直接搜索到该文件,复制之后再按上面的操作生成即可,下面的代码还可以根据自己需要生成其他代码,比如我的Generate Repository.groovy就是用来生成持久层接口和实现类的
import com.intellij.database.model.DasTable 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<DasObject> * PROJECT project * FILES files helper */ packageName = "com.sample;" typeMapping = [ // (~/(?i)tinyint/) : ["Boolean","BooleanPath","createBoolean",""], (~/(?i)bigint/) : ["Long","NumberPath","createNumber","Long.class"], (~/(?i)tinyint|smallint|mediumint|int/) : ["Integer","NumberPath","createNumber","Integer.class"], (~/(?i)real/) : ["Double","NumberPath","createNumber","Double.class"], (~/(?i)float|double|decimal/) : ["BigDecimal","NumberPath","createNumber","BigDecimal.class"], (~/(?i)longblob|blob|mediumblob/) : ["Byte[]","ArrayPath","createArray","Byte.class"], (~/(?i)datetime|timestamp/) : ["java.time.LocalDateTime","DateTimePath","createDateTime","java.time.LocalDateTime.class"], (~/(?i)date/) : ["java.time.LocalDate","DateTimePath","createDateTime","java.time.LocalDate.class"], (~/(?i)time/) : ["java.time.LocalTime","DateTimePath","createDateTime","java.time.LocalTime.class"], (~/(?i)/) : ["String","StringPath","createString",""] ] keywords = ["abstract", "assert", "boolean", "break", "byte", "case", "catch", "char","const", "continue", "default", "do", "double", "else", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" ] 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) File file = new File(dir,className + ".java") PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) printWriter.withPrintWriter { out -> generate(out, className, fields, table) } // 单独生成Q文件 printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, "Q"+className + ".java")), "UTF-8")) printWriter.withPrintWriter { out -> generateQ(out, className, fields, table) } // 生成mapstruct文件 // 获取绝对路径 // printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir+"/mapstruct", className + "Mapstruct.java")), "UTF-8")) // printWriter.withPrintWriter { out -> generateMapstruct(out, className) } // 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 lombok.*;" 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;" out.println "import org.hibernate.annotations.DynamicInsert;" out.println "import org.hibernate.annotations.DynamicUpdate;" Set types = new HashSet() fields.each() { types.add(it.type) } if (types.contains("Date")) { out.println "import java.util.Date;" } if (types.contains("BigDecimal")) { out.println "import java.math.BigDecimal;" } if (types.contains("InputStream")) { out.println "import java.io.InputStream;" } out.println "" out.println "/**" out.println " * <pre>" out.println " * CREATE TABLE `"+table.getName()+"` (" // 输出建表语句注释 fields.each() { out.println " * `${it.realName}` ${it.dataType} COMMENT `${it.commoent.toString()}` " } out.println " * )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC " out.println " * </pre>" out.println "" out.println " * @Description \n" + " * @Author system\n" + //1. 修改idea为自己名字 " * @Date " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " \n" + " */" out.println "" out.println "@Data" out.println "@AllArgsConstructor" out.println "@NoArgsConstructor" out.println "@Builder(toBuilder = true)" out.println "@DynamicInsert" out.println "@DynamicUpdate" out.println "@Entity" out.println "@Table(name =\"" + table.getName() + "\" )" //2. schema = \"后面添加自己的表空间名称(mysql可以不添加, 不用这个schema属性也行) out.println "@org.hibernate.annotations.Table(appliesTo = \""+table.getName()+"\" , comment = \""+table.getName()+"\")" out.println "public class $className implements Serializable {" out.println "" out.println genSerialID() // 生成一个固定的Q对象,兼容老版本public final static QAgentDeviceType Q = QAgentDeviceType.Q; out.println "" out.println "\tpublic final static Q$className Q = Q$className"+".Q;" 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.realName};" } // // 输出get/set方法,使用了lombok的时候不用 // fields.each() { // out.println "" // out.println "\tpublic ${it.type} get${it.name.capitalize()}() {" // out.println "\t\treturn this.${it.realName};" // out.println "\t}" // out.println "" // // out.println "\tpublic void set${it.name.capitalize()}(${it.type} ${it.realName}) {" // out.println "\t\tthis.${it.realName} = ${it.realName};" // out.println "\t}" // } // 输出toString方法 out.println "" out.println "\t@Override" out.println "\tpublic String toString() {" out.println "\t\treturn \"{\" +" def size = fields.size def index = 0 def priValue fields.each() { index++ priValue = it.realName if(!(it.type.equals("Long") ||it.type.equals("Integer") || it.type.equals("Double") || it.type.equals("BigDecimal"))){ priValue = "\"\\\"\" + ("+it.realName+"==null?\"\":${it.realName}) + \"\\\"\"" } out.println "\t\t\t\t\"\\\"${it.name}\\\":\" + " + priValue + ((index != size)?" + \",\" + ":" +") } out.println "\t\t\t\t\"}\";" out.println "\t}" // 输出字段常量 out.println "" out.println "\t/**\n" + "\t * JPA FIELD \n" + "\t * \n"+ "\t * @Author system\n" + //1. 修改idea为自己名字 "\t */" out.println "\tpublic interface Field {" fields.each() { // 输出注释 if (isNotEmpty(it.commoent)) { out.println "\t\t/**" out.println "\t\t * ${it.commoent.toString()}" out.println "\t\t *" out.println "\t\t * @See" +className +"#${it.name}" out.println "\t\t */" }else{ out.println "" } // 输出成员变量 out.println "\t\t String ${it.colName.toUpperCase()} = \"${it.name}\";" } out.println "\t}" out.println "" out.println "}" } def generateQ(out, className, fields, table) { def QclassName = "Q"+className out.println "package $packageName" out.println "" out.println "import com.querydsl.core.types.Path;" out.println "import com.querydsl.core.types.PathMetadata;" out.println "import com.querydsl.core.types.dsl.EntityPathBase;" out.println "import com.querydsl.core.types.PathMetadataFactory;" out.println "import com.querydsl.core.types.dsl.DateTimePath;" out.println "import com.querydsl.core.types.dsl.NumberPath;" out.println "import com.querydsl.core.types.dsl.StringPath;" out.println "import com.querydsl.core.types.dsl.BooleanPath;" out.println "import lombok.Setter;" out.println "import lombok.Getter;" Set types = new HashSet() fields.each() { types.add(it.type) } if (types.contains("Date")) { out.println "import java.util.Date;" } if (types.contains("BigDecimal")) { out.println "import java.math.BigDecimal;" } if (types.contains("InputStream")) { out.println "import java.io.InputStream;" } out.println "" out.println "/**\n" + " * @Description \n" + " * @Author system\n" + //1. 修改idea为自己名字 " * @Date " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " \n" + " */" out.println "@Setter" out.println "@Getter" out.println "public class Q$className extends EntityPathBase<$className> {" out.println "" out.println genSerialID() out.println "" out.println "\tpublic static final $QclassName Q = new $QclassName(\""+ javaName(className, false) +"\");" fields.each() { out.println "" // 输出注释 if (isNotEmpty(it.commoent)) { out.println "\t/**" out.println "\t * ${it.commoent.toString()}" out.println "\t *" out.println "\t * @See "+className +"#${it.name}" out.println "\t */" }else{ out.println "" } // 输出成员变量 if("".equals(it.mehtodParam)){ out.println "\tpublic final ${it.typePath} ${it.name} = this.${it.createMethod}(\"${it.name}\");" }else{ out.println "\tpublic final ${it.typePath}<${it.type}> ${it.name} = this.${it.createMethod}(\"${it.name}\", ${it.mehtodParam});" } } // 输出固定实现的三个方法 out.println "" out.println " public Q$className(String variable) {" out.println " super($className"+".class, PathMetadataFactory.forVariable(variable));" out.println " }" out.println "" out.println " public Q$className(Path<? extends $className> path) {" out.println " super(path.getType(), path.getMetadata());" out.println " }" out.println "" out.println " public Q$className(PathMetadata metadata) {" out.println " super($className"+".class, metadata);" out.println " }" out.println "" out.println "}" } def generateMapstruct(out, className, fields, table) { def interfaceName = className+"Mapstruct"; out.println "package $packageName" out.println "" out.println "import org.mapstruct.Mapper;" + out.println "import org.mapstruct.factory.Mappers;" out.println "" out.println "/**\n" + " * @Description \n" + " * @Author system\n" + //1. 修改idea为自己名字 " * @Date " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " \n" + " */" out.println "@Mapper" out.println "public interface $interfaceName {" out.println "" out.println "$interfaceName MAPPER = Mappers.getMapper(" + interfaceName +".class);" out.println "}" } def calcFields(table) { def haveId = false 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[0], commoent: col.getComment(), annos : "\t@Column(name = \"`" + col.getName() + "`\" ,columnDefinition = \""+col.getDataType()+" COMMENT '"+col.getComment()+"'\" )", dataType: col.getDataType(), typePath: typeStr[1], createMethod: typeStr[2], mehtodParam : typeStr[3] ] if(keywords.any { it -> it.equals(comm.name) }){ comm.realName = comm.name+"_" }else{ comm.realName = comm.name } // 默认第一个字段为主键 if (!haveId ){ comm.annos += ["@Id"] haveId = true } fields += [comm] } } // 这里是处理数据库表前缀的方法,这里处理的是t_xxx命名的表 // 已经修改为使用javaName, 如果有需要可以在def className = javaName(table.getName(), true)中修改为javaClassName // 处理类名(这里是因为我的表都是以t_命名的,所以需要处理去掉生成类名时的开头的T, // 如果你不需要去掉表的前缀,那么请查找用到了 javaClassName这个方法的地方修改为 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 str if (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('') } } //生成序列化的serialVersionUID static String genSerialID() { return "\tprivate static final long serialVersionUID = " + Math.abs(new Random().nextLong()) + "L;" }