复合主键,由多个字段组成主键,例如,使用firstname和lastname组成主键。
可以通过两种方式确定主键,一种是基于实体类的复合主键,另一种是通过定义主键类来实现。
不管通过哪种方式,复合主键都需要实现equals方法和hashcode方法,以作为不同数据之间是别的标志。
一.基于实体类属性的复合主键
主键由实体类中的属性组成。
1.
配置文件TUser.hbm.xml 
 <?xml version="1.0"?>
<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 <hibernate-mapping>
<hibernate-mapping>
 <class name="cn.blogjava.start.TUser" table="t_user" catalog="sample">
    <class name="cn.blogjava.start.TUser" table="t_user" catalog="sample">
 <composite-id>
        <composite-id>
 <key-property name="lastname" column="lastname" type="string" />
            <key-property name="lastname" column="lastname" type="string" />
 <key-property name="firstname" column="firstname" type="string" />
            <key-property name="firstname" column="firstname" type="string" />
 </composite-id>
        </composite-id>

 <property name="age" type="integer" column="age"/>
        <property name="age" type="integer" column="age"/>
 </class>
    </class>
 </hibernate-mapping>
</hibernate-mapping>

2.
TUser.java
package cn.blogjava.start;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
/**
 * TUser generated by hbm2java
 */
public class TUser implements java.io.Serializable {
    // Fields    
    private Integer age;
    private String firstname;
    private String lastname;
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
    
    public boolean equals(Object obj) {
        if(!(obj instanceof TUser)) {
            return false;
        }
        
        TUser user = (TUser)obj;
        return new EqualsBuilder()          // EqualsBuilder 和HashCodeBuilder均为apache common lang包中的工具类
            .appendSuper(super.equals(obj))
            .append(this.lastname, user.lastname)
            .append(this.firstname, user.firstname)
            .isEquals();        
    }
    
    public int hasCode() {
        return new HashCodeBuilder(-528253723, -475504089)
            .appendSuper(super.hashCode())
            .append(this.lastname).append(this.firstname)
            .toHashCode();
            
    }
}
3.
测试类HibernateTest.java
package cn.blogjava.start;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class HibernateTest extends TestCase {
    
    Session session = null;
    /**
     * JUnit中的setUp方法在TestCase初始化的时候会自动调用
     * 一般用于初始化公用资源
     */
    protected void setUp() {
        try {
            /**
             * 可以采用hibernate.properties或者hibernate.cfg.xml
             * 配置文件的初始化代码
             * 
             * 采用hibernate.properties
             * Configuration config = new Configuration();
             * config.addClass(TUser.class);
             */
            
            //采用hibernate.cfg.xml配置文件,与上面的方法对比,两个差异
            //1.Configuration的初始化方式
            //2.xml
            Configuration config = new Configuration().configure();
            SessionFactory sessionFactory = config.buildSessionFactory();
            session = sessionFactory.openSession();
            
        } catch (HibernateException e) {
            // TODO: handle exception
            e.printStackTrace();
        }        
    }
    /**
     * JUnit中的tearDown方法在TestCase执行完毕的时候会自动调用
     * 一般用于释放资源
     */    
    protected void tearDown() {
        try {
            session.close();        
        } catch (HibernateException e) {
            // TODO: handle exception
            e.printStackTrace();
        }        
    }    
    
    /**
     * 对象持久化测试(Insert方法)
     */        
    public void testInsert() {
        Transaction tran = null;
        try {
            tran = session.beginTransaction();
            TUser user = new TUser();
            user.setFirstname("bai");
            user.setLastname("yunfeng");
            user.setAge(26);
            session.save(user);
            session.flush();
            tran.commit();
        } catch (HibernateException e) {
            // TODO: handle exception
            e.printStackTrace();
            Assert.fail(e.getMessage());
            if(tran != null) {
                try {
                    tran.rollback();
                } catch (Exception e1) {
                    // TODO: handle exception
                    e1.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 对象读取测试(Select方法)
     */            
    public void testSelect(){
        TUser user = new TUser();
        user.setFirstname("bai");
        user.setLastname("yunfeng");
        
        user = (TUser)session.load(TUser.class, user);
        Assert.assertEquals(user.getAge().intValue(), 26);
    }
}