Hibernate3.3(4)

u  为什么要学习hql(hibernate querylanguage)->这个是官方推荐,功能强大

? 删除

session.delete(对象) -> 批量删除

? 添加

session.save  session.persist

? 修改->批量修改

sessin.update(对象)

 

查询 对象 obj

obj.setXXX();

? 查询

load get

查询所有 性别是男的雇员?

 

u  hql的详解

为了讲解清楚,我模拟一个学生选课系统 ,创建三张表

从创建的三张表,我们看出:

hibernate 设计者推荐我们在设计表的时候,应当每张表有一个主键,而且该主键最好不含业务逻辑, 

 

product 表

id  productNo   name      price

1     bi001       冰箱       1000

2     nj111       电脑       2000 

 

我们现在使用hibernate工具,自动生成 domain 对象 和映射文件,如果我们的表有主外键的关系,则应当先映射主表,再映射从表

 

* uniqueResult方法

如果我们检索一个对象,明确知道最多只有一个对象,则建议使用该方法:

具体用法如下:

Student s=(Student)session.createQuery("from Student wheresid='20050003'").uniqueResult();

                     System.out.println(s.getSname());

*distinct的用法

过滤重复的记录

//比如,显示所有学生的性别和年龄.

                     Listlist=session.createQuery("select distinct sage,ssex fromStudent").list();

                     for(inti=0;i<list.size();i++){

                            Object[]  objs=(Object[]) list.get(i);

                            System.out.println(objs[0].toString()+""+objs[1].toString());

                     }

*between and..

List list=session.createQuery("selectdistinct sage,ssex,sname from Student where sage between 20 and22").list();

                     for(inti=0;i<list.size();i++){

                            Object[]  objs=(Object[]) list.get(i);

                            System.out.println(objs[0].toString()+""+objs[1].toString()+objs[2].toString());

                     }

*in /not in

//查询计算机系和外语系的学生信息

                    

                     List<Student>list=session.createQuery("from Student where sdept in ('计算机系','外语系')").list();

                     //取出1. for 增强

                     for(Students:list){

                            System.out.println(s.getSname()+""+s.getSaddress()+" "+s.getSdept());

                     }

*group by使用

//显示各个系的学生的平均年龄

List<Object[]>list=session.createQuery("select avg(sage),sdept from  Student group by sdept").list();

                     //取出1. for 增强

                     for(Object[]obj:list){

                            System.out.println(obj[0].toString()+""+obj[1].toString());

                     }

 

 

//having的使用

                     //1.对分组查询后的结果,进行筛选:比如请显示人数大于3的系名称

                     //a.查询各个系分别有多少学生.

                    

                     List<Object[]>list=session.createQuery("select count(*) as c1,sdept from  Student group by sdept havingcount(*)>3").list();

                     //取出1. for 增强

                     for(Object[]obj:list){

                            System.out.println(obj[0].toString()+""+obj[1].toString());

                     }

//2查询女生少于200人的系

                     //a.查询各个系的女生有多个个

                     List<Object[]>list=session.

                     createQuery("selectcount(*) as c1,sdept from  Student wheressex='F' group by sdept").list();

                     //取出1. for 增强

                     for(Object[]obj:list){

                            System.out.println(obj[0].toString()+""+obj[1].toString());

                     }

//1.查询计算机系共多少人?->如果我们返回的是一列数据

                     //这时我们的取法是直接取出list->object 而不是 list->Object[]

                     List<Object[]>list=session.

                     createQuery("selectsage from  Student where sdept='计算机系'").list();

                     //取出1. for 增强

                     for(Objectobj:list){

                            System.out.println(obj.toString());

                     }

3.查询选修11号课程的最高分和最低分.

                     List<Object[]>list=session.

                     createQuery("select11,max(grade),min(grade) from Studcourse where course.cid=11").list();

                     //取出1. for 增强

                     for(Object[] obj:list){

                            System.out.println(obj[0].toString()+"max="+obj[1].toString()+" min="+obj[2].toString());

                     }

//计算各个科目不及格的学生数量.(学生练习!)

                    

                     List<Object[]>list=session.

                     createQuery("selectcount(*),student.sdept from Studcourse where grade<60 group by student.sdept").list();

                     //取出1. for 增强

                     for(Object[]obj:list){

                            System.out.println(obj[0].toString()+""+obj[1].toString());

                     }

参数绑定案例 (jdbc->PreparedStatement setXXX)

使用参数绑定的好处有3:

1.      可读性提高, 2 效果高 3,防止 sql注入漏洞

? 面试题: 如果不使用参数绑定,怎样防止登录时, sql注入?

name password  

思路: 1. 通过用户名,查询出该用户名在数据库中对应的密码,然后再与用户输入的秘密比较,如果相等,则用户和法,否则,非法.

 

参数绑定有两种形式

Query q=session.createQuery(from Studentwhere sdept=:dept and sage>:age)

 

如果我们的参数是 :冒号形式给出的,则我们的参数绑定应当这样:

List<Student>list=session.createQuery("from Student where sdept=:a1 andsage>:sage")

                     .setString("a1","计算机系").setString("sage","2").list();

还有一种形式:

Query q=session.createQuery(from Studentwhere sdept=? and sage>?)

如果我们的参数是以 ? 形式给出的则,参数绑定应当:

List<Student>list=session.createQuery("from Student where sdept=? and sage>?")

                     .setString(0,"计算机系").setString(1,"2").list();

 

参数的绑定,可以分开写:形式如下:

Query query=session.createQuery("fromStudent where sdept=? and sage>?");

                    

                     query.setString(0,"计算机系");

                     query.setString(1,"2");

                     List<Student> list=query.list();

                     for(inti=0;i<list.size();i++){

                            Students= list.get(i);

                            System.out.println(s.getSname()+""+s.getSage());

                     }

把HibernateUtil升级了

u  在映射文件中得到hql语句

hibernate提供了一种更加灵活的查询方法:

把hql语句配置到 对象关系映射文件,

<query name="myquerytest">

       <![CDATA[selectsname,ssex from Student where sage>22]]>

       </query>

在程序中,我们这样获取并执行:

Listlist=session.getNamedQuery("myquerytest").list();

              System.out.println(list.size());

              Iteratorit=list.iterator();

              while(it.hasNext()){

                     Objectobj[]=(Object[])it.next();

                     System.out.println("n="+obj[0]);

       }

 

hibernate 对象的三种关系:

 

1.      one – to – one : 身份证<--->人

2.      one – to – many  部门 <---> 员工

3.      many-to-one   员工<--->部门

4.      many-to-many  学生<--->老师

 

criterial使用:

//查询年龄大于10岁的学生 criteria

             

              Sessions=HibernateUtil.getCurrentSession();

              Transactiontx=s.beginTransaction();

              Criteriacri=s.createCriteria(Student.class);

              //添加检索条件

              cri.add(Restrictions.gt("sage",new Long(10)));

              List<Student>list=cri.list();

              for(Students1: list){

                     System.out.println(s1.getSname());

              }

             

              tx.commit();      

 

hibernate开发的三种方式中的:

编写domainobject + 映射文件------> 创建出对应的数据库,

这里我们说明如果要自动的创建出对应的数据库,需要做配置(hibernate.cfg.xml).

<propertyname="hbm2ddl.auto">create</property>

这里有四个配置值:create , update , create-drop, validate

create : 当我们的应用程序加载hibernate.cfg.xml [ new Configuration().config(); ]就会根据映射文件,创建出数据库, 每次都会重新创建, 原来表中的数据就没有!!!

update: 如果数据库中没有该表,则创建,如果有表,则看有没有变化,如果有变化,则更新.

create-drop: 在显示关闭 sessionFactory时,将drop掉数据库的schema

validate: 相当于每次插入数据之前都会验证数据库中的表结构和hbm文件的结构是否一致

 

l  在开发测试中,我们配置哪个都可以测试,但是如果项目发布后,最好自己配置一次,让对应的数据库生成,完后取消配置,

 

 

u  domain对象的细节:

1.      需要一个无参的构造函数(用于hibernate反射该对象)

2.      应当有一个无业务逻辑的主键属性.

3.      给每个属性提供 get set方法.

4.      在domian对象中的属性,只有配置到了对象映射文件后,才会被hiberante管理.

5.      属性一般是private范围

 

u  对对象关系映射文件的说明

对象关系文件中,有些属性是可以不配,hibernate会采用默认机制,比如

<class table=”?” > table 值不配,则以类的小写做表名

<property type=”?”> type不配置,则hibernate会根据类的属性类型,选择一个适当的类型

 

hibernate对象的三种状态,转换图:

面试图:如果判断一个对象处于怎样的状态?

主要的依据是: 1. 看该对象是否处于session, 2, 看在数据库中有没有对应的记录

瞬时态: 没有session管理,同时数据库没有对应记录

持久态: 有session管理,同时在数据库中有记录

脱管态/游离态: 没有session管理,但是在数据库中有记录.

 

懒加载:

简述: 当我们查询一个对象的时候,在默认情况下,返回的只是该对象的普通属性,当用户去使用对象属性时,才会向数据库发出再一次的查询.这种现象我们称为 lazy现象.

解决方法可以这样:

1.      显示初始化 Hibernate.initized(代理对象)

2.      修改对象关系文件 lazy  改写 lazy=false

3.      通过过滤器(web项目)openSessionInView

 

通过openSessionInView来解决懒加载.

many-to-one 的many这方,如果你配置了

<class name="Student"lazy="false">

那么hibernate就会在 查询学生 many 方时,把它相互关联的对象也查询,这里我们可以看出,对select语句查询影响不大,

one-to-many 的one 的这方,如果你配置

<set name="stus"cascade="save-update" lazy="false">

当你去查询一个部门的时候,我们看到:

Hibernate: select department0_.id asid0_0_, department0_.name as name0_0_ from Department department0_ wheredepartment0_.id=?

Hibernate: select stus0_.dept_id asdept3_1_, stus0_.id as id1_, stus0_.id as id1_0_, stus0_.name as name1_0_,stus0_.dept_id as dept3_1_0_ from Student stus0_ where stus0_.dept_id=?

这样就会把该部门关联的学生全部返回,不管你使用否?

矛盾: 如何让我们的session范围更大.(缺点是session关闭会延时.)

 

u  hibernate对象的关系映射

1.       many-to-one

比如  Employe 和 Department

2.      one-to-many

比如  Departmetn 和 Employee

看一个需求: 通过一个部门号(1),来获取该部门的所有学生?

这里请大家参考代码:

 

3        one-to-one

一对一有有两种方式

(1)    基于主键的一对一

Person IdCard

基于主键的one-to-one指的就是 IdCard 这样主键值同时充当外键.

原理图 :

 

 

 

(2)   基于外键的一对一

 

原理图 :

 

3.       many-to-many

 

案例  学生《---》课程

 

学生<--->课程 就是many-to-many

顾客<--->商品

qq<--->qq群

 

 

上机练习,

请自己想出 生活中

one-to-many

many-to-one

many-to-many

one-to-one

的四组对象关系,并使用hibernate实现写出

对应的domainobject和对象关系映射文件,并通过hbm2ddl 自动创建成功对应的表

 

级联操作

所谓级联操作就是说,当你进行某个操作(添加/修改/删除...),就由hibernate自动给你完成.

比如: Department <---->Student 对象关系,我希望当我删除一个department ,那么就自动删除该部门的所有学生?

 

再比如: bbs项目

主帖<---->回帖 , 把主帖删除,那我们就希望把该主帖的回帖自动删除,这样我们可以使用级联(cascade)操作

\

案例:如何配置级联操作,当删除某个部门的时候,我们自动删除其学生.

首先我们在 配置文件中修改:

<!-- 配置one-to-many关系

 cascade="delete" 当删除该部门的时候(主对象,则级联删除它的学生从对象) -->

<setname="stus" cascade="delete">

<!-- 指定Student类对应的外键 -->

<keycolumn="dept_id" />

<one-to-manyclass="Student" />

</set>

 

java代码中操作:

//演示删除级联

                     //获取到某个部分

                     Departmentdepartment=(Department) s.get(Department.class, 41);

                     s.delete(department);

 

u  演示save-update

配置文件:

<setname="stus" cascade="save-update">

<!-- 指定Student类对应的外键 -->

<keycolumn="dept_id" />

<one-to-manyclass="Student" />

</set>

代码:

//添加学生

Department department=new Department();

department.setName("业务部门3");

                    

Student stu1=new Student();

stu1.setName("顺平6");

//     stu1.setDept(department);

                     Studentstu2=new Student();

                     stu2.setName("小明6");

              //     stu2.setDept(department);

 

                     Set<Student>students=new HashSet<Student>();

                     students.add(stu1);

                     students.add(stu2);

                     department.setStus(students);

                    

                     s.save(department);

说明:

在集合属性和普通属性中都能使用cascade

一般讲cascade配置在one-to-many(one的一方,比如Employee-Department),one-to-one(主对象一方)

 

 

 

 

hibernate综合运用.

以一个内部留言本来讲解.本案例本身不复杂,通过该案例我们讲解 struts+hibernate+接口编程的方式, 主要听点是程序结构的设计.

 

开始:

1.      看需求

2.      根据需求文档,我们画出程序框架图, 框架图的三个接口,暂时不写,后面我们再引入.

3.      创建一个web项目.

4.      创写web层.

4.1引入struts

42.把web层的jsp 表单 action 编写完毕,并且打通这个登录的模块

5. 引入hibernate 使用手动的方法来开发domain和对象关系文件

6. 把hibernate.cfg.xml写好

7. 写成工具类 dao HibernateUtil.java

8. 测试一下看看能否映射ok

测试成功!

9. 我们使用接口来解耦. web---接口--业务层

10. hibernate中,取消lazy 不要在 one-to-many 的 one的一方的<set /> ,可以在 many的一方配置 lazy=false;

11. 添加消息的功能.(假设用户是唯一的.,如果用户不唯一,我们可以通过id来发送信息)

 

 

 

* 在jsp页面中获取当前项目名称可以

<%=this.getServletContext().getContextPath() %>

通过标签: ${pageContext.request.contextPath}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值