uuid策略生成主键
native自动选择数据库本身的的生成策略(只能在指定的三个策略中选择identity、sequence(序列)。)
assigned 手动分配,就是由用户插入记录时插入id
foregn(外部引用,就是引用其它主键做主键,必须配合ont-to-one使用)
在*.hbm.xml文件的property中如果不指定length那么mysql默认length为255
加上table就是可以更改表别名,如你的类名为User如果不指定table那么数据库中表就是user如果加上table="t_table"那么数据库中表就为t_table
unique="true"//唯一索引
name=""//对应类的属性名
type//指定属性的类型,一般情况不用指定,由hibernat自动匹配
column//字段名称,如果不指定就是属性的名称,如果你的property 跟系统的变量相同那么必须指定一个column名称
=======================================
many2one与one2one叫单端关联,对方的一端是one所以叫单端
=======================================
《many-to-one(多对一关联,也就是主外键关联)》
注意:many-to-one是在多的一端添加一个外键,指向一的主键
把many to one写在多的一端
其实就是在外键的表中(就是多的那端)另外增加了一个字段这个字段就叫做外键。
many为外键one为主键,cascade是级联属性
Group g = new Group();
g.setName("java开发组");
//如果使用了级联删除那么下面的session.save(g);就不用写
//session.save(g);
User u = new User();
for(int i=0,i<5,i++){
u.setName("user"+i);
u.setGroup(g);
}
session.save(u);//如果用了级联保存在这里save的时候就自动save了g对象,所以不用再写上面的session.save(g)否则就要写,如果不写就会出错因为持久化对象不能引用瞬时对象。
=================================
=================================
《one-to-one关联》
重要:
//要让新添加的user与已存在的persion关联,下面就是addUser的DAO方法,要不然你必烦是save一个user 就必须save一个persion
public void addUser(User user,int persionId) {
user.setPersion((Persion)this.getHibernateTemplate().load(Persion.class, persionId));
this.getHibernateTemplate().save(user);
}
注意:one-to-one标签指示hibernate如何加载引用对象,缺省情况下根据主键加载引用对象
一对一关系有两种写法:
1.one-to-one(主键关联)
2.唯一外键方法
one-to-one默认设置了cascade所以不会产生瞬时错误
idCard
//这里必须要加constrained="true"
//one-to-one默认是用主键加载,也就是说引用的是主键的值,
如果要指定引用的是其它字段就要在里加上property-ref="属性名"
//这里是persion的id引用了idCard的id(persion依赖idCard)
但是如果有persion的id就一定有idCard的id因为在保存persion时就会自动存储idCard,所以如果没有idCard就无法保存persion,
这样才能保持两表数据的同步存在,这就是主键的关联
如果persion的映射文件也设置ont-to-one那么就是双向关联,这样也可以通过idCard取得persion的信息
否则就是单向关联就只能 通过persion取得idCard信息
保存数据只能先保存idCard的再保存persion的反过来不行,所以这样关系的维护是由persion维护idcard的
》》one-to-one单向关联配置:
只需在persion写上one-to-one配合foreign生成id策略
idCard
》》one-to-one双向关联配置:(保存都是同样的代码)分两边加载
在单向关联配置基础上还要在idcard的映射文件加上而且还要在idCard类里加上persion属性
many-to-one是多对一关联关系但如果在外键加上唯一约束也就变成了one-to-one关联关系
唯一外键单向关联配置:
这样persion与idCard的对象映射配置就变成了和many-to-one关联关系一样写法
只须在中加上unique="true"变成就可以。
唯一外键双向关联配置:
persion的映射配置和单向关联写法一样,只需要在idCard映射文件中加上而且还要在idCard类里加上persion属性即可。one-to-one默认是用主键加载的这里的property-ref=""就是引用是的你指定的属性名(也就是字段名)
=========================
=========================
《one-to-many》
多对一关联映射:是在多的一端添加一个外键维护多指向一的关联引用
一对多关联映射:是在多的一端添加一个外键维护一指向多的关联引用
也就是说,一对多和多对一的映射策略是一致的,只是站的角度不同
缺点:
* 更新student表中的classesid字段时,需要对每一个student发出一个update的sql,
来更新classesid字段
* 如果将t_student表中的classesis设置为非空,则不能保存student数据,因为关系是由
classes维护的,在保存student时,还没有对应的classesid被生成
》》one-to-many单向关联:
student.hbm.xml是普通的配置
》》one-to-many双向关联:(保存的代码不一样)分两边加载
classes.hbm.xml配置不变student.hbm.xml配置如下:
save代码:
Set students = new HashSet();
for(int i=0;i<5;i++){
Student s = new Student();
s.setName("user"+i);
session.save(s);
students.add(s);
}
Classes classes = new Classes();
classes.setName("电脑班");
classes.setStudents(students);
session.save(classes);
====================================
====================================
key表明要在对方的表中添加一个外键指向一一端
在多一端使用mony-to-one来映射
key对应的字段外键名需要和many-to-one标签定义的字段外键名一致,否则会造成引用丢失。
从一一端来维护一对多双向关联关系,hibernate会发出多于的update语句,所以一般情况下,我们便会从多一端来维护其关联关系
关于inverse属性
-----------hibernate2007-08-02(下午).avi----------------
inverse设置在set集合上,inverse="false"表示可以在一一端维护关系,也可以在多一端维护关系,
如果inverse="true"就只能在多一端维护关系,但是inverse只对插入数据有影响,加载数据没有影响。
inverse被用于one-to-many和many-to-many双向关联
在one-to-many的一方如果不设置inverse=true即默认不设置即为false插入数据代码如下:
session = HibernateUtil.getSesison();
session.beginTransaction();
Set students = new HashSet();
for(int i=0;i<5;i++){
Student s = new Student();
s.setName("user"+i);
session.save(s);
students.add(s);
}
Classes classes = new Classes();
classes.setName("电脑班");
classes.setStudents(students);
session.save(classes);
session.getTransaction().commit();
运行上面代码会发出如下hql语句:
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_classes (name) values (?)
Hibernate: update t_student set classid=? where id=?
Hibernate: update t_student set classid=? where id=?
Hibernate: update t_student set classid=? where id=?
Hibernate: update t_student set classid=? where id=?
Hibernate: update t_student set classid=? where id=?
如果设置inverse=true再运行上面代码
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_classes (name) values (?)
比上面的HQL少了5条update所以student表中的classid字段数据为null,
原因是设置inverse=true后关系由多的一端维护了,也就是说必须用
many-to-one方的插入代码student表中的classid字段数据才能保存,从Student端维护两者之间的关系代码如下:
Classes classes = new Classes();
classes.setName("class_1");
//将classes持久化
session.save(classes);
for (int i = 0; i < 10; i++) {
Student student = new Student();
student.setName("student_" + i);
//建立对象引用关系
student.setClasses(classes);
//将student持久化
session.save(student);
}
运行上面代码会发出如下hql语句:
Hibernate: insert into t_classes (name) values (?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
《many-to-many》
》》many-to-many单向关联
private Set users;//getter/setter属性
Role.hbm.xml:
User.hbm.xml:
一般配置这法
》》many-to-many双向关联
private Set roles;//getter/setter属性
Role.hbm.xml配置不变
User.hbm.xml:
===========================================================================================
===========================================================================================
hibernate2007-08-02(下午).avi
《lazy》延迟加载
lazy可以设置在、集合属性与普通属性,普通属性一般不设置
运行本单元测试的前提条件:
设置标签中的lazy="true",或是保持默认(即不配置lazy属性)
//many-to-one代码测试
//不会发出查询sql
Group group = (Group)session.load(Group.class, 1);
//不会发出查询sql
System.out.println("group id=" + group.getId());
//发出查询sql,加载数据到Group
System.out.println("group name=" + group.getName());
//不会发出查询sql
System.out.println("group name=" + group.getName());
:
load具有延迟加载,在执行load时不会发出sql,只有在get属性时而且是属性没有手工设置了值时才发出sql(如果手工设置了值那么也不会发出查询sql,你取得的值就是你设置的值),而且以后再get属性就不会再发sql了,这就是延迟加载的特性。因为load时就把所有属性load出来了,
但如果把get属性放在关闭session之后执行,就会出错,因为session已关闭无法再load了。这样就要用hibernate提供的open session in view过滤器来保持session一直打开。
----------------------------------------
<设置集合上的lazy=true,即默认设置,就是不用设置>:
//(用的是one-to-many单向关联的代码)
//不会发出查询sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出一条查询sql,加载数据到classes
System.out.println("班级:【" + classes.getName() + "】 拥有的学生:");
//不会发出查询sql
Set students = classes.getStudents();
//会发出一条查询sql,加载数据到Students
for (Iterator iter = students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
------------------------------------------------------------------------
<设置集合上的lazy=false>:
//(用的是one-to-many单向关联的代码)
//不会发出查询sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出两条查询sql,加载数据到classes和Students中
System.out.println("班级:【" + classes.getName() + "】 拥有的学生:");
//不会发出查询sql
Set students = classes.getStudents();
//不会发出查询sql
for (Iterator iter = students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
load不发sql
在get任意一个属性时会把所有关联的数据都查询出来。这就是不用延迟加载的区别
----------------------------------------------------------------------------
<设置集合上的lazy=extra>:
//(用的是one-to-many单向关联的代码)
//不会发出查询sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出一条查询sql,加载数据到classes
System.out.println("班级:【" + classes.getName() + "】 拥有的学生总数:");
//不会发出查询sql
Set students = classes.getStudents();
//会发出一条较为智能的查询sql,如:
//select count(id) from t_student where classid =?
System.out.println(students.size());
//如果接着还要iterator,那么它还会发一条。
//如果先iterator再students.size()那只有iterator发一条而students.size不会发
lazy=true与lazy=extra区别在于
true时如果要取得学生总数它就会加载所有数据到students对象然后取得集合的size()属性值,效率低
而extra就会发一条select count(*)的sql语句来查询。这是一种智能的,一般都用这种抓取策略
-----------------------------------------------------------------------------------
单端关联的lazy测试:(many2one与one2one叫单端关联,对方的一端是one所以叫单端)
ibernate单端关联懒加载策略:即在/标签上可以配置
懒加载策略。
可以取值为:false/proxy/no-proxy
false:取消懒加载策略,即在加载对象的同时,发出查询语句,加载其关联对象
proxy:这是hibernate对单端关联的默认懒加载策略,即只有在调用到其关联对象的方法的时候
才真正发出查询语句查询其对象数据,其关联对象是代理类
no-proxy:这种懒加载特性需要对类进行增强,使用no-proxy,其关联对象不是代理类
注意:在class标签上配置的lazy属性不会影响到关联对象!!!
》》注意:many-to-one标签的lazy值默认是proxy
设置的lazy="false"只对property中设置的lazy有影响不会对单端关联和集合的lazy的设置有影响
/**
* 所有lazy的属性默认
* @author Administrator
*
*/
//用many2one代码测试
//不会发出查询sql
User user = (User)session.load(User.class, 2);
//会发出一条查询sql,转载数据到User
System.out.println("user name=" + user.getName());
//不会发出查询sql
Group group = user.getGroup();
//会发出一条查询sql,转载数据到Group
System.out.println("related group=" + group.getName());
/**
* 将标签中的lazy设置为false
* @author Administrator
*
*/
//会发出一条查询sql,转载数据到User
User user = (User)session.load(User.class, 2);
//不会发出查询sql
System.out.println("user name=" + user.getName());
//不会发出查询sql
Group group = user.getGroup();
//会发出一条查询sql,转载数据到Group
System.out.println("related group=" + group.getName());
/**
* 保持标签中的lazy默认设置
* 将标签中加入lazy=false,many-to-one中的lazy默认为proxy
* @author Administrator
*
*/
//不会发出一条查询sql,转载数据到User
User user = (User)session.load(User.class, 2);
//会发出两条查询sql,因为group不支持了延迟加载所以这里就一次性加载所有数据了。
System.out.println("user name=" + user.getName());
//不会发出查询sql
Group group = user.getGroup();
//不会发出一条查询sql,转载数据到Group
System.out.println("related group=" + group.getName());