powerdee.com
Google
 
このサイト内 Web
 
カウンタ

Hibernate Annotations

インデックスへ戻る
前回のマッピングファイルで動作していたサンプルを Hibernate Annotationsを使うように改良してみます。
当サンプルのソースコードはこちらです。

マッピング定義

Middlegenで生成したPOJO(Category.javaとItem.java)にアノテーションを追加しデータベーススキーマとマッピングを行います。

日付のプロパティは共通しているので、スーパークラスにしてみました。

package com.powerdee.model.annotations;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@MappedSuperclass
public class Entity implements Serializable {

    private Date insertDate;
     
    private Date updateDate;
     
    private Date deleteDate;

    @Column(name="DELETE_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getDeleteDate() {
        return deleteDate;
    }
    
    public void setDeleteDate(Date deleteDate) {
        this.deleteDate = deleteDate;
    }
    @Column(name="INSERT_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getInsertDate() {
        return insertDate;
    }

    public void setInsertDate(Date insertDate) {
        this.insertDate = insertDate;
    }

    @Column(name="UPDATE_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }
}

で、これをCategoryとItemが継承します。

package com.powerdee.model.annotations;

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

import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

/** @author Hibernate CodeGenerator */
@javax.persistence.Entity
@Table(name="CATEGORY")
public class Category extends Entity {

    /** identifier field */
    private Long categoryId;

    /** persistent field */
    private String name;

    /** persistent field */
    private Category category;

    /** persistent field */
    private List items = new ArrayList();

    /** persistent field */
    private List categories = new ArrayList();

    /** constructor */
    public Category(Long categoryId, String name, Category category) {
        this.categoryId = categoryId;
        this.name = name;
        this.category = category;
    }

    /** default constructor */
    public Category() {
    }

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="CATEGORY_ID")
    public Long getCategoryId() {
        return this.categoryId;
    }

    public void setCategoryId(Long categoryId) {
        this.categoryId = categoryId;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return this.name;
    }

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

    @ManyToOne(fetch=FetchType.LAZY, targetEntity=Category.class)
    @JoinColumn(name="PARENT_CATEGORY_ID")
    public Category getCategory() {
        return this.category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @OneToMany(fetch=FetchType.LAZY, mappedBy="category")
    @Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
    @OrderBy("itemId")
    public List getItems() {
        return this.items;
    }

    public void addItem(Item item) {
        if (item == null)
            throw new IllegalArgumentException("Can't add a null Category as item.");
        if (item.getCategory() != null)
        	item.getCategory().getItems().remove(item);
        
        item.setCategory(this);
        
        this.getItems().add(item);
    }

    private void setItems(List items) {
        this.items = items;
    }

    @OneToMany(fetch=FetchType.LAZY, mappedBy="category")
    @Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
    public List getCategories() {
        return this.categories;
    }

    public void addChildCategory(Category category) {
        if (category == null)
            throw new IllegalArgumentException("Can't add a null Category.");
        if (category.getCategory() != null)
        	category.getCategory().getCategories().remove(category);
        
        category.setCategory(this);
        
        this.getCategories().add(category);
    }

    private void setCategories(List categories) {
        this.categories = categories;
    }

    public String toString() {
        return new ToStringBuilder(this)
            .append("categoryId", getCategoryId())
            .toString();
    }

}

package com.powerdee.model.annotations;

import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;


/** @author Hibernate CodeGenerator */
@javax.persistence.Entity
@Table(name="ITEM")
public class Item extends Entity {

    /** identifier field */
    private Long itemId;

    /** nullable persistent field */
    private String name;

    /** nullable persistent field */
    private String description;

    /** nullable persistent field */
    private Integer price;

    /** persistent field */
    private Category category;

    /** constructor */
    public Item(Long itemId, String name, String description, Integer price, Category category) {
        this.itemId = itemId;
        this.name = name;
        this.description = description;
        this.price = price;
        this.category = category;
    }

    /** default constructor */
    public Item() {
    }

    /** minimal constructor */
    public Item(Long itemId, Category category) {
        this.itemId = itemId;
        this.category = category;
    }

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ITEM_ID")
    public Long getItemId() {
        return this.itemId;
    }

    public void setItemId(Long itemId) {
        this.itemId = itemId;
    }

    @Column(name="NAME")
    public String getName() {
        return this.name;
    }

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

    @Column(name="DESCRIPTION")
    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Column(name="PRICE")
    public Integer getPrice() {
        return this.price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @ManyToOne(fetch=FetchType.LAZY, targetEntity=Category.class)
    @JoinColumn(name="CATEGORY_ID", nullable=false)
    public Category getCategory() {
        return this.category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public String toString() {
        return new ToStringBuilder(this)
            .append("itemId", getItemId())
            .toString();
    }

}

Hibernate設定ファイルを変更する

mapping resourceは前回の設定なので、コメントにしてmapping packageとmapping classを追加しています。

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC 
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">demouser</property>
        <property name="connection.password">demouser</property> 
        <property name="connection.url">jdbc:mysql://localhost:3306/demo_db</property>
        <property name="show_sql">true</property>

<!--        
        <mapping resource="com/powerdee/model/Category.hbm.xml" />
        <mapping resource="com/powerdee/model/Item.hbm.xml" />
-->

        <mapping package="com.powerdee.model.annotations"/>    <-- 追加
        <mapping class="com.powerdee.model.annotations.Category"/>    <-- 追加
        <mapping class="com.powerdee.model.annotations.Item"/>    <-- 追加

    </session-factory>
</hibernate-configuration>

テストを実行する

変更箇所は1箇所のみです。configure()を呼び出すメソッドがConfiguration()から、AnnotationConfiguration()になっています。

package com.powerdee.model.annotations;

import java.util.Iterator;
import java.util.List;

import junit.framework.TestCase;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateAnnotationsTest extends TestCase {

    private static final SessionFactory sessionFactory;

    static {
        try {
            sessionFactory 
                = new AnnotationConfiguration()    <-- 変更
                    .configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() throws HibernateException {
        return sessionFactory.openSession();
    }

    public static void main(String[] args) {
        junit.textui.TestRunner.run(HibernateAnnotationsTest.class);
    }

    public void testInsertCategory() throws Exception {
        Session session = getSession();

        Item item1 = new Item();
        item1.setName("アイテムその1");
        Item item2 = new Item();
        item2.setName("アイテムその2");
        Item item3 = new Item();
        item3.setName("アイテムその3");
        
        Category childCategory = new Category();
        childCategory.setName("子カテゴリ");
        childCategory.addItem(item1);
        childCategory.addItem(item2);
        childCategory.addItem(item3);
        
        Category parentCategory = new Category();
        parentCategory.setName("親カテゴリ");
        parentCategory.addChildCategory(childCategory);

        Transaction transaction = session.beginTransaction();
        session.save(parentCategory);
        transaction.commit();
        session.close();
    }

    public void testSelectDeleteCategory() throws Exception {
        Session session = getSession();
        Transaction transaction = session.beginTransaction();
        
        String HQL 
            = "from Category cat where cat.category.categoryId is null";
        Query query = session.createQuery(HQL);
        List categoryList = query.list();
        Category parentCategory = (Category) categoryList.get(0);
        assertEquals("親カテゴリ", parentCategory.getName());
        
        Iterator categories = parentCategory.getCategories().iterator();
        Category childCategory = (Category) categories.next();
        assertEquals("子カテゴリ", childCategory.getName());
        
        Iterator items = childCategory.getItems().iterator();
        assertEquals("アイテムその1", ((Item) items.next()).getName());
        assertEquals("アイテムその2", ((Item) items.next()).getName());
        assertEquals("アイテムその3", ((Item) items.next()).getName());
        
        session.delete(parentCategory);
        transaction.commit();
        
        session.close();
    }
}

インデックスへ戻る


おすすめ書籍


HIBERNATE イン アクション

著者:Christain Bauer、Gavin Ki
出版社:ソフトバンク クリエイティブ(2005-12-28)
価格:¥4,410(税込)
Light Weight Java―JSF/Hibernate/SpringによるフレームワークでWebアプリケーションの開発効率向上

著者:岡本 隆史、金子 崇之、吉田 英嗣、権藤 夏男
出版社:毎日コミュニケーションズ(2005-04)
価格:¥3,360(税込)


ページTopへ / ▲Homeへ