Hibernate之主键生成策略
Posted psyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate之主键生成策略相关的知识,希望对你有一定的参考价值。
hibernate的主键生成器:
generator元素:表示了一个主键生成器,它用来为持久化类实例生成唯一的标识 。
1 程序员自己控制:assigned
2 数据库控制: identity(标识列/自动增长) sequence
3 hibernate控制:increment uuid/uuid.hex
4 其它:native
assigned:
主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。
<id name="sid" type="java.lang.Integer" column="sid">
<generator class="assigned" />
</id>
特点:可以跨数据库,人为控制主键生成。
increment:
由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。
<id name="sid" type="java.lang.Integer" column="sid">
<generator class="increment" />
</id>
Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
identity:
identity由底层数据库生成标识符。identity是由数据库自己生成的,但这个主键必须设置为自增长,使用identity的前提条件是底层数据库支持自动增长字段类型
<id name="id" column="id">
<generator class="identity" />
例:如果使用mysql数据库,则主键字段必须设置成auto_increment。
id int(11) primary key auto_increment
特点:只能用在支持自动增长的字段数据库中使用,如MySQL。
sequence:
采用数据库提供的sequence机制生成主键,需要数据库支持sequence。
<generator class="sequence" >
<param name="sequence_name">aaa</param>
</generator> -->
Hibernate生成主键时,查找sequence并赋给主键值,主键值由数据库生成,Hibernate不负责维护,使用时必须先创建一个sequence,如果不指定sequence名称,则使用Hibernate默认的sequence,名称为hibernate_sequence,前提要在数据库中创建该sequence。
特点:只能在支持序列的数据库中使用。
案例演示:
1.在数据库中建好测试的表(这里用的MYSQL)
表的实体类:
package com.psy.two.entity; import java.io.Serializable; public class Student implements Serializable private Integer sid; private String sname; public Integer getSid() return sid; public void setSid(Integer sid) this.sid = sid; public String getSname() return sname; public void setSname(String sname) this.sname = sname; public Student(Integer sid, String sname) super(); this.sid = sid; this.sname = sname; public Student() super(); // TODO Auto-generated constructor stub @Override public String toString() return "Student [sid=" + sid + ", sname=" + sname + "]";
package com.psy.two.entity; public class Worker private String wid; private String wname; public String getWid() return wid; public void setWid(String wid) this.wid = wid; public String getWname() return wname; public void setWname(String wname) this.wname = wname; public Worker(String wid, String wname) super(); this.wid = wid; this.wname = wname; public Worker() super(); // TODO Auto-generated constructor stub @Override public String toString() return "Worker [wid=" + wid + ", wname=" + wname + "]";
实体映射文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.psy.two.entity.Student" table="t_hibernate_student"> <id name="sid" type="java.lang.Integer" column="sid"> <generator class="assigned" /><!-- 由程序员控制 --> <!-- <generator class="increment" /> --><!-- hibernate控制--> <!-- <generator class="sequence" /> --> <!-- 由数据库控制--> <!-- <generator class="identity" > <param name="sequence_name">aaa</param> </generator> --> <!-- <generator class="com.javaxl.two.id.Myts" /> --> </id> <property name="sname" type="java.lang.String" column="sname"> </property> </class> </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.psy.two.entity.Worker" table="t_hibernate_worker"> <id name="wid" type="java.lang.String" column="wid"> <!-- <generator class="assigned" /> --> <!-- <generator class="uuid" /> --> <!-- <generator class="sequence" > <param name="sequence_name">aaa</param> </generator> --> <generator class="com.psy.two.id.Myts" /> </id> <property name="wname" type="java.lang.String" column="wname"> </property> </class> </hibernate-mapping>
SessionFactoryUtils工具类(用来检测所写映射文件是否正确)
package com.psy.two.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * * * * 作用: * 可以用来检测所写的映射文件是否正确 * @author Admin * */ public class SessionFactoryUtils private static SessionFactory sessionFactory; // 存放当前会话 private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); static Configuration cfg = new Configuration(); Configuration configure = cfg.configure("/hibernate.cfg.xml"); sessionFactory = configure.buildSessionFactory(); public static Session openSession() Session session = threadLocal.get(); if (null == session) session = sessionFactory.openSession(); threadLocal.set(session); return session; public static void closeSession() Session session = threadLocal.get(); if (null != session) if (session.isOpen()) session.close(); threadLocal.set(null); public static void main(String[] args) Session session = openSession(); System.out.println(session.isConnected()); closeSession();
主配置文件hibernate.cfg.xml
<!-- 讲解主键生成策略 --> <mapping resource="com/psy/two/entity/Worker.hbm.xml" /> <mapping resource="com/psy/two/entity/Student.hbm.xml" />
测试类:
package com.psy.two.dao; import java.io.Serializable; import org.hibernate.Session; import org.hibernate.Transaction; import com.psy.two.entity.Student; import com.psy.two.entity.Worker; import com.psy.two.util.SessionFactoryUtils; public class DemoDao /** * |添加学生 * @param stu * @return */ public Serializable addStudent(Student stu) Session session = SessionFactoryUtils.openSession(); Transaction transaction = session.beginTransaction(); Serializable saveId = session.save(stu); transaction.commit(); session.close(); return saveId; /** * 添加工人 * @param worker * @return */ public Serializable addWorker(Worker worker) Session session = SessionFactoryUtils.openSession(); Transaction transaction = session.beginTransaction(); Serializable saveId = session.save(worker); transaction.commit(); session.close(); return saveId; public static void testStudent(String[] args) DemoDao dao=new DemoDao(); Student stu =new Student(); stu.setSid(22); stu.setSname("辣鸡"); System.out.println(dao.addStudent(stu)); public static void main(String[] args) DemoDao dao=new DemoDao(); Worker worker=new Worker(); worker.setWname("enh"); System.out.println(dao.addWorker(worker));
以上是关于Hibernate之主键生成策略的主要内容,如果未能解决你的问题,请参考以下文章