`
wangqiang6028
  • 浏览: 86160 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Hibernate复合主键映射

阅读更多

Hibernate复合主键映射

目录:

1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起

2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用

 

  在日常开发中会遇到这样一种情况,数据库中的某张表需要多个字段列才能唯一确定一行记录,这时表需要使用复合主键。面对这样的情况Hibernate为我们提供了两种方式来解决复合主键问题。

 

方式一:将复合主键对应的属性与实体其他普通属性放在一起

例如实体类People中"id"和"name"属性对应复合主键:

复制代码
/*实体类,使用复合主键必须实现Serializable接口*/
public class People implements Serializable
{
    private static final long serialVersionUID = -4888836126783955019L;
    
    private String id;
    private String name;
    private int age;
    
    public People()
    {
        
    }

    public String getId()
    {
        return id;
    }

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

    public String getName()
    {
        return name;
    }

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

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        People other = (People) obj;
        if (id == null)
        {
            if (other.id != null)
                return false;
        }
        else if (!id.equals(other.id))
            return false;
        if (name == null)
        {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }
}
复制代码

People.hbm.xml:

复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.People" table="people">
        <!-- 复合主键使用composite-id标签 -->
        <composite-id>
            <!-- key-property标签表示哪一些属性对应复合主键 -->
            <key-property name="id" column="id" type="string"></key-property>
            <key-property name="name" column="name" type="string"></key-property>
        </composite-id>

        <property name="age" column="age" type="integer"></property>
    </class>
</hibernate-mapping>
复制代码

Hibernate中使用复合主键时需要注意一些规则:

1. 使用复合主键的实体类必须实现Serializable接口。必须实现Serializable接口的原因很简单,我们查找数据的时候是根据主键查找的。打开Hibernate的帮助文档我们可以找到get与load方法的声明形式如下:

Object load(Class theClass,Serializable id)

Object get(Class theClass,Serializable id)

当我们查找复合主键类的对象时,需要传递主键值给get()或load()方法的id参数,而id参数只能接收一个实现了Serializable接口的对象。而复合主键类的主键不是一个属性可以表示的,所以只能先new出复合主键类的实例(例如:new People()),然后使用主键属性的set方法将主键值赋值给主键属性,然后将整个对象传递给get()或load()方法的id参数,实现主键值的传递,所以复合主键的实体类必须实现Serializable接口。

2. 使用复合主键的实体类必须重写equals和hashCode方法。必须重写equals和hashCode方法也很好理解。这两个方法使用于判断两个对象(两条记录)是否相等的。为什么要判断两个对象是否相等呢?因为数据库中的任意两条记录中的主键值是不能相同的,所以我们在程序中只要确保了两个对象的主键值不同就可以防止主键约束违例的错误出现。也许这里你会奇怪为什么不使用复合主键的实体类不重写这两个方法也没有主键违例的情况出现,这是因为使用单一主键方式,主键值是Hibernate来维护的,它会确保主键不会重复,而复合主键方式,主键值是编程人员自己维护的,所以必须重写equals和hashCode方法用于判断两个对象的主键是否相同。

3. 重写的equals和hashCode方法,只与主键属性有关,普通属性不要影响这两个方法进行判断。这个原因很简单,主键才能决定一条记录,其他属性不能决定一条记录。

 

保存测试:

复制代码
public class Client
{
    public static void main(String[] args)
    {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        
        try
        {
            tx = session.beginTransaction();
            
            People people = new People();
            /*主键值由我们自己维护*/
            people.setId("123456");
            people.setName("zhangsan");
            people.setAge(40);
            
            session.save(people);
            
            tx.commit();
        }
        catch (Exception e)
        {
            if(tx != null)
            {
                tx.rollback();
            }
            
            e.printStackTrace();
        }
        finally
        {
            session.close();
        }
    }
}
复制代码

看看数据库:

数据被正确的插入到数据库中了。

 

读取数据测试:

复制代码
public class Client
{
    public static void main(String[] args)
    {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        
        try
        {
            tx = session.beginTransaction();
            
            /*查询复合主键对象,需要先构建主键*/
            People peoplePrimaryKey = new People();
            peoplePrimaryKey.setId("123456");
            peoplePrimaryKey.setName("zhangsan");
            
            /*然后将构建的主键值传入get方法中获取对应的People对象*/
            People people = (People)session.get(People.class, peoplePrimaryKey);
            
            System.out.println("people age is:"+people.getAge());
            
            tx.commit();
        }
        catch (Exception e)
        {
            if(tx != null)
            {
                tx.rollback();
            }
            
            e.printStackTrace();
        }
        finally
        {
            session.close();
        }
    }
}
复制代码

控制台输出:

people age is:40

可以看到数据成功的取出了。

 

方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用。

主键类:

复制代码
/*必须实现Serializable接口*/
public class PeoplePrimaryKey implements Serializable
{
    private static final long serialVersionUID = -1190986010439330142L;
    
    /*复合主键值*/
    private String id;
    private String name;
    
    public PeoplePrimaryKey()
    {
        
    }
    
    /*复合主键值的get和set方法*/
    public String getId()
    {
        return id;
    }

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

    public String getName()
    {
        return name;
    }

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

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PeoplePrimaryKey other = (PeoplePrimaryKey) obj;
        if (id == null)
        {
            if (other.id != null)
                return false;
        }
        else if (!id.equals(other.id))
            return false;
        if (name == null)
        {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }
}
复制代码

实体类:

复制代码
public class People
{
    /*持有主键类的一个引用,使用该引用作为这个类的OID*/
    private PeoplePrimaryKey peoplePrimaryKey;
    private int age;
    
    public People()
    {
        
    }
    
    public PeoplePrimaryKey getPeoplePrimaryKey()
    {
        return peoplePrimaryKey;
    }

    public void setPeoplePrimaryKey(PeoplePrimaryKey peoplePrimaryKey)
    {
        this.peoplePrimaryKey = peoplePrimaryKey;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }
}
复制代码

People.hbm.xml文件稍有一点变动:

复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.suxiaolei.hibernate.pojos.People" table="people">
        <!-- 复合主键使用composite-id标签 -->
        <!--
        name - 指定了复合主键对应哪一个属性
        class - 指定了复合主键属性的类型
        -->
        <composite-id name="peoplePrimaryKey" class="com.suxiaolei.hibernate.pojos.PeoplePrimaryKey">
            <!-- key-property指定了复合主键由哪些属性组成 -->
            <key-property name="id" column="id" type="string"></key-property>
            <key-property name="name" column="name" type="string"></key-property>
        </composite-id>

        <property name="age" column="age" type="integer"></property>
    </class>
</hibernate-mapping>
复制代码

  场景测试与方式一大同小异这里不再举例了。
转自:http://www.cnblogs.com/otomedaybreak/archive/2012/01/25/2329390.html

 

分享到:
评论

相关推荐

    hibernate复合主键映射

    复合主键映射 &lt;br&gt;通常将复合主键相关属性,单独抽取出来,建立一个独立的类 * 必须实现序列化接口 * 必须实现equals和hashcode方法 采用标签进行映射,其它属性采用正常映射

    hibernate 无主键表映射

    hibernate 无主键表映射资源说明: 1. 简单Demo 2. Demo对应的sql语句 3. 对应博客文档

    Java的Hibernate框架中复合主键映射的创建和使用教程

    复合主键映射用起来比普通的增加主键字段要复杂,这里我们就来共同学习Java的Hibernate框架中复合主键映射的创建和使用教程,需要的朋友可以参考下

    Hibernate学习笔记

    023 复合主键 关联映射 024 其它 关联映射 025 hibernate 悲观锁、乐观锁 026 hibernate 操作树形结构 027 hibernate 查询语言(HQL) 028 hibernate 缓存(性能优化策略) 029 hibernate 抓取策略

    Hibernate入门(代码+笔记)

    总共分5部分:1和2为hibernate入门,3为hibernate实体映射,4为hibernate复合主键,5为hibernate实体层设计.

    Hibernate映射配置入门进阶详解

    1)根元素映射&lt;hibernate-mapping/&gt; 2)类映射 3)属性映射 4)主键的配置 5)主键生成策略 复合主键策略 史上最详细

    hibernate学习笔记

    复合(联合)主键映射(hibernate_composite) 27 集合(collection)映像 (hibernate_collection) 28 Hibernate 对数据库的并发支持 30 悲观锁(hibernate_pessimistic) 30 乐观锁(hibernate_optimistic) 32 HQL...

    Hibernate3.1_学习源码

    04 04Hibernate_Composite : 复合主键的使用,在开发中很少用到,一般良好的设计都会为一个表添加一个自动增长的主键标识列。其中重点配置方法和Hibernate中普遍采用的方法链编程的使用。还需注意可以将组合主键构建...

    Hibernate Annotations 中文文档

    2.2.6. 映射复合主键与外键 2.2.7. 映射二级表(secondary tables) 2.3. 映射查询 2.3.1. 映射EJBQL/HQL查询 2.3.2. 映射本地化查询 2.4. Hibernate独有的注解扩展 2.4.1. 实体 2.4.2. 标识符 2.4.3. 属性 2.4...

    J2EE三大框架_笔记_a

    18-Hibernate复合主键笔记 20-22Hibernate_容器映射技术笔记 23-26Hibernate数据关联技术笔记 27-32Hibernate数据关联技术_1vs1应用案例_笔记 33-37Hibernate1对N案例笔记 38-43Hibernate多对多案例笔记 J2EE框架_...

    hibernate注解案例

    Hibernate 的注解学习 ExportDBAnnotation HibernateAnnotationUtils 【一对一】关系映射【一对多】关系映射 【多对多】关系映射 【composite复合主键】关系映射【component组件】关系映射

    J2EE框架_笔记_c

    18-Hibernate复合主键笔记 20-22Hibernate_容器映射技术笔记 23-26Hibernate数据关联技术笔记 27-32Hibernate数据关联技术_1vs1应用案例_笔记 33-37Hibernate1对N案例笔记 38-43Hibernate多对多案例笔记 J2EE框架_...

    hibernate annotation 中文文档

    2.2.6. 映射复合主键与外键 2.2.7. 映射二级表(secondary tables) 2.3. 映射查询 2.3.1. 映射EJBQL/HQL查询 2.3.2. 映射本地化查询 2.4. Hibernate独有的注解扩展 2.4.1. 实体 2.4.2. 标识符 2.4.3. 属性 2.4.3.1. ...

    J2EE框架_笔记_b

    18-Hibernate复合主键笔记 20-22Hibernate_容器映射技术笔记 23-26Hibernate数据关联技术笔记 27-32Hibernate数据关联技术_1vs1应用案例_笔记 33-37Hibernate1对N案例笔记 38-43Hibernate多对多案例笔记 J2EE框架_...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     15.1.2 按照主键映射  15.2 映射单向多对多关联  15.3 映射双向多对多关联关系  15.3.1 关联两端使用元素  15.3.2 在inverse端使用元素  15.3.3 使用组件类集合  15.3.4 把多对多关联分解为两个一对多关联 ...

    javaEE框架笔记,识货人下

    18-Hibernate复合主键笔记.pdf 19-Hibernate实体层设计笔记.pdf 2-JSP+JDBC_真分页(基于Oracle数据库分页)笔记.pdf 20-22Hibernate_容器映射技术笔记.pdf 23-26Hibernate数据关联技术笔记.pdf 27-32Hibernate数据...

    hibernate annotation帮助文档

    2.2.6. 映射复合主键与外键 2.2.7. 映射二级表(secondary tables) 2.3. 映射查询 2.3.1. 映射EJBQL/HQL查询 2.3.2. 映射本地化查询 2.4. Hibernate独有的注解扩展 2.4.1. 实体 2.4.2. 标识符 2.4.3. 属性 2.4...

Global site tag (gtag.js) - Google Analytics