Hibernate 表映射 主键生成策略与复合主键

主要分析三点:

一、数据表和Java类的映射 ;

二、单一主键映射和主键的生成策略 ;

三、复合主键的表映射 ;

一、数据表和Java类的映射 

Hibernate封装了数据库DDL语句,只需要将数据表和类之间实现映射,即可对数据表进行操作。

示例:数据库中存在表interface_admin.ds_area,实现表和类之间映射,其中单一主键oggKeyId,使用主键自动生成策略UUID,具体第二点进行阐述 。

package com.pec.model;

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

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

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "interface_admin.ds_area")
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
public class DsAreaModel implements Serializable {
    private static final long serialVersionUID = 1L;
    //电商平台代号(WS微商/CT村淘/TM天猫/JD京东)
    private String comId ;
    //行政省/直辖市代号
    private String provinceId ;
    //行政省/直辖市名称
    private String provinceName ;
    //地级市代号
    private String cityId ;
    //地级市名称
    private String cityName ;
    //行政区/县代号
    private String regiId ;
    //行政区/县名称
    private String regiName ;
    //创建时间
    private Timestamp creatDate ;
    //最后更新时间
    private Timestamp lastUpdDate ;
    //主键
    private String oggKeyId ;

    @Column(name = "com_id")
    public String getComId() {
        return comId;
    }
    public void setComId(String comId) {
        this.comId = comId;
    }

    @Column(name = "province_id")
    public String getProvinceId() {
        return provinceId;
    }
    public void setProvinceId(String provinceId) {
        this.provinceId = provinceId;
    }

    @Column(name = "province_nm")
    public String getProvinceName() {
        return provinceName;
    }
    public void setProvinceName(String provinceName) {
        this.provinceName = provinceName;
    }

    @Column(name = "city_id")
    public String getCityId() {
        return cityId;
    }
    public void setCityId(String cityId) {
        this.cityId = cityId;
    }

    @Column(name = "city_nm")
    public String getCityName() {
        return cityName;
    }
    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    @Column(name = "regi_id")
    public String getRegiId() {
        return regiId;
    }
    public void setRegiId(String regiId) {
        this.regiId = regiId;
    }

    @Column(name = "regi_nm")
    public String getRegiName() {
        return regiName;
    }
    public void setRegiName(String regiName) {
        this.regiName = regiName;
    }

    @Column(name = "cre_date")
    public Timestamp getCreatDate() {
        return creatDate;
    }
    public void setCreatDate(Timestamp creatDate) {
        this.creatDate = creatDate;
    }

    @Column(name = "last_upd_date")
    public Timestamp getLastUpdDate() {
        return lastUpdDate;
    }
    public void setLastUpdDate(Timestamp lastUpdDate) {
        this.lastUpdDate = lastUpdDate;
    }

    @Id
    @Column(name = "ogg_key_id", unique = true, nullable = false)
    @GeneratedValue(generator = "systemUUID")
    @GenericGenerator(name = "systemUUID", strategy = "uuid")
    public String getOggKeyId() {
        return oggKeyId;
    }
    public void setOggKeyId(String oggKeyId) {
        this.oggKeyId = oggKeyId;
    }
}

二、单一主键映射和主键的生成策略 

当数据表中只存在单一主键(大多数情况下都是单一主键),主键标识着一条记录,不可重复和为空,标志位唯一。但是此主键不需要手动输入,而在Hibernate下包含有主键的生成策略。例如第一点的示例中:

    @Id
    @Column(name = "ogg_key_id", unique = true, nullable = false)
    @GeneratedValue(generator = "systemUUID")
    @GenericGenerator(name = "systemUUID", strategy = "uuid")
    public String getOggKeyId() {
        return oggKeyId;
    }
    public void setOggKeyId(String oggKeyId) {
        this.oggKeyId = oggKeyId;
    }

此时,只需要在相应的setter的方法上,设置主键的生成策略(本例中为UUID)Hibernate即可自动生成唯一性标识,而省去了手动输入的麻烦。使用Hibernate映射主键总结几点:

1、为了保证对象标识符的唯一性与不可变性,应该让Hibernate来为主键赋值,而不是程序。

2、Hibernate中唯一一种最简单通用的主键生成器就是:UUID。虽然是个32位难读的长字符串,但是它没有跨数据库的问题,将来切换数据库极其简单方便,推荐使用。

3、Hibernate下的UUID生成和Java下的UUID生成有所不同,Hibernate下是32位字长的16进制数,而Java下的则是36位字长。

4、其他主键的生成策略:assigned、increment、hilo、seqhilo、sequence、identity、native、guid、foreign、select。详解参考:http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html

三、复合主键的表映射 (出现情况不多,不推荐使用复合主键)

复合主键的情况是数据表存在多个主键,在实现与类映射时,情况比单一主键更加复杂。通常情况都会想法设法修改表结构成为单一主键,绕开复合主键,所以不推荐使用。但最近在做项目的时候,遇到表结构是复合主键,也无法绕开的情况,所以按此思路开始。这里我使用的是将主键属性封装在一个类当中,其中要注意的几点:

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方法,只与主键属性有关,普通属性不要影响这两个方法进行判断。这个原因很简单,主键才能决定一条记录,其他属性不能决定一条记录。

4.主键类必须有默认的public无参数的构造方法。

实现复合主键映射的三种方式:

1、@Embeddable + @Id + @Embedded(@Embeddable 表示这个类可以嵌入到别的类中去,常以表示其他类的某个属性。)

2、@Embeddable + @EmbeddedId( @Embedded 它和 @Embeddable 正好相反,它用来表示某个属性是被嵌入进来的。)

3、@IdClass + @Id(@EmbeddedId = @Embedded + @Id)

以下贴出第一种方式的代码:

主键类ModelKey:

package com.pec.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class ModelKey implements Serializable{

    private static final long serialVersionUID = 8099372586856509841L;

    // 接口类型
    private String intType;
    // 条目识别码
    private String recordId;
    //
    private String createTimeStamp;

    public String getIntType() {
        return intType;
    }
    public void setIntType(String intType) {
        this.intType = intType;
    }
    public String getRecordId() {
        return recordId;
    }
    public void setRecordId(String recordId) {
        this.recordId = recordId;
    }
    public String getCreateTimeStamp() {
        return createTimeStamp;
    }
    public void setCreateTimeStamp(String createTimeStamp) {
        this.createTimeStamp = createTimeStamp;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((createTimeStamp == null) ? 0 : createTimeStamp.hashCode());
        result = prime * result + ((intType == null) ? 0 : intType.hashCode());
        result = prime * result
                + ((recordId == null) ? 0 : recordId.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;
        ModelKey other = (ModelKey) obj;
        if (createTimeStamp == null) {
            if (other.createTimeStamp != null)
                return false;
        } else if (!createTimeStamp.equals(other.createTimeStamp))
            return false;
        if (intType == null) {
            if (other.intType != null)
                return false;
        } else if (!intType.equals(other.intType))
            return false;
        if (recordId == null) {
            if (other.recordId != null)
                return false;
        } else if (!recordId.equals(other.recordId))
            return false;
        return true;
    }

    public ModelKey(String intType, String recordId, String createTimeStamp) {
        this.intType = intType;
        this.recordId = recordId;
        this.createTimeStamp = createTimeStamp;
    }
    public ModelKey() {
    }
}

实现类InterFaceDataModel:

package com.pec.model;

import java.io.Serializable;
import java.sql.Timestamp;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;

import com.sun.tracing.dtrace.Attributes;

@Entity
@Table(name = "interface_admin.interface_data_test")
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
//@IdClass(ModelKey.class)
public class InterFaceDataModel implements Serializable{

    private static final long serialVersionUID = 8586209694356988171L;

    private ModelKey modelKey ;
    private String seniorRecordId ;
    private Timestamp daleteTime ;
    private String createUser ;
    private String oprStatus ;
    private String oprUser ;
    private String oprTimeStamp ;
    private String yyyymmdd ;
    private String selKey1 ;
    private String selKey2 ;
    private String selKey3 ;
    private String selKey4 ;
    private String valList ;    

    @Id
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="intType", column = @Column(name="int_type")),
        @AttributeOverride(name="recordId", column = @Column(name="record_id")),
        @AttributeOverride(name="createTimeStamp", column = @Column(name="create_timestamp"))
    })
    public ModelKey getModelKey() {
        return modelKey;
    }

    public void setModelKey(ModelKey modelKey) {
        this.modelKey = modelKey;
    }

    @Column(name = "senior_record_id")
    public String getSeniorRecordId() {
        return seniorRecordId;
    }

    public void setSeniorRecordId(String seniorRecordId) {
        this.seniorRecordId = seniorRecordId;
    }

    @Column(name = "delete_time")
    public Timestamp getDaleteTime() {
        return daleteTime;
    }

    public void setDaleteTime(Timestamp daleteTime) {
        this.daleteTime = daleteTime;
    }

    @Column(name = "create_user")
    public String getCreateUser() {
        return createUser;
    }

    public void setCreateUser(String createUser) {
        this.createUser = createUser;
    }

    @Column(name = "opr_status")
    public String getOprStatus() {
        return oprStatus;
    }

    public void setOprStatus(String oprStatus) {
        this.oprStatus = oprStatus;
    }

    @Column(name = "opr_user")
    public String getOprUser() {
        return oprUser;
    }

    public void setOprUser(String oprUser) {
        this.oprUser = oprUser;
    }

    @Column(name = "opr_timestamp")
    public String getOprTimeStamp() {
        return oprTimeStamp;
    }

    public void setOprTimeStamp(String oprTimeStamp) {
        this.oprTimeStamp = oprTimeStamp;
    }

    @Column(name = "yyyymmdd")
    public String getYyyymmdd() {
        return yyyymmdd;
    }

    public void setYyyymmdd(String yyyymmdd) {
        this.yyyymmdd = yyyymmdd;
    }

    @Column(name = "sel_key1")
    public String getSelKey1() {
        return selKey1;
    }

    public void setSelKey1(String selKey1) {
        this.selKey1 = selKey1;
    }

    @Column(name = "sel_key2")
    public String getSelKey2() {
        return selKey2;
    }

    public void setSelKey2(String selKey2) {
        this.selKey2 = selKey2;
    }

    @Column(name = "sel_key3")
    public String getSelKey3() {
        return selKey3;
    }

    public void setSelKey3(String selKey3) {
        this.selKey3 = selKey3;
    }

    @Column(name = "sel_key4")
    public String getSelKey4() {
        return selKey4;
    }

    public void setSelKey4(String selKey4) {
        this.selKey4 = selKey4;
    }

    @Column(name = "val_list")
    public String getValList() {
        return valList;
    }

    public void setValList(String valList) {
        this.valList = valList;
    }

}

具体参考链接:

http://blog.csdn.net/handsomelinux/article/details/50575877

http://www.cnblogs.com/otomedaybreak/archive/2012/01/25/2329390.html

时间: 2024-08-06 15:57:39

Hibernate 表映射 主键生成策略与复合主键的相关文章

从实例看hibernate的主键生成策略

学习了hibernate会发现,hibernate中有实体类,实体类的映射文件,但是我们怎么样才能知道实体类的主键是怎样的生成方式呢?hibernate提供的主键生成策略帮我们完美地解答了这个疑问.下面让我们一起从实例开始认识hibernate的实体生成策略. 一.首先通过User实体类和映射文件的实例 ?User的实体类 package com.bjpowernode.hibernate; import java.util.Set; public class User { private in

Hibernate @TableGenrator表管理主键生成策略

@TableGenerator 是在数据库生成一张表来管理主键生成策略 import javax.persistence.TableGenerator; @TableGenerator( name = "Teacher_GEN",  // TableGenerator's name table = "GENERATOR_TABLE",  // 表名 pkColumnName = "pk_key",  // 列1,varchar 类型,存储生成ID

Hibernate(4)——主键生成策略、CRUD 基础API区别的总结 和 注解的使用

俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: hibernate的主键生成策略 UUID 配置的补充:hbm2ddl.auto属性用法 注解还是配置文件 hibernate注解的基本用法 使用Session API CRUD操作对象,以及对象状态的转换 hibernate缓存的概念 get()/load()的区别到底是什么,源码分析 代理模式实现的懒加载 saveOrUpdate()/merge()的区别 Assigned(常用,一般情况使用很方便):

初学Hibernate主键生成策略

具有业务含义的主键叫自然主键:随机生成,不具备业务含义的字段作为主键,叫代理主键. 在表与POJO类关系映射文件XXX.hbm.xml中,可通过配置id元素下generator节点的class属性指定数据表主键生成策略<generator class="生成策略"></generator>:所谓主键生成策略就是hibernate怎样管理表的主键 主键生成策略:1~4自动增长(1.2.3······),代理主键:5主键为字符串,代理主键:6一般用于自然主键,需要在

Hibernate主键生成策略总结(转)

Hibernate提供的主键生成策略,使我们可以在实体类的映射xml文件中设定关键字来告诉hibernate我们要使用的主键生成方式,然后hibernate会根据设定完成数据库的主键控制. 一.首先通过举例子来了解实体映射文件(*.hbm.xml)中对id生成策略配置格式 用户User的实体类User.java [java] view plaincopy package com.bjpowernode.hibernate; import java.util.Date; public class 

hibernate id主键生成策略

数据库的设计和操作中,我们通常会给表建立主键. 主键,可以分为自然主键和代理主键. 自然主键表示:采用具有业务逻辑含义的字段作为表的主键.比如在用户信息表中,采用用户的身份证号码作为主键.但是这样一来,随着业务逻辑的变化,主键就有可能要更改.比如,假设哪天身份证号码升级成19,2位,那....... 代理主键:在表中人为的增加一个字段,该字段并没有表示任何的业务逻辑,仅仅用来标识一行数据.比如说在用户信息表中,增加一个用户ID的字段.用来表示该条用户信息的记录. 通常情况下,用的比较多的是代理主

(转) Hibernate持久化类与主键生成策略

http://blog.csdn.net/yerenyuan_pku/article/details/65462930 Hibernate持久化类 什么是持久化类呢?在Hibernate中持久化类的英文名称是Persistent Object(简称PO),PO=POJO+hbm映射配置文件. 对于Hibernate中的PO,有如下编写规则: 必须提供一个无参数的public构造方法. 所有属性要用private修饰,对外提供public的get/set方法. 在PO类必须提供一个标识属性,让它与

IT忍者神龟之Hibernate联合主键下,主键生成策略

如果数据库中用多个字段而不仅仅是一个字段作为主键,也就是联合主键,这个时候就可以使用hibernate提供的联合主键生成策略. 具体如下: 可以使用一个组件作为一个实体类的标识符.你的组件类必须满足以下要求: 它必须实现 java.io.Serializable 接口 它必须重新实现 equals() 和 hashCode() 方法,始终和组合关键字在数据库中的概念保持一致 注意:在 Hibernate3 中,第二个要求并非是 Hibernate 强制必须的.但最好这样做. 不能使用一个 Ide

Hibernate框架的主键生成策略

在Hibernate中,id元素的<generator>子元素用于生成持久化类的对象的唯一标识符,也就是主键.Hibernate框架中定义了许多主键生成策略类,也叫生成器类.所有的生成器类都实现了org.hibernate.id.IdentifierGenerator接口.通过实现IdentifierGenerator接口来创建自己的生成器类.Hibernate框架提供了许多内置的生成器类: assigned increment sequence hilo native identity se