Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1002384
  • 博文数量: 152
  • 博客积分: 4937
  • 博客等级: 上校
  • 技术积分: 1662
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-05 16:55
文章分类

全部博文(152)

文章存档

2013年(12)

2012年(6)

2011年(58)

2010年(43)

2009年(1)

2008年(15)

2007年(17)

我的朋友

分类:

2010-06-24 17:35:01

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单向关联:
classes.hbm.xml配置:
 
  
   
  

  
  
   
   
  

 
 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());
 
 
 
阅读(1376) | 评论(0) | 转发(0) |
0

上一篇:ssh配置

下一篇:hibernate_hql

给主人留下些什么吧!~~