一个简单的复合主键的做关联类的例子(转自JavaEye)

robbin
论坛管理员



性别:
年龄:30
十二宫图:
加入时间: 2003/09/07
文章: 2028
来自: 上海

时间: 2004-10-20 16:12:30    标题: 一个简单的复合主键的做关联类的例子

我写这个例子的来由是因为haha1903提了一个这种类型的问题

http://forum.javaeye.com/viewtopic.php?t=8285

场景是这样的:

用户类User,物品类Goods,每次记录用户使用物品的情况,情况包括谁在什么时间借了什么物品。其中有一个约束条件就是用户只能对同一物品使用一次。使用记录类为Record类。我们可以看出User对Record是1:n多的关系,Record对Goods是n:1的关系,而User和Goods之间没有之间的关系。

RecordId类是复合主键类,分别以n:1关联User类,n:1关联Goods类。RecordId类需要实现equals方法,需要实现Serializable。而Record类用RecordId来做主键。

类定义如下:

java代码: 


/*
* Created on 2004-10-20
*
*/

package com. javaeye;

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

/**
* @author robbin

*/

public class User {

    private Long id;

    private String name;

    private Set usingRecords = new HashSet ( );

    /**
     * @return Returns the id.
     */

    public Long getId ( ) {
        return id;
    }

    /**
     * @param id
     *            The id to set.
     */

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

    /**
     * @return Returns the name.
     */

    public String getName ( ) {
        return name;
    }

    /**
     * @param name
     *            The name to set.
     */

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

    /**
     * @return Returns the usingRecords.
     */

    public Set getUsingRecords ( ) {
        return usingRecords;
    }

    /**
     * @param usingRecords
     *            The usingRecords to set.
     */

    public void setUsingRecords ( Set usingRecords ) {
        this. usingRecords = usingRecords;
    }

    public void useGoods (Goods goods ) {
        RecordId id = new RecordId ( );
        id. setUser (this );
        id. setGoods (goods );
        Record record = new Record ( );
        record. setRecordId (id );
        record. setRecordTime ( Calendar. getInstance ( ) );
        usingRecords. add (record );
    }

    public void removeRecord (Record record ) {
        usingRecords. remove (record );
    }
}



java代码: 



/*
* Created on 2004-10-20
*
*/

package com. javaeye;

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

/**
* @author robbin

*/

public class Goods {

    private Long id;

    private String name;

    private Set usedRecords = new HashSet ( );

    /**
     * @return Returns the id.
     */

    public Long getId ( ) {
        return id;
    }

    /**
     * @param id
     *            The id to set.
     */

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

    /**
     * @return Returns the name.
     */

    public String getName ( ) {
        return name;
    }

    /**
     * @param name
     *            The name to set.
     */

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

    /**
     * @return Returns the usedRecords.
     */

    public Set getUsedRecords ( ) {
        return usedRecords;
    }

    /**
     * @param usedRecords
     *            The usedRecords to set.
     */

    public void setUsedRecords ( Set usedRecords ) {
        this. usedRecords = usedRecords;
    }

}



java代码: 


/*
* Created on 2004-10-20
*
*/

package com. javaeye;

import java. io. Serializable;

/**
* @author robbin

*/

public class RecordId implements Serializable {

    private User user;

    private Goods goods;

    /**
     * @return Returns the goods.
     */

    public Goods getGoods ( ) {
        return goods;
    }

    /**
     * @param goods
     *            The goods to set.
     */

    public void setGoods (Goods goods ) {
        this. goods = goods;
    }

    /**
     * @return Returns the user.
     */

    public User getUser ( ) {
        return user;
    }

    /**
     * @param user
     *            The user to set.
     */

    public void setUser (User user ) {
        this. user = user;
    }

    public boolean equals ( Object obj ) {
        return (obj instanceof RecordId )
                && (this. getUser ( ). equals ( ( (RecordId ) obj ). getUser ( ) ) )
                && (this. getGoods ( ). equals ( ( (RecordId ) obj ). getGoods ( ) ) );
    }

    public int hashCode ( ) {
        return this. getUser ( ). hashCode ( ) ^ this. getGoods ( ). hashCode ( );
    }
}



java代码: 


/*
* Created on 2004-10-20
*
*/

package com. javaeye;

import java. util. Calendar;

/**
* @author robbin

*/

public class Record {

    private RecordId recordId;

    private Calendar recordTime;

    /**
     * @return Returns the recordId.
     */

    public RecordId getRecordId ( ) {
        return recordId;
    }

    /**
     * @param recordId
     *            The recordId to set.
     */

    public void setRecordId (RecordId recordId ) {
        this. recordId = recordId;
    }

    /**
     * @return Returns the recordTime.
     */

    public Calendar getRecordTime ( ) {
        return recordTime;
    }

    /**
     * @param recordTime
     *            The recordTime to set.
     */

    public void setRecordTime ( Calendar recordTime ) {
        this. recordTime = recordTime;
    }
}

返回顶端
robbin
论坛管理员



性别:
年龄:30
十二宫图:
加入时间: 2003/09/07
文章: 2028
来自: 上海

时间: 2004-10-20 16:17:43    标题:

映射文件配置如下:

xml代码: 


<?xml version= "1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
        <class name= "com.javaeye.User">
                <id name= "id" unsaved-value= "null">
                        <generator class= "native"/>
                </id>
               
                <property name= "name"/>
               
                <set name= "usingRecords" inverse= "true" lazy= "true" cascade= "all-delete-orphan">
                        <key column= "user_id" />
                        <one-to-many class= "com.javaeye.Record"/>
                </set>
        </class>
       
</hibernate-mapping>




xml代码: 

<?xml version= "1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
        <class name= "com.javaeye.Goods">
                <id name= "id" unsaved-value= "null">
                        <generator class= "native"/>
                </id>
               
                <property name= "name"/>
               
                <set name= "usedRecords" inverse= "false" lazy= "true" cascade= "all-delete-orphan">
                        <key column= "goods_id" />
                        <one-to-many class= "com.javaeye.Record"/>
                </set>
        </class>
       
</hibernate-mapping>



xml代码: 


<?xml version= "1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
        <class name= "com.javaeye.Record">
                <composite-id name= "recordId" class= "com.javaeye.RecordId" unsaved-value= "any" >
                        <key-many-to-one name= "user" column= "user_id" class= "com.javaeye.User" />
                        <key-many-to-one name= "goods" column= "goods_id" class= "com.javaeye.Goods" />
                </composite-id>
               
                <property name= "recordTime" type= "calendar"/>

        </class>
       
</hibernate-mapping>

返回顶端
robbin
论坛管理员



性别:
年龄:30
十二宫图:
加入时间: 2003/09/07
文章: 2028
来自: 上海

时间: 2004-10-20 16:26:43    标题:

记录物品使用情况的代码书写如下:

java代码: 


Goods goods = new Goods ( );
goods. setName ( "book" );
s. save (goods );
User user = new User ( );
user. setName ( "robbin" );
s. save (user );

// 用户使用物品
user. useGoods (goods );



当用户重复使用物品的时候,调用userGoods方法,Hibernate会抛出主键重复的错误。

判断用户是否使用某物品的办法如下:

java代码: 


RecordId id = new RecordId ( );
id. setUser (user );
id. setGoods (goods );

Record record = (Record ) session. get (Record. class, id );

if (record == null ) {
    user. usGoods (goods );
} else {
    throw new UsedGoodsException ( "..." );
}



然而需要指出的是,Gavin King并不提倡使用composite-id,如果你不是基于已有的数据库编程,而是重新设计数据库结构,那么建议使用UserType。你可以自定义一个UserType,包括User和Goods,并且在hbm中定义该UserType为unique的,同样可以达到目的。而这种方式的好处则是不需要你来手工维护id,而由Hibernate自动维护。UserType的使用方法参考手册5.2.4节和Hibernate自带的示例中的net.sf.hibernate.test.DoubleStringType。

你可能感兴趣的:(java)