hibernate教程笔记3

为什么要学习hql(hibernate query language)->这个是官方推荐,功能强大
? 删除
session.delete(对象) -> 批量删除
? 添加
session.save session.persist
? 修改->批量修改
sessin.update(对象)

查询 对象 obj
obj.setXXX();
? 查询
load get
查询所有 性别是 男的雇员?

hql的详解
为了讲解清楚,我模拟一个学生选课系统 ,创建三张表
从创建的三张表,我们看出:
hibernate 设计者 推荐我们在设计表的时候,应当每张表有一个主键,而且该主键最好不含业务逻辑,

product 表
id productNo name price
1 bi001 冰箱 1000
2 nj111 电脑 2000

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

  • uniqueResult方法
    如果我们检索一个对象,明确知道最多只有一个对象,则建议使用该方法:
    具体用法如下:
    Student s=(Student) session.createQuery(“from Student where sid=‘20050003’”).uniqueResult();
    System.out.println(s.getSname());
    *distinct的用法
    过滤重复的记录
//比如,显示所有学生的性别和年龄.
			List list=session.createQuery("select distinct sage,ssex from Student").list();
			for(int i=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("select distinct sage,ssex,sname from Student where sage between 20 and 22").list();
			for(int i=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(Student s: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 having count(*)>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("select count(*) as c1,sdept from  Student where ssex='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("select sage from  Student where sdept='计算机系'").list();
			//取出1. for 增强
			for(Object obj:list){
				System.out.println(obj.toString());
			}
//查询选修11号课程的最高分和最低分.
			List<Object[]> list=session.
			createQuery("select 11,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("select count(*),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 Student where sdept=:dept and sage>:age)

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

List<Student> list=session.createQuery("from Student where sdept=:a1 and sage>:sage")
			.setString("a1", "计算机系").setString("sage", "2").list();

还有一种形式:

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

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

List<Student> list=session.createQuery("from Student where sdept=? and sage>?")
			.setString(0, "计算机系").setString(1, "2").list();

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

Query query=session.createQuery("from Student where sdept=? and sage>?");
			
			query.setString(0, "计算机系");
			query.setString(1, "2");
			List <Student> list=query.list();
			for(int i=0;i<list.size();i++){
				Student s= list.get(i);
				System.out.println(s.getSname()+" "+s.getSage());
			}

把HibernateUtil升级了

  • 在映射文件中得到hql语句
    hibernate提供了一种更加灵活的查询方法:
    把hql语句配置到 对象关系映射文件,
<query name="myquerytest">
	<![CDATA[select sname,ssex from Student where sage>22]]>
	</query>

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

List list=session.getNamedQuery("myquerytest").list();
		System.out.println(list.size());
		Iterator it=list.iterator();
		while(it.hasNext()){
			Object obj[]=(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
		
		Session s=HibernateUtil.getCurrentSession();
		Transaction tx=s.beginTransaction();
		Criteria cri=s.createCriteria(Student.class);
		//添加检索条件
		cri.add(Restrictions.gt("sage", new Long(10)));
		List<Student> list=cri.list();
		for(Student s1: list){
			System.out.println(s1.getSname());
		}
		
		tx.commit();       

hibernate开发的三种方式中的:
编写domain object + 映射文件 ------> 创建出对应的数据库,
这里我们说明如果要自动的创建出对应的数据库,需要做配置(hibernate.cfg.xml).
create
这里有四个配置值: create , update , create-drop, validate
create : 当我们的应用程序加载hibernate.cfg.xml [ new Configuration().config(); ]就会根据映射文件,创建出数据库, 每次都会重新创建, 原来表中的数据就没有!!!
update: 如果数据库中没有该表,则创建,如果有表,则看有没有变化,如果有变化,则更新.
create-drop: 在显示关闭 sessionFactory时,将drop掉数据库的schema
validate: 相当于每次插入数据之前都会验证数据库中的表结构和hbm文件的结构是否一致

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

  • domain对象的细节:

  1. 需要一个无参的构造函数(用于hibernate反射该对象)
  2. 应当有一个无业务逻辑的主键属性.
  3. 给每个属性提供 get set方法.
  4. 在domian对象中的属性,只有配置到了对象映射文件后,才会被hiberante管理.
  5. 属性一般是private范围
  • 对对象关系映射文件的说明
    对象关系文件中,有些属性是可以不配,hibernate会采用默认机制,比如
    table 值不配,则以类的小写做表名
    type不配置,则hibernate会根据类的属性类型,选择一个适当的类型

hibernate对象的三种状态,转换图:
在这里插入图片描述

面试题:如果判断一个对象处于怎样的状态?
主要的依据是: 1. 看该对象是否处于session, 2, 看在数据库中有没有对应的记录
瞬时态: 没有session管理,同时数据库没有对应记录
持久态: 有session管理,同时在数据库中有记录
脱管态/游离态: 没有session管理,但是在数据库中有记录.

  • 懒加载:
    简述: 当我们查询一个对象的时候,在默认情况下,返回的只是该对象的普通属性,当用户去使用对象属性时,才会向数据库发出再一次的查询.这种现象我们称为 lazy现象.
    解决方法可以这样:
  1. 显示初始化 Hibernate.initized(代理对象)
  2. 修改对象关系文件 lazy 改写 lazy=false
  3. 通过过滤器(web项目) openSessionInView
  • hibernate对象的关系映射
  1. many-to-one
  2. one-to-many
    看一个需求: 通过一个部门号(1),来获取该部门的所有学生?
    这里请大家参考代码:
  3. one-to-one
    一对一有有两种方式
    (1) 基于主键的一对一

原理图 :

(2) 基于外键的一对一

原理图 :

  1. many-to-many

学生<—>课程 就是many-to-many
顾客<—>商品
qq<—>qq群

上机练习,
请自己想出 生活中
one-to-many
many-to-one
many-to-many
one-to-one
的四组对象关系,并使用hibernate实现写出
对应的domain object和对象关系映射文件,并通过 hbm2ddl 自动创建成功对应的表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值