How to Auto‑Generate JPA Entity Classes in IntelliJ IDEA Using Groovy Scripts
This guide walks you through connecting IntelliJ IDEA to a database, using its built‑in POJO generators, adding JPA modules, and creating custom Groovy scripts to produce fully annotated JPA entity classes, complete with getters, setters, and utility methods.
Introduction
Many IDEs and plugins can automatically generate data entity classes from database tables; this article explains how to use IntelliJ IDEA's Groovy script feature to generate JPA‑annotated entity classes.
1. Connect IDEA to a Database
Only the Ultimate edition of IDEA provides this feature; the Community edition does not. The screenshots were taken with IDEA 2018.3, so the UI may differ slightly in other versions.
Create a New Data Connection
Open the Database tool window via View → Tool Windows → Database if it is not already visible.
The same steps apply to Oracle databases.
Configure the Data Connection
Enter any connection name.
Leave the driver selection as default.
Provide the database IP (e.g., localhost or 127.0.0.1).
Enter the port (default 3306 for MySQL).
Specify the database name, username, and password.
Download the required driver if prompted.
Test the connection; ensure the MySQL service is running for local connections.
2. IDEA’s Two Built‑in Ways to Create Entity Classes
(1) Generate simple POJOs (properties, getters, setters) without JPA/Hibernate annotations.
Open the created data connection.
Navigate to the schema and select the tables (Ctrl/Shift for multi‑select).
Right‑click → Scripted Extensions → Generate POJOs.groovy.
Choose the output directory.
Generated classes may have a default package name (e.g., com.sample ) that you need to adjust manually.
(2) Generate JPA‑annotated entities using the Persistence tool.
Add the JPA module: File → Project Structure → Modules → + → JPA → Apply.
Use Persistence → Generate Persistence Mapping → By Database Schema, then select the connection, target package, tables, and fields. Check the option to generate annotated entities.
3. Advanced: Use Your Own Groovy Script to Generate Annotated Entities
The two built‑in methods have trade‑offs: simple POJOs lack JPA annotations, while the Persistence tool may generate unwanted system tables and restrict output locations. By customizing the Groovy script you can overcome these limitations.
Benefits of a Custom Groovy Script
Operate directly from the Database tool window.
Fully customize the generated code to meet project conventions.
Avoid system tables when working with databases like Oracle.
Choose any output directory on your machine.
Drawbacks
Author name in @author must be edited manually.
Schema attribute in @Table may need manual adjustment.
Primary‑key generation strategy is not automatically inferred.
Extending the Script
Add hashCode() and equals() generation.
Create a New Groovy Script
In the Database tool window, right‑click → Scripted Extensions → Go to Scripts Directory, then create GenerateMyPOJOs.groovy.
Paste the following script (the core logic is unchanged; modify author name, schema, and other placeholders as needed):
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 = ""
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) }
}
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;"
def 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 "/**
* @Description
* @Author idea
* @Date " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "
*/"
out.println "@Entity"
out.println "@Table(name=\"${table.getName()}\", schema=\"\")"
out.println "public class $className implements Serializable {"
out.println ""
out.println genSerialID()
fields.each { field ->
out.println ""
if (isNotEmpty(field.commoent)) {
out.println "\t/**"
out.println "\t * ${field.commoent}"
out.println "\t */"
}
if (field.annos.contains("[@Id]")) out.println "\t@Id"
if (field.annos != "") out.println "\t${field.annos.replace("[@Id]", "")}"
out.println "\tprivate ${field.type} ${field.name};"
}
// getters and setters
fields.each { field ->
out.println ""
out.println "\tpublic ${field.type} get${field.name.capitalize()}() {"
out.println "\t return this.${field.name};"
out.println "\t}"
out.println ""
out.println "\tpublic void set${field.name.capitalize()}(${field.type} ${field.name}) {"
out.println "\t this.${field.name} = ${field.name};"
out.println "\t}"
}
// toString
out.println ""
out.println "\t@Override"
out.println "\tpublic String toString() {"
out.println "\t return \"${className}{\" +"
fields.each { f ->
out.println "\t \"${f.name}='\" + ${f.name} + \'\'\" +"
}
out.println "\t \"}\";"
out.println "\t}"
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]
}
}
def javaName(str, capitalize) {
def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
return 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 genSerialID() {
return "\tprivate static final long serialVersionUID = " + Math.abs(new Random().nextLong()) + "L;"
}After saving the script, right‑click a table in the Database view and select your script to generate the annotated entity class.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
