Создание таблиц из классов Entity в Hibernate

1- Цель статьи

Данная статья основана на:
  • Hibernate 5.2.2.Final

  • Eclipse 4.6 (MARS)

В данной статье я покажу вам как создать систему таблиц, основываясь на любой базе данных. ( Oracle, MySQL, SQL Server, ..)  основывая на классах  Entity. Созданные таблицы будут полностью иметь ограничения (Constraints) по указаниям в классах  Entity.

Заметьте, что  Hibernate создан чтобы работать с любой базой данных. Поэтому, когда вы меняте базу данных вам не придется менять код программы. Но при этом, вам нужно создать систему таблицы в базе данных. Hibernate помогает вам создать систему таблицы из классов  Entity.
Данная статья является продолжением "Руководство программирования Hibernate для начинающих", которое вы можете посмотреть по ссылке:
  • TODO Link!

2- Создать Maven Project & Объявить библиотеку

В pom.xml я объявляю библиотеку  Hibernate 5, и библиотека  JDBC для разных  Database ( Oracle, MySQL и  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

Мы создаем классы  Entity. Каждый  Entity описывает таблицу в  DB. Не говорите ничего, про то что имеется в этих таблицах. 
  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

Чтобы создать таблицы, вам нужен файл конфигурации базы данных  database ( hibernate-<datatype>.cfg.xml) и классы  Entity.
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>
Удостоверьтесь, что вы создали пустые  Schema. (Пустые  database) без таблиц. Например с  Oracle я создаю новую  Schema с названием  simplehr2.
-- ORACLE
Create user simplehr2 identified by 12345;
grant dba to simplehr2;

5- Создать таблицы из Entity

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);
   }
   
}
Запуск примера:
Смотрим файл Script: