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)