Hibernate Toolsを使ってJPAのEntityクラスを生成する

# 概要

EclipseプラグインのHibernate Toolsを使ってJPAのEntityクラスを生成するための環境構築や設定方法のまとめです。

**環境**

* Windows10 Professional
* Java 1.8.0_101
* Eclipse Neon
 * JBoss Tools 4.4.1.Final
 * MySQL Connector/J 5.1.40
* MySQL 5.6

**参考**

* [sing Hibernate Tools generate entity classes from Tables] (http://o7planning.org/en/10125/using-hibernate-tools-generate-entity-classes-from-tables)



# 必要なライブラリの準備

## Hibernate ORM

http://hibernate.org/orm/

上記のサイトよりアーカイブファイルをダウンロードし適当な場所へ展開しておきます。
今回使用したのはhibernate-release-5.2.4.Final.zipです。

## MySQL Connector/J

https://dev.mysql.com/downloads/connector/j/

上記のサイトよりアーカイブファイルをダウンロードし適当な場所へ展開しておきます。
今回使用したのはmysql-connector-java-5.1.40.zipです。


# Eclipseの設定

## JBoss Toolsのインストール

マーケットプレイスよりJBoss Tools 4.4.1.Finalをインストールします。

![jboss_tool_1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/3cd5165f-c61d-35d4-6de7-748bf25a1739.png)

インストールするのはHibernate Toolsだけで大丈夫です。

![jboss_tool_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/3dc4ed52-5156-0a14-811d-3c0550dda0f4.png)


## Driver Definition

メニューバー → Preferences → Data Management → Connectivity → Driver Definitions

<span class="label label-default">Add...</span> をクリックします。

![driver_definition_1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/eea2ee27-4937-91b8-4e55-88e0e83ab217.png)

Vendor FilterにMySQLを選択し、driver templateにMySQL 5.1を指定します。

![driver_definition_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/984c31fe-523e-830e-2491-eeb0a427335e.png)

JAR Listタブで <span class="label label-default">Add JAR/Zip...</span> を押して先ほどダウンロードしたMySQL Connector/Jのjarを指定します。

![driver_definition_3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/a1b240ca-97c7-c363-08b7-c906fd941965.png)


## Connection Profile

Data Source ExplorerビューのDatabase Connectionsを右クリックし、コンテキストメニューから"New..."を選択します。

Connection ProfileにMySQLを選択します。
Nameは"MySQL (sample_db)"としました。

![connection_profile_1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/6a8a41dd-489e-e5b2-f3d6-2e9ff1b6444a.png)

JDBC Driverのpropertyを入力します。
ついでにTest Connectionで接続できるか確認も行います。

![connection_profile_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/cefa619c-280e-f63f-74cc-c6eb66b02c55.png)

今回の設定内容です。

![connection_profile_3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/daca29a0-7cb1-e67f-9934-8eefc13eabe1.png)


## Hibernate

メニューバー → Preferences → Java → Build Path → User Libraries

<span class="label label-default">New...</span> をクリックします。

![user_libraries_hibernate_1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/9f942f1f-77a7-33b7-ad88-525bbfbe36e1.png)

nameに"hibernate"と入力しました。

![user_libraries_hibernate_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/5e7f962a-8d14-9a10-6be8-9986ac78ac3e.png)

<span class="label label-default">Add External JARs...</span> をクリックして、先ほどダウンロードしたHibernateのJarを指定します。
指定するのは展開フォルダ下のlib/requireにあるjarファイル全てです。

![user_libraries_hibernate_3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/3b64a666-d265-d98b-3e4a-668d28249b97.png)



# JPA Projectの作成

Entityクラスを生成するためのプロジェクトを作ります。
Project Explorerで右クリックし、コンテキストメニューからNew → Project... → JPA → JPA Projectを選択します。

![jpa_project_1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/e55040f6-d674-32ab-1724-72dcc64060db.png)

Project nameは"sample_db"としました。この名前がpersistence-unitの名前にもなります。
その他の設定は図の通りです。

![jpa_project_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/57fce777-b840-3f71-d7af-c5d975e61d12.png)

ここはそのまま <span class="label label-default">Next ></span> で進みます。

![jpa_project_3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/3402a2dd-7cec-c94a-4be4-48a30ad6a617.png)

JPA implementationに"User Library"を選び、上記で登録した"hibernate"を指定します。
Connectionも上記で登録した"MySQL(sample_db)"を指定します。
<span class="label label-default">Finish</span> をクリックして登録を完了します。

![jpa_project_4.png](https://qiita-image-store.s3.amazonaws.com/0/22772/ceec825f-63a7-3632-4674-b919992cf5a2.png)

JPA Projectの作成直後の状態です。

![jpa_project_5.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c34ecb97-fc49-3a3f-7bae-020cd7d0fcd8.png)


生成されたpersistence.xmlを下記のように修正します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
	<persistence-unit name="sample_db">
	    <provider>org.hibernate.ejb.HibernatePersistence</provider>
	    <exclude-unlisted-classes>false</exclude-unlisted-classes>
	    <properties>
	        <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
	        <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/sample_db"/>
	        <property name="hibernate.connection.username" value="test_user"/>
	        <property name="hibernate.connection.password" value="test_user"/>
	        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
	    </properties>
	</persistence-unit>
</persistence>
```

プロジェクト名を右クリックしコンテキストメニューからBuild Path → Configure Build Path... → JPA → Entity Generationを選択し、Default packageを設定します。
今回は"com.example.model"としました。

![jpa_project_6.png](https://qiita-image-store.s3.amazonaws.com/0/22772/a7f74663-7a33-0dcf-4ca7-1769be0301b1.png)

プロジェクト名を右クリックしコンテキストメニューからNew → JPA Entities from Tablesを選択します。

![jpa_project_7.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b8eb1a45-3038-2f88-3753-19fdfe268db0.png)

データベース接続されていない場合は、図で示すアイコンをクリックしてデータベース接続を行います。

![jpa_project_8.png](https://qiita-image-store.s3.amazonaws.com/0/22772/1db27f8f-49dc-cc67-ae41-c5cfce533e70.png)

接続が成功すればテーブルの一覧が表示されるのでEntityクラスが必要なテーブルにチェックを入れます。

![jpa_project_9.png](https://qiita-image-store.s3.amazonaws.com/0/22772/52fbf4e7-eb45-18db-87bb-b15e5ce6124c.png)

ここはそのまま <span class="label label-default">Next ></span> で進みます。

![jpa_project_10.png](https://qiita-image-store.s3.amazonaws.com/0/22772/9041b7d0-30df-e9bb-205d-4f5344c8d306.png)

生成するEntityクラスのカスタマイズを行います。
ここではKey generatorに"identity"を指定しました。

![jpa_project_11.png](https://qiita-image-store.s3.amazonaws.com/0/22772/07050360-c637-18fc-9e1c-ae837169bff3.png)

<span class="label label-default">Finish</span> をクリックしてEntityクラスを生成します。

![jpa_project_12.png](https://qiita-image-store.s3.amazonaws.com/0/22772/d0491265-e129-6334-e320-62776e8944e9.png)

Entityクラスを生成した直後のJPA Projectの状態です。Entityクラスの他にpersistence.xmlの設定にも反映されています。

![jpa_project_13.png](https://qiita-image-store.s3.amazonaws.com/0/22772/83e51420-349b-16a7-d367-c19946532479.png)


# 補足

## 使用するDB環境

この記事で使用するDB環境です。

### データベース、ユーザー

```sql
create database if not exists sample_db character set utf8;

create user 'test_user'@'localhost' identified by 'test_user';

grant all on sample_db.* to 'test_user'@'localhost';
```

### テーブル

#### customer

```sql
create table if not exists customer (
  id int not null auto_increment,
  customer_number int not null,
  customer_name varchar(124) not null,
  contact_last_name varchar(124) not null,
  contact_first_name varchar(124) not null,
  phone varchar(32),
  address_line1 varchar(124),
  address_line2 varchar(124),
  city varchar(32),
  state varchar(32),
  postal_code varchar(32),
  country varchar(32),
  sales_rep_employee_number int,
  credit_limit decimal(10,2),
  primary key (id)
) engine = INNODB;
```

生成されたEntityクラス(Customer)。getter/setterは省略しています。

```java:Customer.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;

/**
 * The persistent class for the customer database table.
 * 
 */
@Entity
@NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c")
public class Customer implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	@Column(name="address_line1")
	private String addressLine1;

	@Column(name="address_line2")
	private String addressLine2;

	private String city;

	@Column(name="contact_first_name")
	private String contactFirstName;

	@Column(name="contact_last_name")
	private String contactLastName;

	private String country;

	@Column(name="credit_limit")
	private BigDecimal creditLimit;

	@Column(name="customer_name")
	private String customerName;

	@Column(name="customer_number")
	private int customerNumber;

	private String phone;

	@Column(name="postal_code")
	private String postalCode;

	@Column(name="sales_rep_employee_number")
	private int salesRepEmployeeNumber;

	private String state;

	public Customer() {
	}

}
```


#### orders

```sql
create table if not exists orders (
  id int not null auto_increment,
  order_number int not null,
  order_date date not null,
  required_date date not null,
  shipped_date date,
  status varchar(32),
  comments varchar(256),
  customer_number int,
  primary key (id)
) engine = INNODB;
```

```java:Order.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;


/**
 * The persistent class for the orders database table.
 * 
 */
@Entity
@Table(name="orders")
@NamedQuery(name="Order.findAll", query="SELECT o FROM Order o")
public class Order implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	private String comments;

	@Column(name="customer_number")
	private int customerNumber;

	@Temporal(TemporalType.DATE)
	@Column(name="order_date")
	private Date orderDate;

	@Column(name="order_number")
	private int orderNumber;

	@Temporal(TemporalType.DATE)
	@Column(name="required_date")
	private Date requiredDate;

	@Temporal(TemporalType.DATE)
	@Column(name="shipped_date")
	private Date shippedDate;

	private String status;

	public Order() {
	}

}
```


#### order_detail

```sql
create table if not exists order_detail (
  id int not null auto_increment,
  order_number int not null,
  product_code varchar(32) not null,
  quantity_ordered int,
  price_each decimal(10,2),
  order_line_number int,
  primary key (id)
) engine = INNODB;
```

```java:OrderDetail.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;


/**
 * The persistent class for the order_detail database table.
 * 
 */
@Entity
@Table(name="order_detail")
@NamedQuery(name="OrderDetail.findAll", query="SELECT o FROM OrderDetail o")
public class OrderDetail implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	@Column(name="order_line_number")
	private int orderLineNumber;

	@Column(name="order_number")
	private int orderNumber;

	@Column(name="price_each")
	private BigDecimal priceEach;

	@Column(name="product_code")
	private String productCode;

	@Column(name="quantity_ordered")
	private int quantityOrdered;

	public OrderDetail() {
	}

}
```


#### payment

```sql
create table if not exists payment (
  id int not null auto_increment,
  customer_number int not null,
  check_number varchar(64) not null,
  payment_date date not null,
  amount decimal(10,2) not null,
  primary key (id)
) engine = INNODB;
```

```java:Payment.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;


/**
 * The persistent class for the payment database table.
 * 
 */
@Entity
@NamedQuery(name="Payment.findAll", query="SELECT p FROM Payment p")
public class Payment implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	private BigDecimal amount;

	@Column(name="check_number")
	private String checkNumber;

	@Column(name="customer_number")
	private int customerNumber;

	@Temporal(TemporalType.DATE)
	@Column(name="payment_date")
	private Date paymentDate;

	public Payment() {
	}

}
```


#### product

```sql
create table if not exists product (
  id int not null auto_increment,
  product_code varchar(32) not null,
  product_name varchar(128) not null,
  product_line varchar(32) not null,
  product_scale varchar(32) not null,
  product_vendor varchar(64) not null,
  product_description varchar(1024),
  quantity_in_stock int,
  buy_price decimal(10,2),
  msrp decimal(10,2),
  primary key (id)
) engine = INNODB;
```

```java:Product.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;


/**
 * The persistent class for the product database table.
 * 
 */
@Entity
@NamedQuery(name="Product.findAll", query="SELECT p FROM Product p")
public class Product implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	@Column(name="buy_price")
	private BigDecimal buyPrice;

	private BigDecimal msrp;

	@Column(name="product_code")
	private String productCode;

	@Column(name="product_description")
	private String productDescription;

	@Column(name="product_line")
	private String productLine;

	@Column(name="product_name")
	private String productName;

	@Column(name="product_scale")
	private String productScale;

	@Column(name="product_vendor")
	private String productVendor;

	@Column(name="quantity_in_stock")
	private int quantityInStock;

	public Product() {
	}

}
```


#### product_line

```sql
create table if not exists product_line (
  id int not null auto_increment,
  product_line varchar(32) not null,
  text_description varchar(1024),
  html_description varchar(1024),
  image varchar(1024),
  primary key (id)
) engine = INNODB;
```

```java:ProductLine.java
package com.example.model;

import java.io.Serializable;
import javax.persistence.*;


/**
 * The persistent class for the product_line database table.
 * 
 */
@Entity
@Table(name="product_line")
@NamedQuery(name="ProductLine.findAll", query="SELECT p FROM ProductLine p")
public class ProductLine implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	@Column(name="html_description")
	private String htmlDescription;

	private String image;

	@Column(name="product_line")
	private String productLine;

	@Column(name="text_description")
	private String textDescription;

	public ProductLine() {
	}

}
```