class="cn.jbit.hibernatedemo.entity.Dept"/>
部门:
一方配置多方的集合:
privateSetemps=newHashSet();
Cascade:
none/delete/all/save-update
元素的inverse属性:
关联方向
1三期课程核心---项目主导
必须保证每个框架做一个项目实例
1.1软件生命周期
一个完整的项目或软件的生命周期有具体如下:
软件的生命周期:
Ø1.可行性分析
Ø2.需求分析
Ø3.概要设计
Ø4.详细设计
Ø5.数据库设计
Ø6.程序设计
Ø7.编码
Ø8.模块测试
Ø9.集成测试
Ø10.实施和维护
程序人员而言我们重点关注的是“程序设计“
1.2程序/软件设计
软件设计中的核心是面向对象!
在整个软件设计中我们编码人员尤为关注的是“OOD面向对象的设计“。
面向对象设计的过程中三点尤为重要:
⏹平台架构
⏹应用设计模式
S2:
我们学过的设计模式:
单例、工厂、DAO等。
C#和Java中都学到单例,在这里一定要强
调:
设计模式和语言无关
我们三期的核心=====》MVC
⏹框架
定义:
框架是一种或几种设计模式的实现,它是基于某一种固定语言,它为我们提供了一些类库以及设计结构,使得程序的设计更加标准以及可维护!
我么三期会针对企业中最常用的框架进行讲解(J2EE3种SSH和JQuery类库)
⏹设计模式和框架的区别
以上图画中描述的CEO,CFO,技术总监等职位,一般是针对大型的技术型公司!
一般的“饭店不适用“这就相当于框架一样,框架是针对某种具体语言的某种设计模式的实现。
我们三期最核心的是MVC设计模式,一下将进一步做介绍!
1.3MVC设计模式
1.4业务逻辑层的介绍
持久化:
定义:
由内存转到外存的一个过程叫持久化。
我们可以简单的想象为数据库操作比如:
将用户名和密码保存到数据库!
但是不完全对!
因为我们也可能将数据保存到文件中!
持久层做什么?
✓连接数据库
✓获取连接通道
✓返回结果集
✓。
。
。
。
。
。
。
。
这是我们JDBC操作数据库的7个步骤!
后来我们经过封装=====》封装为DBHelper(打开连接、非查询的通用方法)====》封装后我们的数据库操作更加简单!
=====》我们Hibernate为我们封装了更多持久化数据操作的方法,而且Hibernate也是面向对象的。
1.5Hibernate核心介绍
◆1.ORM模式
◆2.Hibernate框架
◆3.框架原理(枯燥,但是非常重要,有利于理解定制框架)
◆4.Hibernate核心接口
◆5.基于MyEclipse的Hibernate配置
◆6.案例:
单表应用
◆7.MVC基于Hibernate的应用
1.5.1ORM对象关系映射
通过面向对象的思想,将数据库中的表和Java中的对象一一对应!
在数据库中一对多的关系通过主外键表示!
比如:
表中一个用户====》多个联系人!
那如果在类中表现一对多的关系呢?
1.引入:
用户类中创建一个联系人的对象集合!
2.分析:
⏹List------------------》允许存放相同的对象
⏹Set-------------------》不允许存放相同的对象
⏹Map------------------》键值对
==================【应该使用Set集合存放联系人集合】
主键在表中唯一标识一列,所以一个对象也是唯一的。
应该用====》set集合存放
3.实现
Ø一方添加多方的Set集合
Ø多方添加一方的对象属性
4.如何告诉程序这种关联关系呢?
Ø写程序:
比如通过selet语句关联查询
Ø配置文件:
⏹*.properties配置文件--log4j
⏹*。
Xml文件-----------最常见的web.xml
Xml格式大致如下:
将表中的字段和对象中的属性逐一的对应
…..users中id属性-----对应表中id…
。
。
。
users中username-----对应表中username...
.......
数据库连接的配置
……className=”***”….
……usename=”sa”….
……passwod=”123”….
。
。
。
等数据库连接的相关信息
最终达到的目标是:
New一个类就插入一条记录
两个配置文件分别对应:
1.描述表和类的对应关系
2.描述数据库的配置信息
这些配置信息我们可以自己写!
但是我们自己写有如下缺点:
1.安全性不够
2.功能不全面
3.执行效率极低!
===一些牛人就联合起来帮我们实现了!
【Hibernat框架】
1.6ORM
ORM核心:
⏹一个表对应一个类
⏹表和类对应的配置文件
⏹描述操作哪个数据库的配置文件
Hibernate是如何实现的呢?
我来详细讲解!
1.7Hibernate简介和核心接口
1.7.1版本
最新版本:
4.*经典版本:
3.*版本2.X和3.X相差甚远,建议不要去学习,我们针对3.X学习
1.7.2核心
1.7.2.1
特点
1一个sessionFactory实例对应一个数据源,线程安全(可被多个线程共享),重量级(初始化创建需要很大缓存),如需访问多个数据库则需为每个数据库创建单独实例
2Session接口:
CURD核心接口,也被成为”持久化管理器”,轻量级,线程安全
3Transaction:
hibernate底层自动封装了事务。
4Query对象:
是查询接口。
该对象封装了HQL查询语句,HQL是面向对象的,查询使用类名和类的属性名。
不是表名和字段名。
5Crieteria:
也是查询接口,封装了基于字符串形式的查询语句。
比Query更加面向对象。
擅长执行动态查询
CURD操作分类
●1.单表
●2.多表
●3.Hibernate优化(最重要
●4.Hibernate和web应用整合
这也是我们Hibernate的核心内容
1.8MyEclips中配置Hibernae
⏹1.DBBrower配置
⏹2.为项目引入Hibernate框架
⏹3.Hibernate反向工程(将表映射为实体类)
1.8.1数据库浏览器介绍(DB Brower)
第一步:
在左上角“透视图”中选择数据库浏览视图
第二步:
新建
第三步:
数据库驱动配置
第四步:
Hibernate反向工程将数据库中的表映射成Java中的实体对象
具体操作详看视频
学生常见错误总结:
1.Oracle服务没启动
2.soctt用户解锁
3.密码不对
4.连接字符串不对
5.oracle表中没有主键
1.8.2为项目引入Hibernate框架
第一步:
新建Java项目三期_Hibernate01
第二步:
为三期_Hibernate01引入Hibernate框架支持
第二步:
选择Hibernate版本
第三步:
选择核心文件的位置(直接默认,下一步)
第四步:
选择配置好的数据库驱动
第五步:
SessionFactory工厂类
点击完成,项目添加Hibernate成功。
成功后如图所示
1.8.3Hibernate反向工程
将数据库中的表映射为Java中的实体对象!
步骤:
切换到数据库浏览视图-----》右击对应的表-选择Hibernate反向工程---选择
Hiberane可以帮我们自动生成主键,常用的主键生成策略有:
1.Native:
会根据底层数据库的实现来自动选择主键生成方法。
2.Identity:
自动增长。
比如mysql和sqlserver
3.Sequence:
序列方式。
Oracle和DB2
4.Uuid:
Hibernate会自动生成唯一编码
5.Assigend:
主键生成规则由外部层序负责。
oracle序列配置如下
--序列配置-->
序列名
下面这个图是映射成功的JavaBean对象和期配置文件
1.9Hibernate单表操作
步骤:
⏹创建配置文件
⏹生成SessionFactory对象
⏹获取session
⏹非查询打开事务对象
⏹关闭Session对象
⏹Oracle序列器更改,生成id的类型修改(Oracle不支持BigDecimal类型)
⏹显示打印SQL配置
--打印sql-->
true
//1.获取项目的核心配置文件
Configurationconf=newConfiguration().configure();
//2.构建SessionFactory工厂类:
SessionFactoryfactory=conf.buildSessionFactory();
//3.从session工厂中创建Session对象
Sessionsession=factory.openSession();
//4.非查询操作,打开事务
Transactiontx=session.beginTransaction();
tx.begin();//开始事务
//调用接口保存
TestUserstestUsers=newTestUsers("zzy","123");
session.save(testUsers);
mit();//提交事务
//关闭Session对象
session.close();
1.10利用工具类HibernateSessionFactory实现单表操作
Configurationconf=null;
SessionFactoryfactory=null;
Sessionsession=null;
Transactiontx=null;
try{
//读取配置文件
conf=HibernateSessionFactory.getConfiguration();
//获取session工厂
factory=HibernateSessionFactory.getSessionFactory();
//打开session
session=factory.openSession();
//非查询打开事务
tx=session.beginTransaction();
//保存
TblUseru=newTblUser("zzy1","123");
session.save(u);
//提交事务
mit();
}catch(HibernateExceptione){
tx.rollback();
}finally{
session.close();
}
1.11常用方法:
保存:
session.save(实体对象);
根据对象id删除
session.delete(带id的实体对象);
修改(update当id不存在时报异常)
session.update(带id的实体对象);
修改(merge也是修改,当要修改id不存在时,自动插入)
session.merge(u);
保存或修改,如果实体类包含id,就修改,否则新增
session.saveOrUpdate(实体类);
根据id查询:
load,找不到对应id行返回空指针异常
TblUseru2=(TblUser)session.load(TblUser.class,2);
根据id查询:
get方法,找不到对应id的行返回null
TblUseru2=(TblUser)session.get(TblUser.class,2);
1.12Hibernate对象三种状态区别
(1)瞬时态/临时态--Transient
(2)持久态--Persistent
(3)游离态/脱管态---Detached
瞬时态:
刚new出来,还未被持久化保存,还未被session管理的对象。
如果变量未被引用,适当时jvm会回收!
持久态:
已经被持久化,加入到session缓存中。
处于持久化状态的java对象叫持久态。
(1)和session对象关联,对象加载到session缓存中。
(2)在数据库中有和对象一一对应的记录
游离态:
已经被持久化,单不再处于session缓存中,处于游离状态的java对象。
特点:
(1)本质上与瞬时态相同,都是存储在内存中,在长时间不被使用时jvm会自动回收
(2)比瞬时态多了一个对应的数据库记录标识!
当某持久对象关联的session关闭后,该对象转为瞬时状态。
1.13Hibernate缓存机制
一级缓存(Session缓存)
案例:
TblUseru=newTblUser(“zzy1”,”123”);
session.save(u);
注意:
调用save方法保存用户时,并不是马上将对象保存数据库!
而是暂时将对象保存到session对象中。
同理,调用其他方法时也不会直接和数据库沟通!
中间都要先将数据暂时保存在session对象中。
我们把session对象的数据存储机制叫一级缓存!
事务范围,每个事务(Session)都有单独的第一级缓存.
一级缓存的管理:
当应用程序调用Session的save()、update()、saveOrUpdate()、get()或load(),以及调用查询接口的list()、iterate()--(用的是n+1次查询,先查id)或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。
当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。
Session为应用程序提供了两个管理缓存的方法:
evict(Objectobj):
从缓存中清除参数指定的持久化对象。
clear():
清空缓存中所有持久化对象,flush():
使缓存与数据库同步。
比如:
两次调用get方法查询同意对象,第二次查询不调用数据库,不生成sq语句。
因为第一次查询时会将结果存储到内存中(session缓存中),第二次直接从一级缓存中查找
TblUseru=(TblUser)session.get(TblUser.class,3);
TblUseru2=(TblUser)session.get(TblUser.class,3);
二级缓存(SessionFactory):
---后期需要专门借助第三方插件实现!
!
二级缓存参见:
01-Hibernate缓存原理.doc
2Hibernate查询
HQL查询:
语法与熟悉的sql语句差不多,是我最常用也是最喜欢用的一种查询方式。
条件查询,分页查询,连接查询,子查询写起来与sql语法基本一致。
唯一不同的就是把表名转化成了类或实体对象名。
Hql关键字不区分大小写,但是属性和类名区分大小写!
2.1HQL
查询所有:
from类名as别名where条件groupby...having...orderby....;
查询某几列:
select别名.列1,别名.列2....from类名别名where条件........;
案例2:
查询所有
Stringhql="fromTblUser";
Queryquery=session.createQuery(hql);
Listlist=query.list();//list循环遍历
Iteratorit=query.iterate();//迭代器遍历
while(it.hasNext()){
TblUseru=(TblUser)it.next();
System.out.println(u.getUname());
}
两种遍历数据方式区别:
List直接从数据库查询数据库。
生成一条查询语句
Iterator,先从数据库查询id,然后再从缓存中找数据是否存在,如果不存在再根据每个id从数据库查询,生成n+1次查询
ititerate()--(用的是n+1次查询,先查id)
list和iterate的区别?
*list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
*iterate:
在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题
避免N+1查询解决方法:
1、可以将fetch抓取数据的属性改为“join”,来避免N+1次的查询;
2、使用二级缓存
案例2:
为参数动态复制
Stringhql="fromTblUseruwhereu.id=?
";
Stringhql="fromTblUseruwhereu.id=:
别名";
Listlist=query.list();//list循环遍历
query.setParamter(0,值);--?
从0开始赋值
query.setParamter("别名","值")--别名赋值
//赋值还可以连接
Queryq=session.createQuery("fromCategorycwherec.id>:
minandc.id<:
max")
.setInteger("min",2)
.setInteger("max",8);
Listcategories=(List)q.list();
案例3:
两表联合
Stringhql="fromStudentwhere Class.className ='二班'";
(Student实体类中含有Class对象的引用。
这样相当于两张表的联合查询)
案例4:
分页
Queryquery=session.createQuery("fromCustomerc
orderbyc.nameasc");
query.setFirstResult(开始位置);
query.setMaxResults(每页显示几条);
Listresult=query.list();
开始位置=(当前页数-1)*每页条数
案例5:
模糊查询
Stringhql="fromTblUseruwhereu.unamelike?
";
Queryquery=session.createQuery(hql);
query.setParameter(0,"zzy%");
Listlist=query.list();
案例6:
重排
Queryq=session.createQuery("selectdistinctcfromCategorycorderbyc.namedesc");
Listcategories=(List)q.list();
案例7:
查询部分列,返回一个object数组列表
Queryq=session.createQuery("selectu.id,u.unamefro