Tuesday, 6 June 2017

Reverse Engineering : Generate Java Persistence Entity from Database

If there is already an existing database , then we could use some reverse engineering tool to automatically generate java persistence entity classes.

You may find below 2 ways from internet :
1. hibernate*-maven-plugin
2. IDE based reverse engine tools

This post would show you how to do it programmatically.





STEP 1 : Create a Maven Project with Below pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.junjun.util</groupId>
<artifactId>db-to-java</artifactId>
<version>1.0.0</version>
<properties>
<version.java>1.8</version.java>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-tools</artifactId>
<version>5.2.3.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${version.java}</source>
<target>${version.java}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
view raw pom.xml hosted with ❤ by GitHub



Note :

1. it is org.hibernate:hibernate-tool provides us everything we need to generate java code from database, and it needs org.hibernate:hibernate-core.

2. we use com.h2database:h2 as database for demo purpose , you may use mysql/sql server/oracle or whatever relational database.

3. spring boot is in the pom.xml is because in case you want to see database tables you can use web based H2 console easily.






STEP 2 : Create Service for Generating Java Code from Database


package org.junjun.util.java.service;
public interface ReverseEngineService {
Boolean databaseToJava();
}

package org.junjun.util.java.service;
import java.io.File;
import org.apache.log4j.Logger;
import org.hibernate.tool.ant.Hbm2JavaExporterTask;
import org.hibernate.tool.ant.HibernateToolTask;
import org.hibernate.tool.ant.JDBCConfigurationTask;
import org.springframework.stereotype.Service;
@Service
public class ReverseEngineServiceImpl implements ReverseEngineService {
private static final Logger log = Logger.getLogger(ReverseEngineServiceImpl.class);
public Boolean databaseToJava() {
Boolean done = Boolean.TRUE;
try {
final File destDir = new File("src/main/java");
final File hibernateConfig = new File("src/main/resources/hibernate.cfg.xml");
final HibernateToolTask persistenceGenerator = new HibernateToolTask();
persistenceGenerator.setDestDir(destDir);
final JDBCConfigurationTask jdbcConfiguration = persistenceGenerator.createJDBCConfiguration();
jdbcConfiguration.setConfigurationFile(hibernateConfig);
jdbcConfiguration.setDetectManyToMany(true);
jdbcConfiguration.setDetectOneToOne(true);
jdbcConfiguration.setPackageName("org.junjun.util.java.persistence");
jdbcConfiguration.execute();
final Hbm2JavaExporterTask hbm2Java = (Hbm2JavaExporterTask) persistenceGenerator.createHbm2Java();
hbm2Java.setJdk5(Boolean.TRUE);
hbm2Java.setEjb3(Boolean.TRUE);
hbm2Java.setDestdir(destDir);
hbm2Java.validateParameters();
hbm2Java.execute();
} catch (Exception e) {
log.error(e.getMessage(), e);
done = Boolean.FALSE;
}
return done;
}
}

Note :

1. it is org.hibernate.tool.ant.Hbm2JavaExporterTask class generates java code as class name suggested.

2. you may have a look at classes under package org.hibernate.tool.ant to see what other reverse engineering tasks are available


 





STEP 3 : Create Application Launcher and Configuration

package org.junjun.utl.java;
import org.junjun.util.java.service.ReverseEngineService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class AppLauncher {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(AppLauncher.class, args);
ReverseEngineService service = ctx.getBean(ReverseEngineService.class);
service.databaseToJava();
ctx.close();
System.exit(0);
}
}


package org.junjun.utl.java.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan(basePackages = { "org.junjun.util.java" })
@Configuration
public class AppConfig {
}
view raw AppConfig.java hosted with ❤ by GitHub


server.port = 9001
spring.datasource.url=jdbc:h2:mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.path=/h2
spring.h2.console.enabled=true
spring.datasource.initialize=true
spring.datasource.schema=classpath:/schema.sql
spring.datasource.data=classpath:/data.sql
#logging.level.org.springframework=DEBUG
logging.level.org.hibernate=DEBUG



<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.H2Dialect
</property>
<property name="hibernate.connection.driver_class">
org.h2.Driver
</property>
<property name="hibernate.connection.url">
jdbc:h2:mem:mydb
</property>
<property name="hibernate.default_schema">TEST</property>
<property name="hibernate.connection.username">
sa
</property>
<property name="hibernate.connection.password"></property>
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
Note :

1. we use org.springframework.boot:spring-boot-starter-jdbc to initialize the database

2. based on  above configuration h2 console would be accessible here http://localhost:9001/h2/






STEP 4 : Add Database Scripts to Create Tables for Demo

CREATE SCHEMA IF NOT EXISTS TEST;
CREATE TABLE TEST.USER
(
ID NUMBER(19) NOT NULL,
NAME VARCHAR2(50) NOT NULL
);
ALTER TABLE TEST.USER ADD PRIMARY KEY (ID);
CREATE TABLE TEST.ROLE
(
ID NUMBER(19) NOT NULL,
NAME VARCHAR2(50) NOT NULL,
FK_USER_ID NUMBER(19) NOT NULL
);
ALTER TABLE TEST.ROLE ADD PRIMARY KEY (ID);
ALTER TABLE TEST.ROLE
ADD CONSTRAINT ROLE_USER_FK FOREIGN KEY (FK_USER_ID)
REFERENCES TEST.USER ;


On startup , Spring Boot would automatically run schema.sql and data.sql as configured with STEP 3 application.properties.







STEP 5 : Run AppLauncher , then System Would Generate Java Source Code as Below

package org.junjun.util.java.persistence;
// Generated Jun 6, 2017 10:36:31 PM by Hibernate Tools 5.2.3.Final
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* User generated by hbm2java
*/
@Entity
@Table(name="USER"
,catalog="MYDB"
)
public class User implements java.io.Serializable {
private BigDecimal id;
private String name;
private Set<Role> roles = new HashSet<Role>(0);
public User() {
}
public User(BigDecimal id, String name) {
this.id = id;
this.name = name;
}
public User(BigDecimal id, String name, Set<Role> roles) {
this.id = id;
this.name = name;
this.roles = roles;
}
@Id
@Column(name="ID", unique=true, nullable=false, scale=0)
public BigDecimal getId() {
return this.id;
}
public void setId(BigDecimal id) {
this.id = id;
}
@Column(name="NAME", nullable=false, length=50)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(fetch=FetchType.LAZY, mappedBy="user")
public Set<Role> getRoles() {
return this.roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}

package org.junjun.util.java.persistence;
// Generated Jun 6, 2017 10:36:31 PM by Hibernate Tools 5.2.3.Final
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* Role generated by hbm2java
*/
@Entity
@Table(name="ROLE"
,catalog="MYDB"
)
public class Role implements java.io.Serializable {
private BigDecimal id;
private User user;
private String name;
public Role() {
}
public Role(BigDecimal id, User user, String name) {
this.id = id;
this.user = user;
this.name = name;
}
@Id
@Column(name="ID", unique=true, nullable=false, scale=0)
public BigDecimal getId() {
return this.id;
}
public void setId(BigDecimal id) {
this.id = id;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="FK_USER_ID", nullable=false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
@Column(name="NAME", nullable=false, length=50)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}










You may refer to project source code here :  https://github.com/junjun-dachi/java-util/tree/master/db-to-java 



JOB DONE.




1 comment:

Flag Counter