はじめに
株式会社インプルの奈良です。
現在開発中のJava + Spring BootのアプリのSQL関連のエラーで、Hibernateという見慣れないエラーログに遭遇しました。
エラー解決にあたり、このHibernateについて理解する必要があると感じたため、勉強がてら記事をまとめたいと思います。
Hibernateとは
Hibernate(ハイバネート)は、JavaプログラミングのためのO/Rマッピング(オブジェクト関係マッピング)ライブラリです。具体的には、オブジェクト関係マッピング(ORM: Object-Relational Mapping)という技術を使用して、Javaオブジェクトとデータベースのテーブルをマッピング(関連付け)します。
機能概要
第一の機能は、Javaクラスからデータベースの表(およびJavaデータ型からSQLデータ型)へのマッピングである。また、データのクエリと検索機能も提供する。SQL呼び出しを自動生成することで、開発者がSQL呼び出しの結果をいちいちオブジェクトに変換する手間から解放し、性能への影響を最小にしつつ、あらゆるSQLデータベースへの移植性を達成している。
Hibernateは Plain Old Java Object (POJO) のための透過的永続性を提供する。永続性クラスに要求されることは、引数のないコンストラクタが存在することであり、コンストラクタの可視性がpublicでなくともよい(一部アプリケーションでは、equals()とhashCode()メソッドにも注意が必要[1])。
Hibernateには「ダーティチェッキング」機能がある。この機能は、永続的オブジェクトの変更されたフィールドについてのみSQLによる更新を行うもので、不必要なデータベース更新を削減する。
Hibernateは「HQL」というSQLライクなクエリ言語を提供している。オブジェクト指向的な代替手段としてクライテリアクエリも提供されている。
HibernateはスタンドアローンのJavaアプリケーションにも使えるし、Java ServletやEJBセッションビーンを使ったJakarta EEアプリケーションにも使える。
https://ja.wikipedia.org/wiki/Hibernate
オブジェクト関係マッピング (ORM) とは
ORMは、プログラムの中で使われるオブジェクトとデータベースのテーブルとの間の「変換」を行う技術です。これにより、プログラマーはデータベースの細かいクエリを気にすることなく、オブジェクトとしてデータを扱うことができます。
Hibernateの主な特長
データベース独立性
Hibernateを使用すると、異なるデータベース間でアプリケーションを簡単に移行することができます。具体的なSQLクエリを書く必要がなく、Hibernateが適切なSQLを生成してくれます。
キャッシング
Hibernateは、パフォーマンスを向上させるための内部キャッシングメカニズムを持っています。
遅延読み込み
必要になるまでデータの読み込みを遅らせることができ、これによりパフォーマンスが向上します。
簡単な関連管理
オブジェクト間の関連(例: 一対多、多対多)を簡単に設定して管理することができます。
Hibernateを使ったJavaのデータベース操作の基本
①エンティティクラスの作成
データベースのテーブルを表すJavaクラスを作成します。これをエンティティクラスと呼びます。
例:Userクラス
@Entity // このクラスがエンティティであることを示す
@Table(name="users") // 対応するデータベーステーブル名を指定
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="username")
private String username;
@Column(name="email")
private String email;
// getters, setters, constructors, etc.
}
@Entity:Javaクラスがデータベースのテーブルとして表現されるエンティティであることをHibernateに伝えます。
@Table(name=”users”):このクラスがどのデータベースのテーブルにマッピングされるかを指定します。
②設定ファイルの作成
Hibernateは設定ファイルを通して動作します。
設定ファイルでは、データベース接続の詳細やエンティティクラスの位置など、Hibernateがどのように動作するかの情報を提供します。
このファイルは、通常、hibernate.cfg.xmlという名前でプロジェクトのルートディレクトリに配置されます。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
<property name="hibernate.connection.username">your_username</property>
<property name="hibernate.connection.password">your_password</property>
<!-- JDBC connection pool settings -->
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<!-- Specify dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Mention annotated class -->
<mapping class="com.example.User"/>
</session-factory>
</hibernate-configuration>
- データベース接続の詳細:データベースの種類、接続URL、ユーザー名、パスワードなど、データベースへの接続に関する情報を設定します。
- エンティティクラスの位置:mapping要素を使用して、Hibernateがエンティティとして知っておく必要があるクラスを指定します。
③データベース操作の実行
最後に実際にデータベースへの操作を行います。
public class App {
public static void main(String[] args) {
// 1. Create SessionFactory
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(User.class).buildSessionFactory();
// 2. Create Session
Session session = factory.getCurrentSession();
try {
// 3. Use the session to save/read/delete data
User tempUser = new User("John", "john@example.com");
session.beginTransaction();
session.save(tempUser);
session.getTransaction().commit();
} finally {
factory.close();
}
}
}
- SessionFactoryの作成:これは、データベース接続とのセッションを作成するためのオブジェクトです。
- セッションの作成:session = factory.getCurrentSession();で新しいセッションを開始します。
- データベース操作:このセッションを使用して、データベースにデータを保存、読み込み、削除する操作を行います。
上記の例では、新しいUserオブジェクトを作成し、それをデータベースに保存しています。
この時、beginTransaction();で新しいトランザクションを開始し、commit();でそのトランザクションをコミット(確定)しています。
まとめ
このようにHibernateはJavaクラスとデータベーステーブルとの間のマッピングを簡単にするための強力なフレームワークです。
設定やアノテーションを適切に使うことで、複雑なSQLクエリの記述を避け、オブジェクト指向的な方法でデータベース操作を行うことができます。