[JAVA] I made a source that automatically generates JPA Entity class files

Introduction

As the title says, this time I made an application that generates Java files of Entity class! It has been confirmed to work with OracleDB11g2R and MySQL.

Test.java


import java.util.ArrayList;

import annotation.Entity;
import annotation.Table;
import annotation.column;
import annotation.id;

@Entity
@Table("test")//The table name registered in the DB is displayed.
public class Test {

	@id//Primary key
	@column//column
	private String num;

	@column//column
	private String namename;

	public void setNum(String num) {
		this.num = num;
 	}

	public String getNum() {
		return this.num;
 	}

	public void setNamename(String namename) {
		this.namename = namename;
 	}

	public String getNamename() {
		return this.namename;
 	}

}

Environment (appropriate)

Configuration (super overview)

name of the class Description
EntityGenerator A class that creates JavaFile and writes the contents of the file while calling the following class
DBReader Class that connects to DB and fetches metadata (table list, column name, primary key etc...)
DataTypeMapper Class that converts column data type to DB data type → java data type
EntityInfo Class to store the information acquired by DBReader
annotation group @Table, @Id, @column

Source

EntityGenerator

interface

EntityGenerator.java



package entityCreater.generator;

public interface EntityGenerator {

	void generateEntity();

}

Implementation class

EntityGeneratorImplements.java



package entityCreater.generator;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import entityCreater.info.EntityInfo;
import entityCreater.reader.DBReaderImplements;

public class EntityGeneratorImplements implements EntityGenerator{

	//Where to save the file
	String filePlace;

	/**
	 *constructor
	 */
	public EntityGeneratorImplements(String filePlace) {
		this.filePlace = filePlace;
	}

	/**
	 *Entity creation method
	 */
	@Override
	public void generateEntity() {
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		System.out.println("Start EntityFile creation method");

		ArrayList<EntityInfo> entityInfos = new DBReaderImplements().read();
		for(EntityInfo ei : entityInfos) {
			createFile(ei);
		}
	}


	/**
	 *EntityFile creation method
	 * @param entityInfo
	 */
	private void createFile(EntityInfo entityInfo) {
    	//Get DB table information
    	String tableName = entityInfo.getTableName();
    	String id = entityInfo.getId();
    	List<String[]> columns = entityInfo.getColumns();

    	//Generate class name
    	String className = tableName.substring(0, 1).toUpperCase() + tableName.substring(1).toLowerCase();

		//EntityFile class
		File entityFile = new File(filePlace + "/" + className + ".java");

		try{
			if (entityFile.createNewFile()){
				System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		    	System.out.println("The file was created successfully.");
		    }else{
		    	System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		    	System.out.println("Failed to create file");
		    }
		}catch(IOException e){
		    System.out.println(e);
		}

		//Create the contents of File
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
    	System.out.println("Create the contents of the file.");

    	try(PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(entityFile, true)));) {

    		//Annotation import statement
    		pw.println("import annotation.Entity;");
    		pw.println("import annotation.Table;");
    		pw.println("import annotation.id;");
    		pw.println("import annotation.column;");
    		pw.println("");

    		//Class declaration(start)
    		pw.println("@Entity");
    		pw.println("@Table(\"" + tableName + "\")");
    		pw.println("public class " + className + " {");
    		pw.println("");

    		//Column declaration
    		Iterator<String[]> it = columns.iterator();

    		while(it.hasNext()) {
    			String[] colum = it.next();

    			//Column declaration
    			if(colum[1].equals(id)) {
    	    		pw.println("	@id");
    			}
    			pw.println("	@column");
        		pw.println("	private " + colum[0] + " " + colum[1] + ";");
        		pw.println("");

    		}

    		//Setter.Getter Declaration
    		//Put Iterator back
    		it = columns.iterator();

    		while(it.hasNext()) {
    			String[] colum = it.next();

    			//Setter declaration
    			pw.println("	public void set" + colum[1].substring(0, 1).toUpperCase() + colum[1].substring(1).toLowerCase() + "(" + colum[0] + " " + colum[1] + ") {");
    			pw.println("		this." + colum[1] + " = " + colum[1] + ";");
    			pw.println(" 	}");
    			pw.println("");

    			//Getter Declaration
    			pw.println("	public " + colum[0] + " get" + colum[1].substring(0, 1).toUpperCase() + colum[1].substring(1).toLowerCase() + "() {");
    			pw.println("		return this." + colum[1] + ";");
    			pw.println(" 	}");
    			pw.println("");
    		}

    		//Class declaration(End)
    		pw.println("}");

			//End display
			System.out.println(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
	    	System.out.println("*************************************************************");
	    	System.out.println("***Add the SUCCESS package declaration and multiplicity declaration.***");
	    	System.out.println("*************************************************************");

		} catch (IOException e) {
			e.printStackTrace();
		}finally {

		}
	}


}

DBReader interface

DBReader.java


package entityCreater.reader;

import java.util.ArrayList;

import entityCreater.info.EntityInfo;

public interface DBReader {

	ArrayList<EntityInfo> read();
}

Implementation class

DBReaderImplements.java


package entityCreater.reader;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;

import container.DBConfig;
import container.EnvironmentConfigReader;
import db_access.DBAccess;
import entityCreater.dataTypeMapper.DataTypeMapper;
import entityCreater.info.EntityInfo;

public class DBReaderImplements implements DBReader{

	@Override
	public ArrayList<EntityInfo> read() {

		//For storing metadata
		ResultSet rs = null;

		//For storing Table information
		ArrayList<String> tableNames = new ArrayList<>();

		//For storing Entity information
		ArrayList<EntityInfo> entityInfos = new ArrayList<>();

		//Get DB settings
                /*
          *Don't worry too much about the following ranges.
          *Get the DB connection information (URL, PASSWORD, etc.) from your own yaml file,
          *I'm just getting the Connection with the DB inside the DBAccess class.
          *The source of EnvironmentConfigReader and DBAccess is described for reference.
          */

               /*
               *from here
               */
		EnvironmentConfigReader ecr = new EnvironmentConfigReader();
		DBConfig dbc = ecr.read();

		String dbName = dbc.getDbName();

		//Establishing a connection
		DBAccess dba = new DBAccess(dbc);

               /*
               *So far
               */

		try {

			//Connection with database
			Connection con = dba.getConnection();

			//Get database metadata
			DatabaseMetaData dbmd = con.getMetaData();

			//Get Table name
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Get Table list");
			String[] types = { "TABLE", "VIEW", "SYSTEM TABLE" };
			rs = dbmd.getTables(dbName, null, "%", types);
			while (rs.next()) {
				String tableName = rs.getString("TABLE_NAME");

				//Storage of Table name
				tableNames.add(tableName);
			}

			//Classes for storing Table information
			Iterator<String> tableNameList = tableNames.iterator();
			String tableName;
			String id = null;
			ArrayList<String[]> columns;

			while (tableNameList.hasNext()) {

				//Get TableName
				tableName = tableNameList.next();

				System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
				System.out.println("Table name:" + tableName + "Generate Entity class of");

				//Get all column information of Table
				System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
				System.out.println("Table name:" + tableName + "Get all column information of");
				rs = dbmd.getColumns(dbName, null, tableName, "%");

				//For column storage
				columns = new ArrayList<>();
				while (rs.next()) {
					//Convert from SQL data type to Java data type
					String dataType = DataTypeMapper.dataTypeChange(rs.getString("TYPE_NAME"));

					//Convert variable names to lowercase
					String columnName = rs.getString("COLUMN_NAME").toLowerCase();

					String[] column = { dataType, columnName };
					columns.add(column);
				}

				//Get Primary Key
				System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
				System.out.println("Table name:" + tableName + "Get the Primary Key of");
				ResultSet primaryKeys = dbmd.getPrimaryKeys(dbName, null, tableName);
				if (primaryKeys.next()) {
					System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
					System.out.println("Table name:" + tableName + "Primary Key" + primaryKeys.getString("COLUMN_NAME") + "is");
					id = primaryKeys.getString("COLUMN_NAME").toLowerCase();
				}

				System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
				System.out.println("Table information is stored in EntityInfo class");
				//Table information storage class
				EntityInfo ei = new EntityInfo();

				//Set TableName in the table information storage class
				ei.setTableName(tableName);
				//Set id in Table information storage class
				ei.setId(id);
				//Set column information in Table information storage class
				ei.setColumns(columns);

				entityInfos.add(ei);
			}

			rs.close();

			//Database close
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Discard the connection with the DB");
			con.close();

		} catch (Exception e) {
			System.out.println("Exception occurred");
			e.printStackTrace();
		}
		return entityInfos;
	}

}

DataTypeMapper

DataTypeMapper.java



package entityCreater.dataTypeMapper;

public class DataTypeMapper {

	/**
	 *A class that converts SQL data types to Java data types
	 * @param sqlDataType
	 * @return
	 */
	public static String dataTypeChange(String sqlDataType) {

		String javaDataType = null;

		switch (sqlDataType) {
		case "CHAR":
		case "VARCHAR":
		case "LONGVARCHAR":
			javaDataType = "String";
			break;
		case "NUMERIC":
		case "DECIMAL":
			javaDataType = "java.math.BigDecimal";
			break;
		case "BIT":
			javaDataType = "boolean";
			break;
		case "TINYINT":
			javaDataType = "byte";
			break;
		case "SMALLINT":
			javaDataType = "short";
			break;
		case "INTEGER":
		case "INT":
			javaDataType = "Integer";
			break;
		case "BIGINT":
			javaDataType = "long";
			break;
		case "REAL":
			javaDataType = "float";
			break;
		case "FLOAT":
		case "DOUBLE":
			javaDataType = "double";
			break;
		case "BINARY":
		case "VARBINARY":
		case "LONGVARBINARY":
			javaDataType = "byte[]";
			break;
		case "DATE":
			javaDataType = "java.sql.Date";
			break;
		case "TIME":
			javaDataType = "java.sql.Time";
			break;
		case "TIMESTAMP":
			javaDataType = "java.sql.Timestamp";
			break;
		default:
			break;
		}

		return javaDataType;

	}

}

EntityInfo

EntityInfo.java



package entityCreater.info;

import java.util.List;

/**
 *
 *Entity information storage class
 * @author okamotoyuuma
 *
 */
public class EntityInfo {

	//table name
	private String tableName;

	//Primary Key name
	private String id;

	//All column names and types
	private List<String[]> columns;

	/**
	 * (non-javadoc)
	 * getter setter
	 * @return
	 */

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public List<String[]> getColumns() {
		return columns;
	}

	public void setColumns(List<String[]> columns) {
		this.columns = columns;
	}

}

Annotation

@Table annotation (class that stores table name in attribute)

Table.java


package annotation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Target(TYPE)
@Retention(RUNTIME)
public @interface Table {

	String value();

}

@id annotation (assigned to the primary key field)

id.java


package annotation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(FIELD)
public @interface id {

}

@columnn annotation (added to the column value of the table)

column.java


package annotation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(FIELD)
public @interface column {

}

How to use

Create a Main method and specify the location to store the generated Entity class as shown below.

main.java



public class main {

	public static void main(String[] args) {
               EntityGenerator eg = new EntityGeneratorImplements("Destination path");
               eg.generateEntity();
	}

}

Finally

This time I tried to automatically generate the Entity class. The source and logic are still immature and childish, but it was a very good experience because I had never created a file! If you have any suggestions for points that have not been taken into consideration or improvements in the source, please leave a comment.

Since the DB setting file and the class to be read are listed in the following reference section, which are not listed in the above source. If you are interested, please take a look.

Reference (DB setting YAML file and class to read the setting file, etc.)

DB configuration file

DBProfile.yaml



#DB settings
!!container.DBConfig #DB definition setting class path
driver: com.mysql.cj.jdbc.Driver #driver name
url: jdbc:mysql://localhost:3306/DB name#DB URL
user:DB username#DB user
password: password #DB password
numberOfAccess: 10 #Number of connections
dbName:Database name#DB name
dbType: MySQL #DB type (only MySQL and Oracle DB are supported this time)
schema:Schema name

Class for storing setting information

DBConfig.java



package container;

//Database configuration file
public class DBConfig {

	//Driver name
	String driver;

	//DB URL
	String url;

	//DB user
	String user;

	//password
	String password;

	//Schema name
	String schema;

	//Number of established connections
	int numberOfAccess;

	//DBName
	String dbName;

	//DBType
	String dbType;

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSchema() {
		return schema;
	}

	public void setSchema(String schema) {
		this.schema = schema;
	}

	public int getNumberOfAccess() {
		return numberOfAccess;
	}

	public void setNumberOfAccess(int numberOfAccess) {
		this.numberOfAccess = numberOfAccess;
	}

	public String getDbName() {
		return dbName;
	}

	public void setDbName(String dbName) {
		this.dbName = dbName;
	}

	public String getDbType() {
		return dbType;
	}

	public void setDbType(String dbType) {
		this.dbType = dbType;
	}

}


EnvironmentConfigReader class that reads the above configuration file

EnvironmentConfigReader.java



package container;

import org.yaml.snakeyaml.Yaml;

public class EnvironmentConfigReader implements Reader<DBConfig>{

	//DB configuration file
	static String configFileName = "DBProfile.yaml";

	//Method to get DB settings from yaml file(No arguments)
	@Override
	public DBConfig read() {
		//Log generation location
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		//Processing content
		System.out.println(configFileName + "Will start loading.");

		Yaml yaml = new Yaml();
		DBConfig dbc = (DBConfig) yaml.load(getClass().getResourceAsStream(configFileName));

		//Log generation location
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		//Processing content
		System.out.println(configFileName + "Has been loaded.");

		return dbc;
	}

	//Method to get DB settings from yaml file(With arguments)
	@Override
	public DBConfig read(String setConfigFileName) {
		//Log generation location
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		//Processing content
		System.out.println(configFileName + "Will start loading.");

		//Set the specified file name
		if (configFileName != null) {
			configFileName = setConfigFileName;
		}

		Yaml yaml = new Yaml();
		DBConfig dbc = (DBConfig) yaml.load(getClass().getResourceAsStream(configFileName));

		//Log generation location
		System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
		//Processing content
		System.out.println(configFileName + "Has been loaded.");

		return dbc;
	}

}

Class that stores the connection with DB

DBAccess.java



package db_access;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import container.DBConfig;

public class DBAccess {

	//member
	private Connection conn = null;

	public DBAccess(DBConfig dbc) {
		try {
			Class.forName(dbc.getDriver());
			conn = DriverManager.getConnection(dbc.getUrl(), dbc.getUser(), dbc.getPassword());
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Connected to DB");
			//Auto commit OFF
			conn.setAutoCommit(false);
		} catch (SQLException | ClassNotFoundException e) {//Failed to establish connection
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Failed to connect to DB");
			e.printStackTrace();
		}
	}

	//Distribute the connection
	public Connection getConnection() {
		return conn;
	}

	//Break connection
	public void closeConnection() {
		try {
			conn.close();
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Disconnected from DB");
		} catch (SQLException e) {
			//TODO auto-generated catch block
			System.out.print(Thread.currentThread().getStackTrace()[1].getClassName() + ":");
			System.out.println("Could not disconnect from DB");
			e.printStackTrace();
		}
	}
}

Recommended Posts

I made a source that automatically generates JPA Entity class files
I made a class that automatically generates Json that specifies Minecraft texture etc. [1.12.2]
I made a class that can use JUMAN and KNP from Java
I made a Diff tool for Java files
I made a viewer app that displays a PDF
Simple note: IntelliJ automatically generates Entity class from database
I made a library that works like a Safari tab !!
I made a Wrapper that calls KNP from Java
Item 25: Limit source files to a single top-level class
I made a JAVA framework "numatrix" that easily generates unique numbers in a distributed environment & multithreading.
I made a mod that instantly calls a vehicle with Minecraft
I made a chat app.
I made a question that can be used for a technical interview
Ruby: I made a FizzBuzz program!
Automatically generate jpa entity using Gradle
I made a shopify app @java
I made a GUI with Swing
I made a simple recommendation function.
I made a matching app (Android app)
I made a package.xml generation tool.
[Android] I made a pedometer app.
I made a site that summarizes information on carbohydrate restriction with Vue.js