Generate Tables from Entity classes in Hibernate

1- The objective of the document

This document is based on:
  • Hibernate 5.2.2.Final

  • Eclipse 4.6 (MARS)

In this document I will guide you to create tables from the entity classes, on any database (Oracle, MySQL, SQL Server, ..). The tables created will have full of constraints as designated by the Entity classes.

Take note of that Hibernate is created to work with any databases. This means that when you change a database, you do not have to change the programme code. However, you must create tables in the new database. Hibernate will support you in creating tables from Entity classes.
The post is the next part of "Hibernate Tutorial for Beginners" that you can read here:

2- Create Maven Project & declare libraries

In pom.xml I declare Hibernate 5 library, and JDBC libraries for different types of databases ( Oracle, MySQL and SQL Server).
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.o7planning</groupId>
  <artifactId>HibernateGenerateTables</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>HibernateGenerateTables</name>
  <url>http://maven.apache.org</url>


   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>


   <repositories>
       <!-- Repository for ORACLE JDBC Driver -->
       <repository>
           <id>codelds</id>
           <url>https://code.lds.org/nexus/content/groups/main-repo</url>
       </repository>
   </repositories>
 
 
   <dependencies>


       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>3.8.1</version>
           <scope>test</scope>
       </dependency>

       <!-- Hibernate Core -->
       <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
       <dependency>
           <groupId>org.hibernate</groupId>
           <artifactId>hibernate-core</artifactId>
           <version>5.2.2.Final</version>
       </dependency>


       <!-- MySQL JDBC driver -->
       <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.34</version>
       </dependency>

       <!-- Oracle JDBC driver -->
       <dependency>
           <groupId>com.oracle</groupId>
           <artifactId>ojdbc6</artifactId>
           <version>11.2.0.3</version>
       </dependency>

       <!-- SQLServer JDBC driver (JTDS) -->
       <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
       <dependency>
           <groupId>net.sourceforge.jtds</groupId>
           <artifactId>jtds</artifactId>
           <version>1.3.1</version>
       </dependency>

   </dependencies>
 
</project>

3- Entity classes

We create class Entity. Each Entity describes a table in DB. Wait a minute, don't talk about anything in those classes.
  1. Department
  2. Employee
  3. SalaryGrade
  4. Timekeeper
Department.java
package org.o7planning.tutorial.hibernate.entities;

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;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "DEPARTMENT",
  uniqueConstraints = { @UniqueConstraint(columnNames = { "DEPT_NO" }) })
public class Department {

private Integer deptId;
private String deptNo;

private String deptName;
private String location;
private Set<Employee> employees = new HashSet<Employee>(0);

public Department() {
}

public Department(Integer deptId, String deptName, String location) {
   this.deptId = deptId;
   this.deptNo = "D" + this.deptId;
   this.deptName = deptName;
   this.location = location;
}

@Id
@Column(name = "DEPT_ID")
public Integer getDeptId() {
   return deptId;
}

public void setDeptId(Integer deptId) {
   this.deptId = deptId;
}

@Column(name = "DEPT_NO", length = 20, nullable = false)
public String getDeptNo() {
   return deptNo;
}

public void setDeptNo(String deptNo) {
   this.deptNo = deptNo;
}

@Column(name = "DEPT_NAME", nullable = false)
public String getDeptName() {
   return deptName;
}

public void setDeptName(String deptName) {
   this.deptName = deptName;
}

@Column(name = "LOCATION")
public String getLocation() {
   return location;
}

public void setLocation(String location) {
   this.location = location;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
public Set<Employee> getEmployees() {
   return employees;
}

public void setEmployees(Set<Employee> employees) {
   this.employees = employees;
}
}
Employee.java
package org.o7planning.tutorial.hibernate.entities;

import java.util.Date;
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.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "EMPLOYEE",
   uniqueConstraints = { @UniqueConstraint(columnNames = { "EMP_NO" }) })
public class Employee {
private Long empId;
private String empNo;

private String empName;
private String job;
private Employee manager;
private Date hideDate;
private Float salary;
private byte[] image;

private Department department;
private Set<Employee> employees = new HashSet<Employee>(0);

public Employee() {
}

public Employee(Long empId, String empName, String job, Employee manager,
        Date hideDate, Float salary, Float comm, Department department) {
    this.empId = empId;
    this.empNo = "E" + this.empId;
    this.empName = empName;
    this.job = job;
    this.manager = manager;
    this.hideDate = hideDate;
    this.salary = salary;
    this.department = department;
}

@Id
@Column(name = "EMP_ID")
public Long getEmpId() {
    return empId;
}

public void setEmpId(Long empId) {
    this.empId = empId;
}

@Column(name = "EMP_NO", length = 20, nullable = false)
public String getEmpNo() {
    return empNo;
}

public void setEmpNo(String empNo) {
    this.empNo = empNo;
}

@Column(name = "EMP_NAME", length = 50, nullable = false)
public String getEmpName() {
    return empName;
}

public void setEmpName(String empName) {
    this.empName = empName;
}

@Column(name = "JOB", length = 30, nullable = false)
public String getJob() {
    return job;
}

public void setJob(String job) {
    this.job = job;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MNG_ID")
public Employee getManager() {
    return manager;
}

public void setManager(Employee manager) {
    this.manager = manager;
}

@Column(name = "HIRE_DATE", nullable = false)
@Temporal(TemporalType.DATE)
public Date getHideDate() {
    return hideDate;
}

public void setHideDate(Date hideDate) {
    this.hideDate = hideDate;
}

@Column(name = "SALARY", nullable = false)
public Float getSalary() {
    return salary;
}

public void setSalary(Float salary) {
    this.salary = salary;
}

@Column(name = "IMAGE", length = 1111111, nullable = true)
@Lob
public byte[] getImage() {
    return image;
}

public void setImage(byte[] image) {
    this.image = image;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DEPT_ID", nullable = false)
public Department getDepartment() {
    return department;
}

public void setDepartment(Department department) {
    this.department = department;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "empId")
public Set<Employee> getEmployees() {
    return employees;
}

public void setEmployees(Set<Employee> employees) {
    this.employees = employees;
}

}
SalaryGrade.java
package org.o7planning.tutorial.hibernate.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "SALARY_GRADE")
public class SalaryGrade {
 private Integer grade;
 private Float lowSalary;
 private Float highSalary;

 public SalaryGrade() {
 }

 public SalaryGrade(Integer grade, Float lowSalary, Float highSalary) {
     this.grade = grade;
     this.lowSalary = lowSalary;
     this.highSalary = highSalary;
 }

 @Id
 @Column(name = "GRADE")
 public Integer getGrade() {
     return grade;
 }

 public void setGrade(Integer grade) {
     this.grade = grade;
 }

 @Column(name = "LOW_SALARY", nullable = false)
 public Float getLowSalary() {
     return lowSalary;
 }

 public void setLowSalary(Float lowSalary) {
     this.lowSalary = lowSalary;
 }

 @Column(name = "HIGH_SALARY", nullable = false)
 public Float getHighSalary() {
     return highSalary;
 }

 public void setHighSalary(Float highSalary) {
     this.highSalary = highSalary;
 }
}
Timekeeper.java
package org.o7planning.tutorial.hibernate.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "TIMEKEEPER")
public class Timekeeper {
  public static final char IN = 'I';
  public static final char OUT = 'O';

  private String timekeeperId;

  private Date dateTime;

  private Employee employee;

  // 'I' or 'O'
  private char inOut;

  @Id
  @GeneratedValue(generator = "uuid")
  @GenericGenerator(name = "uuid", strategy = "uuid2")
  @Column(name = "Timekeeper_Id", length = 36)
  public String getTimekeeperId() {
      return timekeeperId;
  }

  public void setTimekeeperId(String timekeeperId) {
      this.timekeeperId = timekeeperId;
  }

  @Column(name = "Date_Time", nullable = false)
  @Temporal(TemporalType.TIMESTAMP)
  public Date getDateTime() {
      return dateTime;
  }

  public void setDateTime(Date dateTime) {
      this.dateTime = dateTime;
  }

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "EMP_ID", nullable = false)
  public Employee getEmployee() {
      return employee;
  }

  public void setEmployee(Employee employee) {
      this.employee = employee;
  }

  @Column(name = "In_Out", nullable = false, length = 1)
  public char getInOut() {
      return inOut;
  }

  public void setInOut(char inOut) {
      this.inOut = inOut;
  }

}

4- hibernate-xxx.cfg.xml

To create tables, you need a database configuration file  (hibernate-<datatype>.cfg.xml) and the Entity classes.
hibernate-oracle.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>

       <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
       <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
       <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:db12c</property>
       <property name="hibernate.connection.username">simplehr2</property>
       <property name="hibernate.connection.password">12345</property>
       <property name="hibernate.show_sql">true</property>
       <property name="hibernate.connection.release_mode">auto</property>
       <property name="current_session_context_class">thread</property>
       <property name="hibernate.connection.autoReconnect">true</property>


       <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
       <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
       <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
       <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />

   </session-factory>
 
</hibernate-configuration>
hibernate-mysql.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
<session-factory>
  <!-- Database connection settings -->
  <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="connection.url">jdbc:mysql://tran-vmware:3306/simplehr?serverTimezone=UTC</property>
  <property name="connection.username">root</property>
  <property name="connection.password">1234</property>
 
  <!-- JDBC connection pool (use the built-in) -->
  <property name="connection.pool_size">1</property>
 
  <!-- SQL dialect -->
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 
  <!-- Enable Hibernate's automatic session context management -->
  <property name="current_session_context_class">thread</property>
 
  <!-- Disable the second-level cache  -->
  <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
 
  <!-- Echo all executed SQL to stdout -->
  <property name="show_sql">true</property>
 
   <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
   <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />
 
</session-factory>

</hibernate-configuration>
hibernate-sqlserver.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
 <session-factory>
   <!-- Database connection settings -->
   <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
   <property name="connection.url">jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS</property>
   <property name="connection.username">sa</property>
   <property name="connection.password">1234</property>
 
   <!-- JDBC connection pool (use the built-in) -->
   <property name="connection.pool_size">1</property>
 
   <!-- SQL dialect -->
   <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
 
   <!-- Enable Hibernate's automatic session context management -->
   <property name="current_session_context_class">thread</property>
 
   <!-- Disable the second-level cache  -->
   <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
 
   <!-- Echo all executed SQL to stdout -->
   <property name="show_sql">true</property>
 
    <mapping class="org.o7planning.tutorial.hibernate.entities.Department" />
    <mapping class="org.o7planning.tutorial.hibernate.entities.Employee" />
    <mapping class="org.o7planning.tutorial.hibernate.entities.SalaryGrade" />
    <mapping class="org.o7planning.tutorial.hibernate.entities.Timekeeper" />
 
</session-factory>

</hibernate-configuration>
Make sure that you have create an empty Schema (The empty database have no tables). For example, I create a new Schema named as simplehr2 for Oracle.
-- ORACLE
Create user simplehr2 identified by 12345;
grant dba to simplehr2;

5- Generate database from Entities

SchemaGeneratorDemo.java
package org.o7planning.generatetables;

import java.io.File;
import java.util.EnumSet;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;

// Hibernate 5.
public class SchemaGeneratorDemo {

   public static final String SCRIPT_FILE = "exportScript.sql";

   private static SchemaExport getSchemaExport() {

       SchemaExport export = new SchemaExport();
       // Script file.
       File outputFile = new File(SCRIPT_FILE);
       String outputFilePath = outputFile.getAbsolutePath();

       System.out.println("Export file: " + outputFilePath);

       export.setDelimiter(";");
       export.setOutputFile(outputFilePath);
       
       // No Stop if Error
       export.setHaltOnError(false);
       //
       return export;
   }

   public static void dropDataBase(SchemaExport export, Metadata metadata) {
       // TargetType.DATABASE - Execute on Databse
       // TargetType.SCRIPT - Write Script file.
       // TargetType.STDOUT - Write log to Console.
       EnumSet<TargetType> targetTypes = EnumSet.of(TargetType.DATABASE, TargetType.SCRIPT, TargetType.STDOUT);

       export.drop(targetTypes, metadata);
   }

   public static void createDataBase(SchemaExport export, Metadata metadata) {
       // TargetType.DATABASE - Execute on Databse
       // TargetType.SCRIPT - Write Script file.
       // TargetType.STDOUT - Write log to Console.
 
       EnumSet<TargetType> targetTypes = EnumSet.of(TargetType.DATABASE, TargetType.SCRIPT, TargetType.STDOUT);

       SchemaExport.Action action = SchemaExport.Action.CREATE;
       //
       export.execute(targetTypes, action, metadata);

       System.out.println("Export OK");

   }

   public static void main(String[] args) {

       // Using Oracle Database.
 
       String configFileName = "hibernate-oracle.cfg.xml";

       // Create the ServiceRegistry from hibernate-xxx.cfg.xml
       ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()//
               .configure(configFileName).build();

       // Create a metadata sources using the specified service registry.
       Metadata metadata = new MetadataSources(serviceRegistry).getMetadataBuilder().build();

       SchemaExport export = getSchemaExport();

       System.out.println("Drop Database...");
       // Drop Database
       dropDataBase(export, metadata);

       System.out.println("Create Database...");
       // Create tables
       createDataBase(export, metadata);
   }
   
}
Running the example
See Script files: