第二章 对象关系数据库映射基础
Generator主键生成器
increment
用于为long,short或者int类型生成唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。在集群下不要使用。
identity
对DB2,MySQL,MSSQLServer,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进制数字的字符串。
guid
在MSSQLServer和MySQL中使用数据库生成的GUID字符串。
native
根据底层数据库的能力选择identity,sequence或者hilo中的一个。
assigned
让应用程序在save()之前为对象分配一个标示符。这是<generator>元素没有指定时的默认生成策略。
select
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
foreign
使用另外一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。
sequence-identity
一种特别的序列生成策略,使用数据库序列来生成实际值,但将它和JDBC3的getGeneratedKeys结合在一起,使得在插入语句执行的时候就返回生成的值。目前为止只有面向JDK1.4的Oracle10g驱动支持这一策略。注意,因为Oracle驱动程序的一个bug,这些插入语句的注释被关闭了。
我们需要掌握的主键生成器
uuid
用一个128-bit的UUID算法生成字符串类型的标识符,这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串。UUID包含:IP地址,JVM的启动时间(精确到1/4秒),系统时间和一个计数器值(在JVM中唯一)。在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了。
native
根据底层数据库的能力选择identity,sequence或者hilo中的一个。如果数据库对应的字段是自增型的,可以用此主键策略.
assigned
让应用程序在save()之前为对象分配一个标示符。这是<generator>元素没有指定时的默认生成策略。
需要注意的地方:
<!--是否自动创建对应的数据库表-->
<propertyname="hbm2ddl.auto">create</property>
这个开关,我们现在暂时最好不要用,因为每次程序启动,会先执行droptable语句.会将先前的数据删除掉.
下面我们来看这几种主键生成器的用法
CREATETABLE`users`(
`userId`intNOTNULLauto_increment,
`userName`varchar(255)defaultNULL,
`userPwd`varchar(255)defaultNULL,
PRIMARYKEY(`userId`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;
在MySQL中建立此表,注意userId在这里是int型,并自增.
编写User.hbm.xml,hibernate.cfg.xml两个配置文件,配置文件中这里变动一下:
<?xmlversion="1.0"?>
<!DOCTYPEhibernate-mappingPUBLIC
"-//Hibernate/HibernateMappingDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="chapter1.model.User"table="Users">
<idname="userId"type="java.lang.Integer"column="userId">
<generatorclass="native"/>
</id>
<propertyname="userName"type="java.lang.String"column="userName"/>
<propertyname="userPwd"type="java.lang.String"column="userPwd"/>
</class>
</hibernate-mapping>
注意,因为type这里我们用到了Integer,所以我们在Model类中也应该用Integer,其实用int也可以,因为Java有自动的装箱拆箱操作.
packagechapter1.model;
publicclassUser{
privateIntegeruserId;
privateStringuserName;
privateStringuserPwd;
publicUser(){
super();
}
publicUser(StringuserName,StringuserPwd){
super();
this.userName=userName;
this.userPwd=userPwd;
}
publicIntegergetUserId(){
returnuserId;
}
publicvoidsetUserId(IntegeruserId){
this.userId=userId;
}
publicStringgetUserName(){
returnuserName;
}
publicvoidsetUserName(StringuserName){
this.userName=userName;
}
publicStringgetUserPwd(){
returnuserPwd;
}
publicvoidsetUserPwd(StringuserPwd){
this.userPwd=userPwd;
}
}
Dao层我们不动:
packagechapter1.dao;
importorg.hibernate.Session;
importchapter1.model.User;
importcommons.util.HibernateUtil;
publicclassUserDao{
publicvoidcreate(Useruser){
Sessionsession=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}
publicstaticvoidmain(String[]args){
UserDaouserDao=newUserDao();
Useruser=newUser("zhanghaidang2","791126");
userDao.create(user);
}
}
可以看到主键按自增方式增长,符合我们平时的习惯.
但是从现在开始,我建议大家使用uuid.hex方式生成主键.
Hibernate的Session中几个常用的方法
save:保存对象
update:更新对象
delete:删除对象
get:获取单个对象
createQuery:获取对象的集合
saveOrUpdate:根据ID的值是否为空,自动调用save或update方法来更新对象.
注意的地方:Hibernate中事务的使用规则,save,update,delete这些操作涉及到数据库中数据的更改,一定要用事务进行提交,get,createQuery用于查询对象,可以不用事务.
下面我们来看一下对单张表的增删改查的操作.
首先在MySQL中建一个student表
CREATETABLE`students`(
`id`varchar(32)NOTNULL,
`name`varchar(32)defaultNULL,
`age`int(11)defaultNULL,
`birthday`datetimedefaultNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8;
增
publicclassStudentDao{
publicvoidinsertStudent(Studentstudent){
Sessionsession=HibernateUtil.getSessionfactory().getCurrentSession();
try{
session.beginTransaction();
session.save(student);
session.getTransaction().commit();
}catch(Exceptione){
session.getTransaction().rollback();
}
}
publicstaticvoidmain(String[]args)throwsParseException{
StudentDaosd=newStudentDao();
//方式一:
SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");
Datedate=sdf.parse("1988-10-22");
Studentstudent1=newStudent("张三",22,newjava.sql.Date(date
.getTime()));
sd.insertStudent(student1);
//方式二:
Calendarcalendar=Calendar.getInstance();
calendar.set(Calendar.YEAR,1988);
calendar.set(Calendar.MONTH,0);
calendar.set(Calendar.DAY_OF_MONTH,21);
Studentstudent2=newStudent("李四",22,newjava.sql.Date(calendar
.getTimeInMillis()));
sd.insertStudent(student2);
}
}