hibernate之主键生成策略
Posted aluoka
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate之主键生成策略相关的知识,希望对你有一定的参考价值。
一、主键类型
1.自然主键(主键本身就是表中的一个字段,实体中一个具体的属性)
表中已经具有某字段,并且该字段具有业务含义作为主键,称之为自然主键。
例如:在person表中的身份证号,既是唯一的,又可以单独标识一个person
2.代理主键(主键不是实体中某个具体的属性,而是一个不相关的字段)
表中原本不存在的字段,且不具备业务含义的字段作为主键,称之为代理主键。更合理的方式是使用代理主键。
二、主键生成策略
主键生成策略,就是每条记录录入时,主键的生成规则。Hibernate中,提供了几个内置的主键生成策略,其常用主键生成策略的名称和描述如下
1.代理主键
identity(主键自增)
适用于long、short或int类型主键,采用底层数据库本身提供的主键生成标识符。在DB2、mysql、MS SQL Server、Sybase和HypersonicSQL数据库中可以使用该生成器,该生成器要求在数据库中把主键定义成为自增类型。Oracle没有自动增长
sequence(序列)
适用于long、short或int类型主键,Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence,MySQL这种不支持sequence
increment(主键自增,单线程,maxID+1)
适用于long、short或int类型主键,由Hibernate提供自动递增的方式生成唯一标识符,每次增量为1。只有当没有其他进程向同一张表中插入数据时才可以使用,不能再多线程环境下使用
hilo(主键自增,高低位算法)
hilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一
native(hilo+identity+sequence三选一)
根据底层数据库对自动生成标识符的能力来选择i dentity、sequence、hilo三种生成器中的一种,适合跨数据库平台开发
uuid(随机字符串作主键)
Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,其UUID被编码为一个长度为32位的十六进制字符串。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字
uuid长度大,占用空间大,跨数据库,不用访问数据库就生成主键值,所以效率高且能保证唯一性,移植非常方便,推荐使用。
guid(全球唯一标识符)
全球唯一标识符,也称作 UUID,是一个128位长的数字,用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。
Hibernate在维护主键时,先查询数据库,获得一个uuid字符串,该字符串就是主键值,该值唯一,缺点长度较大,支持数据库有限,优点同uuid,跨数据库,但是仍然需要访问数据库。注意:长度因数据库不同而不同。
需要数据库支持查询uuid,生成时需要查询数据库,效率没有uuid高,推荐使用uuid。
2.自然主键
assigned(用户手动录入)
由Java程序负责生成标识符,Hibernate不管理主键,用户手动设置主键的值。如果不指定id元素的generator属性,则默认使用该主键生成策略。
内容:
1 assigned
数据类型不限、保存前必须赋值
2 identity
数字,无需赋值
3 sequence
数字,无需赋值, 默认使hibernate_sequence这个序列,
也可以通过sequence/sequence_name参数赋值
4 increment
数字,无需赋值
5 uuid/uuid.hex (是由容器自动生成的一个32位的字符串,.hex代表的是十六进制)
32位的字符串,无需赋值,
6 native
等于identity+sequence
导入SessionFactoryUtils类
1 public class SessionFactoryUtils 2 private static SessionFactory sessionFactory; 3 // 存放当前会话 4 private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); 5 static 6 Configuration cfg = new Configuration(); 7 Configuration configure = cfg.configure("/hibernate.cfg.xml"); 8 sessionFactory = configure.buildSessionFactory(); 9 10 11 public static Session openSession() 12 Session session = threadLocal.get(); 13 if (null == session) 14 session = sessionFactory.openSession(); 15 threadLocal.set(session); 16 17 return session; 18 19 20 public static void closeSession() 21 Session session = threadLocal.get(); 22 if (null != session) 23 if (session.isOpen()) 24 session.close(); 25 26 threadLocal.set(null); 27 28 29 30 public static void main(String[] args) 31 Session session = openSession(); 32 System.out.println(session.isConnected()); 33 closeSession(); 34 35 36
这个类在学习hibernate的过程中所用(整合SSH框架之前用)
作用:可以用来检测所写的映射文件是否正确;
然后创建好实体类和实体映射文件
学生类:
1 public class Student implements Serializable 2 3 private Integer sid; 4 private String sname; 5 public Integer getSid() 6 return sid; 7 8 public void setSid(Integer sid) 9 this.sid = sid; 10 11 public String getSname() 12 return sname; 13 14 public void setSname(String sname) 15 this.sname = sname; 16 17 @Override 18 public String toString() 19 return "Worker [sid=" + sid + ", sname=" + sname + "]"; 20 21
工人类:
1 public class Worker implements Serializable 2 private String wid; 3 private String wname; 4 public String getWid() 5 return wid; 6 7 public void setWid(String wid) 8 this.wid = wid; 9 10 public String getWname() 11 return wname; 12 13 public void setWname(String wname) 14 this.wname = wname; 15 16 @Override 17 public String toString() 18 return "Worker [wid=" + wid + ", wname=" + wname + "]"; 19 20 21 22 23
两个实体映射文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="two.entity.Student" table="t_hibernate_student"> 7 <id name="sid" type="java.lang.Integer" column="sid"> 8 <!-- <generator class="assigned" />--> 9 <!-- <generator class="identity" /> --> 10 <generator class="increment" /> 11 <!-- <generator class="sequence" /> --> 12 <!-- <generator class="sequence" > <param name="sequence_name">aaa</param> 13 </generator> --> 14 <!-- <generator class="com.javaxl.two.id.Myts" /> --> 15 </id> 16 <property name="sname" type="java.lang.String" column="sname"> 17 </property> 18 </class> 19 </hibernate-mapping>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="two.entity.Worker" table="t_hibernate_work"> 7 <id name="wid" type="java.lang.String" column="wid"> 8 <!-- <generator class="uuid" /> --> 9 <!-- <generator class="sequence" /> --> 10 <!-- <generator class="sequence" > <param name="sequence_name">aaa</param> 11 </generator> --> 12 <generator class="two.id.Myts" /> 13 </id> 14 15 <property name="wname" type="java.lang.String" column="wname"> 16 </property> 17 </class> 18 </hibernate-mapping>
dao方法
1 public class DemoDao 2 /** 3 * 添加学生 4 * @param stu 5 * @return 6 */ 7 public Serializable addStudent(Student stu) 8 Session session=SessionFactoryUtils.openSession(); 9 Transaction transaction=session.beginTransaction(); 10 Serializable saveId=session.save(stu); 11 transaction.commit(); 12 session.close(); 13 return saveId; 14 15 /** 16 * 添加工人 17 * @param worker 18 * @return 19 */ 20 public Serializable addWork(Worker worker) 21 Session session=SessionFactoryUtils.openSession(); 22 Transaction transaction=session.beginTransaction(); 23 Serializable saveId=session.save(worker); 24 transaction.commit(); 25 session.close(); 26 return saveId; 27 28 29 30 31 // public static void teststudent(String[] args) 32 // 33 // DemoDao dao=new DemoDao(); 34 // Student stu=new Student(); 35 //// stu.setSid(4); 36 // stu.setSname("张三"); 37 // dao.addStudent(stu); 38 // System.out.println(dao.addStudent(stu)); 39 // 40 public static void main(String[] args) 41 DemoDao dao=new DemoDao(); 42 Worker worker=new Worker(); 43 worker.setWname("啊哈哈哈"); 44 System.out.println(dao.addWork(worker)); 45 46 47 48
各位大佬们可以一一去试
最后一个自定义主键生成器
需要创建一个类来设置你需要变成的id格式
如下:
public class Myts implements IdentifierGenerator @Override public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException // TODO Auto-generated method stub SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return "shop_book_"+sdf.format(new Date());
在dao方法类运行:
显示如下:
以上是关于hibernate之主键生成策略的主要内容,如果未能解决你的问题,请参考以下文章