この記事の続き。
長くなるので分けました。Hibernate(JPA)による操作。とりあえずは動いたがいまいち構成や依存関係がわからない。
事前知識(段取り)
Hibernateを利用する場合、おおよそ下記のものを作ることになるらしい。
Javaの世界は不慣れなので表現とかが間違ってるかもしれない。
- hibernate.cfg.xml(DBの接続情報やクラスのマッピング等を指定)
- Modelクラス(DBテーブルと対応するクラス)
- SessionFactory(Config)クラス(xmlから設定を読み込んで利用できる状態にする?っぽい)
- 実行ファイル(App.java)
準備
テンプレート生成
まずはテンプレートの生成。quickstartで特に問題ない。
mvn archetype:generate \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=RELEASE \
-DinteractiveMode=false \
-DgroupId=com.hoge \
-DartifactId=hibernate-test
cd hibernate-test
pom.xmlの編集
まずは依存ライブラリの指定。hibernateとmysqlを指定。
最新版についてはこちらで検索。
以下は抜粋になります。dependenciesに追加します。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.29.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
実装
Hibernate.cfg.xmlの設定
クラスパスにhibernate.cfg.xmlを作成し、設定する。
ここではresoucesフォルダに作成する。
mkdir -p src/main/resources
touch src/main/resources/hibernate.cfg.xml
記述する。
ここで、DBの接続情報、テーブルの生成条件(hbm2ddl)、マッピングするクラスなどを指定する。
<?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="connection.url">jdbc:mysql://localhost:3306/testdb</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 'show_sql' set true to check sql statements on console else set to false -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 新規に作る場合はcreate, そうでない場合はupdate -->
<property name="hbm2ddl.auto">update</property>
<!-- JDBC connection pool -->
<property name="connection.pool_size">5</property>
<property name="current_session_context_class">thread</property>
<!-- マップするモデルを記述 -->
<mapping class="com.hoge.User" />
</session-factory>
</hibernate-configuration>
Model(Entity)
id,name,ageの3つのプロパティしか持たないが、getterやsetterが必要なので冗長。lombokってのを使うと省略できるらしいが、とりあえず書く。アノテーションでテーブル生成、マッピングの際の条件を表現するみたい。
package com.hoge;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Column;
@Entity(name = "User")
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //AUTOだと既存テーブルだとIDがかぶる
@Column(name = "id")
private int id;
@Column(name = "name", length = 32, nullable = true)
private String name;
@Column(name = "age")
private int age;
// getter, setter
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAage(int age) {
this.age = age;
}
}
SessionFactory(Config)
SessionFactoryを戻すクラスを実装。読み込んだconfig情報をベースにsessionを生成し戻すみたい。
C#のコンテクストて感じかな?
package com.hoge;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class UserSessionFactory {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
return new Configuration().configure().buildSessionFactory();
} catch (Throwable e) {
System.err.println("build SeesionFactory failed :" + e);
throw new ExceptionInInitializerError(e);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void close() {
// Close all cached and active connection pools
getSessionFactory().close();
}
}
実行ファイル
実行ファイル内でいろいろ利用。
package com.hoge;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.query.Query;
public class App {
public static void main(String[] args) {
// session
Session session = UserSessionFactory.getSessionFactory().openSession();
// insert
session.beginTransaction();
User user = new User();
user.setName("Bar");
user.setAage(11);
session.save(user);
session.getTransaction().commit();
// select
Query<User> query = session.createQuery("From User", User.class);
List<User> results = query.list();
System.out.println("number of users:" + results.size());
for (User u : results) {
System.out.println("User:" + u + " " + u.getName());
}
}
}
実行
vscodeのjava extensionの実行を利用しているが、下記ので実行可能。
mvn -q compile exec:java -Dexec.mainClass=com.hoge.App
実行するたびにユーザーが増えます。
User:com.hoge.User@60c97466 hoge
User:com.hoge.User@1e0e9702 foo
User:com.hoge.User@50b06f2c Bar
User:com.hoge.User@1f5b2c0c Bar
User:com.hoge.User@57a06b99 Bar
User:com.hoge.User@30bd1fba Bar
うーん。まあ雰囲気はわかったかな。