一、 Xml方式

<id>标签必须配置在<class>标签内第一个位置。由一个字段构成主键,如果是复杂主键<composite-id>标签

被映射的类必须定义对应数据库表主键字段。大多数类有一个JavaBeans风格的属性, 为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。

<id

name="propertyName"                                          (1)

type="typename"                                              (2)

column="column_name"                                         (3)

unsaved-value="null|any|none|undefined|id_value"             (4)

access="field|property|ClassName"                            (5)

node="element-name|@attribute-name|element/@attribute|.">

<generatorclass="generatorClass"/>

</id>

(1) name (可选): 标识属性的名字(实体类的属性)。

(2) type (可选): 标识Hibernate类型的名字(省略则使用hibernate默认类型),也可以自己配置其它hbernate类型(integer, long, short, float,double, character, byte, boolean, yes_no, true_false)

(2) length(可选):当type为varchar时,设置字段长度

(3) column (可选 - 默认为属性名): 主键字段的名字(省略则取name为字段名)。

(4) unsaved-value (可选 - 默认为一个切合实际(sensible)的值): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。 这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注) 但未再次持久化的实例区分开来。

(5) access (可选 - 默认为property): Hibernate用来访问属性值的策略。

如果 name属性不存在,会认为这个类没有标识属性。

unsaved-value 属性在Hibernate3中几乎不再需要。

还有一个另外的<composite-id>定义可以访问旧式的多主键数据。 我们强烈不建议使用这种方式。

<generator>元素(主键生成策略)

主键生成策略是必须配置

用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数, 用<param>元素来传递。

<id name="id"type="long" column="cat_id">

<generator class="org.hibernate.id.TableHiLoGenerator">

<param name="table">uid_table</param>

<param name="column">next_hi_value_column</param>

</generator>

</id>

所有的生成器都实现org.hibernate.id.IdentifierGenerator接口。 这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然, Hibernate提供了很多内置的实现。下面是一些内置生成器的快捷名字:

increment

用于为long, short或者int类型生成 唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。

identity

对DB2,MySQL, MS SQL Server,Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。 (数据库自增)

sequence

在DB2,PostgreSQL, Oracle, SAPDB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。(数据库自增)

hilo

使用一个高/低位算法高效的生成long, short 或者 int类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key和next_hi)作为高位值的来源。 高/低位算法生成的标识符只在一个特定的数据库中是唯一的。

seqhilo

使用一个高/低位算法来高效的生成long, short 或者 int类型的标识符,给定一个数据库序列(sequence)的名字。

uuid

用一个128-bit的UUID算法生成字符串类型的标识符, 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串,它的生成是由hibernate生成,一般不会重复。

UUID包含:IP地址,JVM的启动时间(精确到1/4秒),系统时间和一个计数器值(在JVM中唯一)。 在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了

guid

在MS SQL Server 和 MySQL 中使用数据库生成的GUID字符串。

native

根据底层数据库的能力选择identity,sequence 或者hilo中的一个。(数据库自增)

assigned

让应用程序在save()之前为对象分配一个标示符。这是 <generator>元素没有指定时的默认生成策略。(如果是手动分配,则需要设置此配置)

select

通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。

foreign

使用另外一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。

二、 annotateon方式

使用@GeneratedValue(strategy=GenerationType)注解可以定义该标识符的生成策略

Strategy有四个值:

①     、AUTO- 可以是identity column类型,或者sequence类型或者table类型,取决于不同的底层数据库.

相当于native

②     、TABLE- 使用表保存id值

③     、IDENTITY- identity column

④     、SEQUENCE- sequence

注意:auto是默认值,也就是说没有后的参数则表示为auto

1、AUTO默认

@Id

@GeneratedValue

public int getId() {

return id;

}

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

public int getId() {

return id;

}

1、  对于mysql,使用auto_increment

2、  对于oracle使用hibernate_sequence(名称固定)

2、IDENTITY

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

public int getId() {

return id;

}

对DB2,MySQL, MS SQL Server,Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。 (数据库自增)

注意:此生成策略不支持Oracle

3、SEQUENCE

@Id

@GeneratedValue(strategy=GenerationType.SEQUENCE)

public int getId() {

return id;

}

在DB2,PostgreSQL,Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。(数据库自增)

注意:此生成策略不支持MySQL

4、为Oracle指定定义的Sequence

a)、首先需要在实体类前面申明一个Sequence如下:

方法:@SequenceGenerator(name="SEQ_Name",sequenceName="SEQ_DB_Name")

参数注意:SEQ_Name:表示为申明的这个Sequence指定一个名称,以便使用

SEQ_DB_Name:表示为数据库中的Sequence指定一个名称。

两个参数的名称可以一样。

@Entity

@SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")

public class Teacher {

……

}

b)、然后使用@GeneratedValue注解

方法:@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="SEQ_Name")

参数:strategy:固定为GenerationType.SEQUENCE

Generator:在实体类前面申明的sequnce的名称

@Entity

@SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")

public class Teacher {

private int id;

@Id

@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")

public int getId() {

return id;

}}

5、TABLE - 使用表保存id值

原理:就是在数据库中建立一个表,这个表包含两个字段,一个字段表示名称,另一个字段表示值。每次在添加数据时,使用第一个字段的名称,来取值作为添加数据的ID,然后再给这个值累加一个值再次存入数据库,以便下次取出使用。

Table主键生成策略的定义:

@javax.persistence.TableGenerator(

name="Teacher_GEN",              //生成策略的名称

table="GENERATOR_TABLE",     //在数据库生成表的名称

pkColumnName = "pk_key",     //表中第一个字段的字段名 类型为varchar,key

valueColumnName = "pk_value",    //表中第二个字段的字段名 int ,value

pkColumnValue="teacher",     //这个策略中使用该记录的第一个字段的值(key值)

initialValue = 1,                //这个策略中使用该记录的第二个字段的值(value值)初始化值

allocationSize=1                  //每次使用数据后累加的数值

)

这样执行后,会在数据库建立一个表,语句如下:

create tableGENERATOR_TABLE (pk_key varchar(255),pk_value integer )

结构:

并且表建立好后,就插入了一个记录,如下:

注:这条记录的pk_value值为2,是因为刚刚做例程序时,已经插入一条记录了。初始化时为1。

使用TABLE主键生成策略:

@Entity

@javax.persistence.TableGenerator(

name="Teacher_GEN",              //生成策略的名称

table="GENERATOR_TABLE",     //在数据库生成表的名称

pkColumnName = "pk_key",     //表中第一个字段的字段名 类型为varchar,key

valueColumnName = "pk_value",    //表中第二个字段的字段名 int ,value

pkColumnValue="teacher",     //这个策略中使用该记录的第一个字段的值(key值)

initialValue = 1,                //这个策略中使用该记录的第二个字段的值(value值)初始化值

allocationSize=1                 //每次使用数据后累加的数值

)

public class Teacher {

private int id;

@Id

@GeneratedValue(strategy=GenerationType.TABLE,generator="Teacher_GEN")

public int getId() {

return id;}}

注意:这样每次在添加Teacher记录时,都会先到GENERATOR_TABLE表取pk_key=teacher的记录后,使用pk_value值作为记录的主键。然后再给这个pk_value字段累加1,再存入到GENERATOR_TABLE表中,以便下次使用。

这个表可以给无数的表作为主键表,只是添加一条记录而以(需要保证table、pkColumnName、valueColumnName三个属性值一样就可以了。),这个主键生成策略可以跨数据库平台。

三、 联合主键

复合主键(联合主键):多个字段构成唯一性。

1、xml方式

a) 实例场景:核算期间

// 核算期间

public class FiscalYearPeriod {

private int fiscalYear; //核算年

private int fiscalPeriod; //核算月

private Date beginDate; //开始日期

private Date endDate; //结束日期

private String periodSts; //状态

public int getFiscalYear() {

return fiscalYear;

}

public void setFiscalYear(int fiscalYear) {

this.fiscalYear = fiscalYear;

}

public int getFiscalPeriod(){  return fiscalPeriod;}

public void setFiscalPeriod(int fiscalPeriod) {

this.fiscalPeriod =fiscalPeriod;

}

public DategetBeginDate() {return beginDate;}

public void setBeginDate(DatebeginDate) {  this.beginDate = beginDate; }

public Date getEndDate(){return endDate;}

public void setEndDate(DateendDate) {  this.endDate = endDate; }

public StringgetPeriodSts() {  return periodSts;}

public voidsetPeriodSts(String periodSts) {this.periodSts = periodSts;}

}

复合主键的映射,一般情况把主键相关的属性抽取出来单独放入一个类中。而这个类是有要求的:必需实现序列化接口(java.io.Serializable)(可以保存到磁盘上),为了确定这个复合主键类所对应对象的唯一性就会产生比较,对象比较就需要复写对象的hashCode()、equals()方法(复写方法如下图片),然后在类中引用这个复合主键类

 

 

 

b) 复合主键类:

复合主键必需实现java.io.Serializable接口

public class FiscalYearPeriodPKimplements java.io.Serializable {

private int fiscalYear;//核算年

private int fiscalPeriod;//核算月

public int getFiscalYear() {

return fiscalYear;

}

public void setFiscalYear(int fiscalYear) {

this.fiscalYear = fiscalYear;

}

public int getFiscalPeriod(){

return fiscalPeriod;

}

public void setFiscalPeriod(int fiscalPeriod) {

this.fiscalPeriod =fiscalPeriod;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime* result + fiscalPeriod;

result = prime* result + fiscalYear;

return result;

}

@Override

public boolean equals(Object obj){

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() !=obj.getClass())

return false;

FiscalYearPeriodPKother = (FiscalYearPeriodPK) obj;

if (fiscalPeriod != other.fiscalPeriod)

return false;

if (fiscalYear != other.fiscalYear)

return false;

return true;

}}

c) 实体类:(中引用了复合主键类)

public class FiscalYearPeriod{

private FiscalYearPeriodPK fiscalYearPeriodPK;//引用 复合主键类

private Date beginDate;//开始日期

private Date endDate;//结束日期

private String periodSts;//状态

public FiscalYearPeriodPK getFiscalYearPeriodPK() {

return fiscalYearPeriodPK;

}

public void setFiscalYearPeriodPK(FiscalYearPeriodPKfiscalYearPeriodPK) {

this.fiscalYearPeriodPK = fiscalYearPeriodPK;

}

………………

d) FiscalYearPeriod.hbm.xml映射文件

<hibernate-mapping>

<class name="com.bjsxt.hibernate.FiscalYearPeriod"table="t_fiscal_year_period">

<composite-id name="fiscalYearPeriodPK">

<key-property name="fiscalYear"/>

<key-property name="fiscalPeriod"/>

</composite-id>

<property name="beginDate"/>

<property name="endDate"/>

<property name="periodSts"/>

</class>

</hibernate-mapping>

e) 导出数据库输出SQL语句:

create table t_fiscalYearPeriod (fiscalYear integer not null, fiscalPeriodinteger not null, beginDate datetime, endDate datetime, periodSts varchar(255),primary key (fiscalYear, fiscalPeriod))//实体映射到数据就是两个字段构成复合主键

f) 数据库表结构:

g) 复合主键关联映射数据存储:

session =HibernateUtils.getSession();

tx =session.beginTransaction();

FiscalYearPeriod fiscalYearPeriod = new FiscalYearPeriod();

//构造复合主键

FiscalYearPeriodPK pk = new FiscalYearPeriodPK();

pk.setFiscalYear(2009);

pk.setFiscalPeriod(11);

fiscalYearPeriod.setFiscalYearPeriodPK(pk);//为对象设置复合主键

fiscalYearPeriod.setEndDate(new Date());

fiscalYearPeriod.setBeginDate(new Date());

fiscalYearPeriod.setPeriodSts("Y");

session.save(fiscalYearPeriod);

h) 执行输出SQL语句:

Hibernate: insert into t_fiscalYearPeriod (beginDate, endDate, periodSts,fiscalYear, fiscalPeriod) values (?, ?, ?, ?, ?)

注:如果再存入相同复合主键的记录,就会出错。

i) 数据的加载:

数据加载非常简单,只是主键是一个对象而以,不是一个普通属性。

2、annotation方式

下面是定义组合主键的几种语法:

将组件类注解为@Embeddable,并将组件的属性注解为@Id

将组件的属性注解为@EmbeddedId

将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id

a) 将组件类注解为@Embeddable,并将组件的属性注解为@Id

组件类:

@Embeddable

public class TeacherPK implementsjava.io.Serializable{

private int id;

private String name;

public int getId() {return id;  }

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

public String getName() {   return name;}

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

@Override

public boolean equals(Object o) {       ……}

@Override

public int hashCode() { return this.name.hashCode();    }

}

将组件类的属性注解为@Id,实体类中组件的引用

@Entity

public class Teacher {

private TeacherPK pk;

private String title;

@Id

public TeacherPK getPk(){

return pk;

}}

b)  将组件的属性注解为@EmbeddedId

注意:只需要在实体类中表示复合主键属性前注解为@Entity,表示此主键是一个复合主键

注意了,复合主键类不需要任何的注意。

@Entity

public class Teacher {

private TeacherPK pk;

private String title;

@EmbeddedId

public TeacherPK getPk(){

return pk;

}}

c)  类注解为@IdClass,主键的属性都注解为@Id

需要将复合主键类建立好,不需要进行任何注解

在实体类中不需要进行复合主键类的引用

需要在实体类前面注解为@IdClass,并且指定一个value属性,值为复合主键类的class

需要在实体类中进行复合主键成员属性前面注解为@Id

如下:

@Entity

@IdClass(TeacherPK.class)

public class Teacher {

//private TeacherPK pk;//不再需要

private int id;

private String name;

@Id

public int getId() {return id;  }

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

@Id

public String getName() {return name;}

public void setName(Stringname) {this.name = name;

}}

Hibernate学习笔记(三)Hibernate生成表单ID主键生成策略的更多相关文章

  1. hibernate学习笔记(4)表单操作

    User.hbm.xml的表单配置: ①主键 <id name="id" type="java.lang.Integer"> <column ...

  2. 分库分布的几件小事(四)分库分表的id主键生成

    1.问题 其实这是分库分表之后你必然要面对的一个问题,就是id咋生成?因为要是分成多个表之后,每个表都是从1开始累加,那肯定不对啊,需要一个全局唯一的id来支持.所以这都是你实际生产环境中必须考虑的问 ...

  3. Django学习笔记(五)—— 表单

    疯狂的暑假学习之  Django学习笔记(五)-- 表单 參考:<The Django Book> 第7章 1. HttpRequest对象的信息 request.path         ...

  4. [原创]java WEB学习笔记85:Hibernate学习之路-- -映射 一对一关系 ,基于主键方式实现

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. Flutter学习笔记(13)--表单组件

    如需转载,请注明出处:Flutter学习笔记(13)--表单组件 表单组件是个包含表单元素的区域,表单元素允许用户输入内容,比如:文本区域,下拉表单,单选框.复选框等,常见的应用场景有:登陆.注册.输 ...

  6. ng2 学习笔记(二)表单及表单验证

    在上一篇文章中提到了表单,只说了表单的数据绑定,这一篇文章主要讲一下表单验证,为什么把表单单独拿出来学习,主要是因为,表单是商业应用的支柱,我们用它来执行登录.求助.下单.预订机票.安排会议,以及不计 ...

  7. SQL学习笔记三之MySQL表操作

    阅读目录 一 存储引擎介绍 二 表介绍 三 创建表 四 查看表结构 五 数据类型 六 表完整性约束 七 修改表ALTER TABLE 八 复制表 九 删除表 一 存储引擎介绍 存储引擎即表类型,mys ...

  8. Hibernate的ID主键生成策略

    ID生成策略(一) 通过XML配置实现ID自己主动生成(測试uuid和native) 之前我们讲了除了通过注解的方式来创建一个持久化bean外.也能够在须要持久化的bean的包路径下创建一个与bean ...

  9. 4.ID主键生成策略

    保证唯一性(auto_increment) 一.xml方式 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping P ...

随机推荐

  1. 加密工具类 - CryptoUtils.java

    加密工具类,包含MD5,BASE64,SHA,CRC32的加密与解密方法. 源码如下:(点击下载  - CryptoUtils.java.commons-io-2.4.jar.commons-code ...

  2. angularjs tips

    angular-ui #1 .Impossible to disable fade in modal angularjs ui modal 去掉fade in效果: googleA googleB # ...

  3. 计算机术语install和setup的区别

    作为安装程序的Setup文件是软件的开发者专门为其软件设计的.exe文件,是当前最为盛行的安装程序.在运行该Setup文件进行软件安装时,Setup除了进行复制.改名.解压和目录维护等基本安装工作外, ...

  4. remove duplicates in Postgres(sql去重)

    A frequent question in IRC is how to delete rows that are duplicates over a set of columns, keeping ...

  5. Android Studio AVD和SDK Manager灰色不能点击的问题。

    之前安装完Android Studio之后,迫不及待的打开,新建项目,发现模板新建之后里面没有文件,并且AVD Manager和SDK Manager 那一排的按钮灰色不能点. 之后查阅资料无果,最后 ...

  6. UVa 10420 List of Conquests

    题意就是有N个pl妹子,然后每行第一个单词是妹子的国籍,后面是妹子的名字. 你的任务就是统计相同国籍妹子的个数,然后按字母表顺序输出. 我首先把所有的国籍都读入,然后用qsort()按字母表顺序排序. ...

  7. Intellij IDEA13 创建多模块Maven项目

    目标:构建一个类似于如下图所示的这种结构的Maven项目. 首先,需要选中“File”——>“New Project”如下图所示 选中“Maven”,设置项目名称与项目构建地址,点击“Next” ...

  8. (转载)DataTable使用技巧总结

    在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结.         一.Da ...

  9. Heritrix源码分析(十三) Heritrix的控制中心(大脑)CrawlController(二)

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/650744      本博客已迁移到本人独立博客: http://www.yun5u. ...

  10. Android WebView中那些不得不解决的坑~~

    前面那张hybrid开发心得 有人问 怎么解决不用onJsPrompt 来回调js函数的问题.其实很简单,就是在在你的jscalljava回调函数内 另外开个线程去load js代码即可: wb.po ...