Hibernate触ってみたメモ

そろそろ仕事がらこの辺りもからんできそうなので家事育児の隙をついて弄ってみました。という備忘録的メモ。まぁ実際はSpring経由でやりそうなんですが、まず直接使ってみたいなぁと。

方針は以下。


-1. 事前準備 => RDBMS(今回、MySQL)にDatabaseとTableを作っとく

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

mysql> select * from depts;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | Development     |
|  2 | Sales           |
|  3 | Human Resources |
+----+-----------------+
3 rows in set (0.00 sec)

mysql> desc members;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | YES  |     | NULL    |       |
| name    | varchar(64) | YES  |     | NULL    |       |
| age     | int(11)     | YES  |     | NULL    |       |
| dept_id | int(11)     | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> select * from members;
+------+------+------+---------+
| id   | name | age  | dept_id |
+------+------+------+---------+
|    1 | aaa  |   11 |       1 |
|    2 | bbb  |   12 |       1 |
|    3 | ccc  |   13 |       1 |
|    4 | ddd  |   21 |       2 |
|    5 | eee  |   22 |       2 |
|    6 | fff  |   23 |       2 |
|    7 | ggg  |   31 |       3 |
|    8 | hhh  |   32 |       3 |
|    9 | iii  |   33 |       3 |
+------+------+------+---------+
9 rows in set (0.04 sec)


0. Maven Projectの作成

mvnコマンド経由でも何でもいいんですが、今回はEclipseで作りました。普通に作ったので省略。


1. pom.xmlにdependenciesを書き書き

試行錯誤の末、こんな感じ。

  <dependencies>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.15</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
  		<groupId>log4j</groupId>
  		<artifactId>log4j</artifactId>
  		<version>1.2.16</version>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.slf4j</groupId>
  		<artifactId>slf4j-log4j12</artifactId>
  		<version>1.4.2</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-annotations</artifactId>
  		<version>3.4.0.GA</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
  		<groupId>javassist</groupId>
  		<artifactId>javassist</artifactId>
  		<version>3.12.1.GA</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  </dependencies>

あまり良く解っていないのだけど、Logging周りがSlf4jというのになっていて、Log4jとのブリッジ的なものとしてslf4j-log4j12が必要っぽい。で、普通に入れると結構新しめなやつが入るのだけど、そうするとhibernate-coreが依存しているslf4j-apiとバージョン不一致を起こすので、一致させるようにしました。

あと、Hibernate-coreがこっそりとjavassistを使っているくせにpom上は依存していないみたいで、Runtimeでエラーが発生していたので、javassistも入れた、みたいな。


2. hibernate.cfg.xml

src/main/resources/hibernate.cfg.xmlを以下のように作成

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.url">jdbc:mysql://localhost/hogehoge</property>
    <property name="connection.username">root</property>
    <property name="connection.password">hogehoge</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

    <property name="show_sql">true</property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    <property name="current_session_context_class">thread</property>
 
    <mapping class="com.komamitsu.model.Dept"/>
    <mapping class="com.komamitsu.model.Member"/>
  </session-factory>
</hibernate-configuration>

createとか書いていたら、プログラムを起動する度にtableが空になる恐怖を味わったりしました。


3. entity的なclass的なもの

package com.komamitsu.model;
import java.io.Serializable;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;


@Entity
@Table(name="depts")
public class Dept implements Serializable {
  @Id
  @GeneratedValue
  private int id;
  private String name;
  @OneToMany(mappedBy="dept")
  private Set<Member> members;
  
  /**
   * @return the id
   */
  public int getId() {
    return id;
  }
  /**
   * @param id the id to set
   */
  public void setId(int id) {
    this.id = id;
  }
  /**
   * @return the name
   */
  public String getName() {
    return name;
  }
  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }
  /**
   * @return the members
   */
  public Set<Member> getMembers() {
    return members;
  }
  /**
   * @param members the members to set
   */
  public void setMembers(Set<Member> members) {
    this.members = members;
  }
  
  @Override
  public String toString() {
    return "id=" + id + ", name=" + name;
  }
}
package com.komamitsu.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="members")
public class Member {
  @Id
  @GeneratedValue
  private int id;
  private String name;
  private int age;
  @ManyToOne
  @JoinColumn(name="dept_id")
  private Dept dept;
  /**
   * @return the id
   */
  public int getId() {
    return id;
  }
  /**
   * @param id the id to set
   */
  public void setId(int id) {
    this.id = id;
  }
  /**
   * @return the name
   */
  public String getName() {
    return name;
  }
  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }
  /**
   * @return the age
   */
  public int getAge() {
    return age;
  }
  /**
   * @param age the age to set
   */
  public void setAge(int age) {
    this.age = age;
  }
  /**
   * @return the dept
   */
  public Dept getDept() {
    return dept;
  }
  /**
   * @param dept the dept to set
   */
  public void setDept(Dept dept) {
    this.dept = dept;
  }
  
  @Override
  public String toString() {
    return "id=" + id + ", name=" + name + ", age=" + age + ", dept=" + dept;
  }
}

@OneToMany, @ManyToOneとか使ってみたかったので使えて良かったなぁという。


4. main()

package com.komamitsu.runner;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.criterion.Restrictions;

import com.komamitsu.model.Dept;
import com.komamitsu.model.Member;

public class Runner {

  /**
   * @param args
   */
  public static void main(String[] args) {
    SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    
    Session session = sessionFactory.getCurrentSession();

    Transaction tx = session.beginTransaction();

    /*
    Dept dept = new Dept();
    dept.setName("Development");
    
    session.save(dept);
    */
    
    Criteria c = session.createCriteria(Dept.class);
    c.add(Restrictions.eq("name", "Sales"));
    List<Dept> list = c.list();
    System.out.println(list.size());
    
    for (Dept d : list)
      for (Member m : d.getMembers())
        System.out.println(m);
    
    tx.commit();

  }
}

まぁ普通な感じで。


5. 実行

Hibernate: select this_.id as id0_0_, this_.name as name0_0_ from depts this_ where this_.name=?
1
Hibernate: select members0_.dept_id as dept4_1_, members0_.id as id1_, members0_.id as id1_0_, members0_.age as age1_0_, members0_.dept_id as dept4_1_0_, members0_.name as name1_0_ from members members0_ where members0_.dept_id=?
id=6, name=fff, age=23, dept=id=2, name=Sales
id=4, name=ddd, age=21, dept=id=2, name=Sales
id=5, name=eee, age=22, dept=id=2, name=Sales

show_sql=trueなのでそれと混じっていますが、こんな感じで。


まぁなんというか普通ですよね... 普通のくせに何か長いな... とか。