liguofeng29’s blog

個人勉強用ブログだっす。

Hibernate - Map属性マッピング

Mapを持つ永続化クラスの保存サンプル。

キーのAnnotaion

  • @ElementCollection
  • @ColletionTable
  • @Column
  • @MapKeyColumn

1. hibernate.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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 接続情報 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">xxxx</property>
        <!-- 各種設定 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- プール内最大Statement -->
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>

        <property name="hibernate.c3p0.validate">true</property>
        <!-- DB方言解消 -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 必要に応じて表生成 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 生成SQL表示 -->
        <property name="show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <!-- マッピングテーブル -->
        <!--  mapping class="entity.Item"/ -->
        <mapping class="map.Person"/>
    </session-factory>
</hibernate-configuration>

2. Person.java

package map;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapKeyClass;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;

@Entity
@Table(name = "person_inf")
public class Person {
    @Id @Column(name="person_id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private int age;
    // 集合属性
    @ElementCollection(targetClass=Float.class)
    // マッピング表
    @CollectionTable(name="score_inf", // ヨクカィア朎鉸ェscore_inf
        joinColumns=@JoinColumn(name="person_id" , nullable=false))
    @MapKeyColumn(name="subject_name")
    // key
    @MapKeyClass(String.class)
    // value
    @Column(name="mark")
    private Map<String , Float> scores
        = new HashMap<>();

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return this.id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    public Map<String, Float> getScores() {
        return scores;
    }

    public void setScores(Map<String, Float> scores) {
        this.scores = scores;
    }

}

3. HibernateUtil.java

package map;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
    public static final SessionFactory sessionFactory;

    static {
        try {
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(cfg.getProperties()).build();
            sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static final ThreadLocal<Session> session = new ThreadLocal<Session>();

    public static Session currentSession() throws HibernateException {
        Session s = session.get();
        if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession() throws HibernateException {
        Session s = session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

4. PersonManager.java

package map;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class PersonManager {
    public static void main(String[] args) {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }

    // Person生成&保存
    private void createAndStorePerson() {
        // セッション
        Session session = HibernateUtil.currentSession();
        // TX
        Transaction tx = session.beginTransaction();
        // Person生成
        Person person = new Person();
        // 属性
        person.setAge(18);
        person.setName("佐藤君");
        // 属性追加
        person.getScores().put("数学", 90F);
        person.getScores().put("英語", 80F);

        session.save(person);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

実行結果

1. 表が自動生成される。
(この設定によってだ。 update

mysql> desc person_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11)      | NO   | PRI | NULL    | auto_increment |
| age       | int(11)      | NO   |     | NULL    |                |
| name      | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> desc score_inf;
+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| person_id    | int(11)      | NO   | PRI | NULL    |       |
| mark         | float        | YES  |     | NULL    |       |
| subject_name | varchar(255) | NO   | PRI | NULL    |       |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

2. データが二つのテーブルに挿入される。

mysql> select * from person_inf;
+-----------+-----+-----------+
| person_id | age | name      |
+-----------+-----+-----------+
|         1 |  18 | 佐藤君    |
+-----------+-----+-----------+
1 row in set (0.00 sec)

mysql> select * from score_inf;
+-----------+------+--------------+
| person_id | mark | subject_name |
+-----------+------+--------------+
|         1 |   90 | 数学         |
|         1 |   80 | 英語         |
+-----------+------+--------------+
2 rows in set (0.00 sec)

Hibernate - Set属性マッピング

Setを持つ永続化クラスの保存サンプル。

キーのAnnotaion

  • @ElementCollection
  • @ColletionTable
  • @Column
  • @OrderColumn

※ Listとは異なるのは、Setは順序がなく重複を許さないため、@OrderColumnは不要である!
※ SetのIFのみ使え、実装は使えない。

1. hibernate.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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 接続情報 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">Int198429#</property>
        <!-- 各種設定 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- プール内最大Statement -->
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>

        <property name="hibernate.c3p0.validate">true</property>
        <!-- DB方言解消 -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 必要に応じて表生成 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 生成SQL表示 -->
        <property name="show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <!-- マッピングテーブル -->
        <!--  mapping class="entity.Item"/ -->
        <!-- mapping class="set.Person"/>  -->
        <mapping class="map.Person"/>
    </session-factory>
</hibernate-configuration>

2. Person.java

package set;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "person_inf")
public class Person {
    @Id
    @Column(name = "perosn_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private int age;

    // 集合属性
    @ElementCollection(targetClass = String.class)
    // マッピング表
    @CollectionTable(name = "school_inf", joinColumns = @JoinColumn(name = "person_id", nullable = false))
    // マッピング列
    @Column(name = "school_name", nullable=false)
    // ここはSetのみ使える
    private Set<String> schools = new HashSet<String>();

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return this.id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    public Set<String> getSchools() {
        return schools;
    }

    public void setSchools(Set<String> schools) {
        this.schools = schools;
    }
}

3. HibernateUtil.java

package set;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
    public static final SessionFactory sessionFactory;

    static {
        try {
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(cfg.getProperties()).build();
            sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static final ThreadLocal<Session> session = new ThreadLocal<Session>();

    public static Session currentSession() throws HibernateException {
        Session s = session.get();
        if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession() throws HibernateException {
        Session s = session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

4. PersonManager.java

package set;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class PersonManager {
    public static void main(String[] args) {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }

    // Person生成&保存
    private void createAndStorePerson() {
        // セッション
        Session session = HibernateUtil.currentSession();
        // TX
        Transaction tx = session.beginTransaction();
        // Person生成
        Person person = new Person();
        // 属性
        person.setAge(18);
        person.setName("佐藤君");
        // 属性追加
        person.getSchools().add("小学校");
        person.getSchools().add("中学校");
        session.save(person);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

実行結果

1. 表が自動生成される。
(この設定によってだ。 update

mysql> desc person_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| perosn_id | int(11)      | NO   | PRI | NULL    | auto_increment |
| age       | int(11)      | NO   |     | NULL    |                |
| name      | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> desc school_inf;
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| person_id   | int(11)      | NO   | PRI | NULL    |       |
| school_name | varchar(255) | NO   | PRI | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

2. データが二つのテーブルに挿入される。

mysql> select * from person_inf;
+-----------+-----+-----------+
| perosn_id | age | name      |
+-----------+-----+-----------+
|         1 |  18 | 佐藤君    |
+-----------+-----+-----------+
1 row in set (0.00 sec)

mysql> select * from school_inf;
+-----------+-------------+
| person_id | school_name |
+-----------+-------------+
|         1 | 中学校      |
|         1 | 小学校      |
+-----------+-------------+
2 rows in set (0.00 sec)

Hibernate - List属性マッピング

Listを持つ永続化クラスの保存サンプル。

キーのAnnotaion

  • @ElementCollection
  • @ColletionTable
  • @Column
  • @OrderColumn

1. hibernate.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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 接続情報 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">xxxx</property>
        <!-- 各種設定 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- プール内最大Statement -->
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>

        <property name="hibernate.c3p0.validate">true</property>
        <!-- DB方言解消 -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 必要に応じて表生成 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 生成SQL表示 -->
        <property name="show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <!-- マッピングテーブル -->
        <!--  mapping class="entity.Item"/ -->
        <mapping class="list.Person"/>
    </session-factory>
</hibernate-configuration>

2. Person.java

package list;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OrderColumn;
import javax.persistence.Table;

@Entity
@Table(name = "person_inf")
public class Person {
    @Id
    @Column(name = "perosn_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private int age;

    // 集合属性
    @ElementCollection(targetClass = String.class)
    // マッピング表
    @CollectionTable(name = "school_inf", joinColumns = @JoinColumn(name = "person_id", nullable = false))
    // マッピング列
    @Column(name = "school_name")
    // index
    @OrderColumn(name = "list_order")
    private List<String> schools = new ArrayList<>();

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return this.id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    public void setSchools(List<String> schools) {
        this.schools = schools;
    }

    public List<String> getSchools() {
        return this.schools;
    }
}

3. HibernateUtil.java

package list;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
    public static final SessionFactory sessionFactory;

    static {
        try {
            Configuration cfg = new Configuration().configure();
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                    .applySettings(cfg.getProperties()).build();
            sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static final ThreadLocal<Session> session = new ThreadLocal<Session>();

    public static Session currentSession() throws HibernateException {
        Session s = session.get();
        if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession() throws HibernateException {
        Session s = session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

4. PersonManager.java

package list;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class PersonManager {
    public static void main(String[] args) {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }

    // Person生成&保存
    private void createAndStorePerson() {
        // セッション
        Session session = HibernateUtil.currentSession();
        // TX
        Transaction tx = session.beginTransaction();
        // Person生成
        Person person = new Person();
        // 属性
        person.setAge(18);
        person.setName("佐藤君");
        // 属性追加
        person.getSchools().add("小学校");
        person.getSchools().add("中学校");
        session.save(person);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

実行結果

1. 表が自動生成される。
(この設定によってだ。 update

mysql> desc person_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| perosn_id | int(11)      | NO   | PRI | NULL    | auto_increment |
| age       | int(11)      | NO   |     | NULL    |                |
| name      | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.02 sec)

mysql> desc school_inf;
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| person_id   | int(11)      | NO   | PRI | NULL    |       |
| school_name | varchar(255) | YES  |     | NULL    |       |
| list_order  | int(11)      | NO   | PRI | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

2. データが二つのテーブルに挿入される。

mysql> select * from person_inf;
+-----------+-----+-----------+
| perosn_id | age | name      |
+-----------+-----+-----------+
|         1 |  18 | 佐藤君    |
+-----------+-----+-----------+
1 row in set (0.00 sec)

mysql> select * from school_inf;
+-----------+-------------+------------+
| person_id | school_name | list_order |
+-----------+-------------+------------+
|         1 | 小学校      |          0 |
|         1 | 中学校      |          1 |
+-----------+-------------+------------+
2 rows in set (0.00 sec)

Hibernate - 永続化オブジェクト

参考:第10章 オブジェクトを扱う

永続化クラスの要件

永続化オブジェクトの状態

  • Transient : newした状態
  • Persistent : sessionスコープにある
  • Detached : Persistent状態だったオブジェクトがsessionクローズされた状態

Transient ⇒ Persistent

  • Serializable save(Object obj)
  • Serializable save(Object obj, Object pk)
  • void persist(Object obj)
  • void save(Object obj, Object pk)
import java.math.BigDecimal;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import entity.Item;

public class TestPersistent {
    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();

        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        // Transient状態
        Item item = new Item();
        item.setPrice(new BigDecimal(100));
        item.setName("item01");

        // TX開始
        Transaction tx = session.beginTransaction();

        // Transient状態 ⇒ Persistent状態
        session.save(item);
        // save(object, pk)
        // persist(object) TX外で実行された場合、即時insert発行はしない
        // persist(object, pk)

        // コミット
        tx.commit();

        session.close();
    }
}

Persistent取得

  • load : 遅延取得、データない場合例外
  • get : 即時取得、データない場合null
  • ロックモード指定可能 : LockOptions.XXXX
import java.math.BigDecimal;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import entity.Item;

public class TestPersistent2 {
    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();

        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        // 即時SQL発行
        Item item1 = (Item) session.get(Item.class, 15);

        // 遅延SQL発行
        Item item2 = (Item) session.load(Item.class, 15);

        // 即時SQL発行 ⇒ null
        Item item3 = (Item) session.get(Item.class, 999);

        // 遅延SQL発行
        Item item4 = (Item) session.load(Item.class, 999);
        // この時loadが実行されSQL発行
        // Exception in thread "main" org.hibernate.ObjectNotFoundException:
        // No row with the given identifier exists: [entity.Item#999]
        item4.setPrice(new BigDecimal(999));

        session.close();
    }
}

Persistent状態オブジェクト更新

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import entity.Item;

public class TestPersistent2 {
    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();

        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        // TX開始
        Transaction tx = session.beginTransaction();

        // Persistentオブジェクト取得
        Item item1 = (Item) session.get(Item.class, 15);
        item1.setName("item99");
        session.flush();
        tx.commit();
        session.close(); //
    }
}

Persistent状態オブジェクト削除 : 削除されたオブジェクトはTransient状態になる

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import entity.Item;

public class TestPersistent3 {
    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();

        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        // TX開始
        Transaction tx = session.beginTransaction();

        // Persistentオブジェクト取得
        Item item1 = (Item) session.get(Item.class, 15);
        // 削除
        session.delete(item1);

        tx.commit();
        session.close(); //
    }
}

Detached状態オブジェクト更新
※あるセッションで使用したインスタンスを別の新しいセッションで使おうとしない限り、 update() や saveOrUpdate() や merge() を使う必要はありません。アプリケーション全体を通じて、これらのメソッドを全く使わないこともあります。

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import entity.Item;

public class TestPersistent4 {
    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();
        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        // Persistentオブジェクト取得
        Item item1 = (Item) session.get(Item.class, 14);
        // item1はDetached状態になる
        session.close();

        Session session2 = sf.openSession();
        // TX開始
        Transaction tx = session2.beginTransaction();

        item1.setName("item14");

        // Persitent状態にする
        session2.update(item1);

        // save()かupdate()か
        // session2.saveOrUpdate(item1);

        // merge()
        // Persistent状態にはならない
        // session2.merge(item1);

        // merge() は以下のように非常に異なります:
        //
        // 同じ識別子を持つ永続化インスタンスがその時点でセッションと関連付いているならば、引数で受け取ったオブジェクトの状態を永続化インスタンスにコピーします。
        // 永続化インスタンスがその時点でセッションに関連付いていないなら、データベースからそれをロードするか、あるいは、新しい永続化インスタンスを作成します。
        // 永続化インスタンスが返されます。
        // 引数として与えたインスタンスはセッションと関連を持ちません。それは、分離状態のままです。

        tx.commit();
        session2.close();
    }
}

Hibernate - 設定ファイル概要

Hibernateの永久化クラスの操作はSessionFactoryを離れない。
SessionFactoryはConfigurationオブジェクトから生成され、逆にConfigurationの唯一の機能はSessionFactoryに生成であり、生成後は破棄される。

Configurationの三つの生成方法

package dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public abstract class DaoSupport {
    protected Session getSession() {

        // 1. hibernate.cfg.xmlでConfiguration生成
        Configuration conf = new Configuration()
        // 引数なし : hibernate.cfg.xml
        // 引数あり : 引数の設定ファイル
                .configure();

        // // 2. hibernate.properitesでConfiguration生成
        // Configuration conf = new Configuration()
        // // 永久化クラス追加
        // .addAnnotatedClass(entity.Item.class);

        // 3. コードだけでConfiguration生成
        // Configuration conf = new Configuration()
        // // 永久化クラス追加
        // .addAnnotatedClass(entity.Item.class)
        // // プロパティ設定
        // .setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver")
        // .setProperty("hibernate.connection.url","jdbc:mysql://localhost/hibernate")
        // .setProperty("hibernate.connection.username", "root")
        // .setProperty("hibernate.connection.password", "xxxxx")
        // .setProperty("hibernate.c3p0.max_size", "20")
        // .setProperty("hibernate.c3p0.min_size", "1")
        // .setProperty("hibernate.c3p0.timeout", "5000")
        // .setProperty("hibernate.c3p0.max_statements", "100")
        // .setProperty("hibernate.c3p0.idle_test_period", "3000")
        // .setProperty("hibernate.c3p0.acquire_increment", "2")
        // .setProperty("hibernate.c3p0.validate", "true")
        // .setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect")
        // .setProperty("show_sql","true")
        // .setProperty("hibernate.format_sql","true");

        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(conf.getProperties()).build();

        // SessionFactory生成
        SessionFactory sf = conf.buildSessionFactory(serviceRegistry);
        // Session生成
        Session session = sf.openSession();

        return session;
    }
}

Configurationの属性

  • JDBC接続

    • hibernate.connection.driver_class
    • hibernate.connection.url
    • hibernate.connection.username
    • hibernate.connection.password
    • hibernate.connection.pool_size : 実際のプロジェクトではC3P0かProxoolを使うのが性能面でよい
    • ほか色々
  • RDMSの方言

    • hieernate.dialect : DB方言解消

      • org.hibernate.dialect.MySQL5InnoDBDialect
      • org.hibernate.dialect.PostgreSQL82Dialect
      • org.hibernate.dialect.Oracle10gDialect
      • ほか色々
  • JNDI(Java Naming Directory Interface): Hibernateがデータを直接管理しない場合

  • Hibernateトランザクション

    • hibernate.transaction.factory_class : HibernateのTX工場指定。TransactionFactoryかサブクラスである。
    • hibernate.transaction.manager_lookup_class : うん・・・
    • hibernate.transaction.flush_before_completion : TX終了後、flushするか
    • hibernate.transaction.auto_close_session : TX終了後、sessionを閉じるか
    • jta.UserTransaction : JNDI名を指定し、JTATransactionFactoryを使いアプリからJTA UserTransactionを取得する
  • 2次キャッシュ

  • ほか

    • hibernate.show_sql
    • hibernate.format_sql
    • hibernate.use_sql_comments : デバックに有効なコメント
    • hibernate.jdbc.fetch_size : 本質はStatement.setFetchSize()メソッド
    • hibernate.jdbc.batch_size : JDBC2のバッチ更新サイズ、5-30勧め?
    • hibernate.connection.autocommit : 自動コミット、勧めしない
    • hibernate.hbm2ddl.auto : SessionFactory生成時に永久化クラスを基に表を作りなおすか? 属性値 : validate, update, create, create-drop