DEV Community

Geoff Bourne
Geoff Bourne

Posted on

Customize POJO generation from IntelliJ Database tool window

I was already a huge fan of IntelliJ Ultimate's Database Tool Window; however, today I found a gem hiding further down in the context menu: Scripted Extensions.

What brought me there in the first place was that I wanted to generate some bare-bones POJOs that were Lombok @Data annotated and had simple JPA @Column fields for use with JOOQ. IntelliJ Ultimate comes with a Scripted Extension, Generate POJOs.groovy, that got pretty close. So, I started with that and created a copy of that file...

Alt Text

...with this content:

import com.intellij.database.model.DasTable
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil
/*
* Derived from "Generate POJOs.groovy" provided by IntelliJ base install
* Available context bindings:
* SELECTION Iterable<DasObject>
* PROJECT project
* FILES files helper
*/
typeMapping = [
(~/(?i)int/) : "long",
(~/(?i)float|double|decimal|real/): "double",
(~/(?i)datetime|timestamp/) : "java.sql.Timestamp",
(~/(?i)date/) : "java.sql.Date",
(~/(?i)time/) : "java.sql.Time",
(~/(?i)/) : "String"
]
nullables = [
'long': 'Long',
'double': 'Double'
]
FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { File dir ->
def packageName = "fixme"
def srcMainJavaIndex = dir.path.indexOf("src/main/java/")
if (srcMainJavaIndex >= 0) {
packageName = dir.path.substring(srcMainJavaIndex+14)
.replaceAll("[/\\\\]", ".")
}
SELECTION.filter { it instanceof DasTable }.each { generate(it, dir, packageName) }
}
def generate(table, File dir, packageName) {
String className = javaName(table.getName(), true)
def fields = calcFields(table)
new File(dir, className + ".java").withPrintWriter { out -> generate(out, packageName, className, fields) }
}
static def generate(out, packageName, className, fields) {
out.println "package $packageName;"
out.println ""
out.println "import javax.persistence.Column;"
out.println "import lombok.Data;"
out.println ""
out.println "@Data"
out.println "public class $className {"
fields.each() {
if (it.annos != "") out.println " ${it.annos}"
out.println " ${it.type} ${it.name};"
}
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
// nullable and primitive?
if (!col.notNull && nullables.containsKey(typeStr)) {
typeStr = nullables.get(typeStr)
}
def columnParams = [
"name = \"${col.getName()}\""
]
if (col.notNull) {
columnParams += "nullable = false"
}
//noinspection GroovyUnusedAssignment
fields += [[
name : javaName(col.getName(), false),
type : typeStr,
annos: "@Column(${columnParams.join(", ")})"]]
}
}
def javaName(str, capitalize) {
String s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
if (s == "Class") {
s = "TheClass"
}
capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

Now I can select tables, right-click, and run the extension:

Alt Text

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay