Hibernate总结文档.docx
《Hibernate总结文档.docx》由会员分享,可在线阅读,更多相关《Hibernate总结文档.docx(19页珍藏版)》请在冰点文库上搜索。
Hibernate总结文档
Hibernate学习总结文档
天润4+5
黄萍
目录
一、Hibernate知识总结4
1.hibernate简介4
2.hibernate基础4
⑴.Session(持久化上下文)4
⑵.Hibernate实体对象生命周期4
三种状态4
⑶.增删改查的方法5
3.搭建Hibernate,建立HibernateAPI6
4.$的功能,jquery的三种语法7
5.hibernate级联关系映射(高级映射)7
⑴.级联关系简介7
⑵.一对一映射8
⑶.一对多单向映射10
⑷.单向映射总结12
⑸.一对多双向映射12
⑹.多对多映射-----ORM(对象关系映射)的优势在多对多的时候体现出来13
6.HQL语言14
⑴.HQL说明14
⑵.数据的检索方式14
⑶.HQL的检索技术14
一、技术知识总结16
1.SQL语句九个动词一共分为四类16
2内存17
3.java的数据类型和封装类的区别17
4.Java容器API17
5.java反射17
6.gettersetter17
一、Hibernate知识总结
1.hibernate简介
通过学习我们对Hibernate有了较深刻地了解:
Hibernate里面木有一行SQL语句,却可以操作数据库。
所以他就是一款使用面向对象的技术去操作数据库的架构。
操作数据库是靠ORM,因为数据库不是面向对象的产物。
在底层通过ORM技术,通过java代码操作数据库
2.hibernate基础
.Session(持久化上下文)
session不是一个对象
计算机内存区域:
堆+栈(缓存:
存储经常使用的数据)
在缓存中hibernate又划分了一小块缓存(数据缓存),他直接与数据库进行交互,这块缓存就是session
一个持久态对象在能对应数据库中的行。
并且改变持久态对象数据库中的行也会随之改变
Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。
)
.Hibernate实体对象生命周期
实体对象生命周期:
瞬态、持久态(不能被垃圾回收)、游离态
对于java来讲一个对象不存在状态,只存在生命周期,但是使用过程中他们也有自己不同的变化“状态”
java是一种高度抽象语言,java中的每一个对象就像现实生活中的一个人一样,不断地将数据模型扩大,在不同的生命周期有不同的特点与动作
当一个对象跟hibernate有关系?
(即这个对象被hibernate所管理)此时hibernate(ORM)赋予对象生命周期中的三个状态
hibernate的ACID即对对象的三种状态进行改变
三种状态
瞬态(Transient):
刚被生命的对象处于瞬态(即与session无关,与数据库无关),一个瞬态的对象不能对应数据库中的行,他与session无关
游离态(Detached):
session.close();即将数据缓存还给数据库,此时对象属于游离态,游离态的对象也对应数据库中的行,但是hibernate不会依照游离态对象的改变来更新数据库。
Error:
数据不同步问题(使用游离态对象)
持久态(Persistent):
持久态的特征:
对其所做的变更操作都会被Hibernate持久化到数据库中去-->就素更改数据库,必须和session对象相关联,
.增删改查的方法
更新:
瞬态对象---save()、update()---持久化要给出唯一标示
save()方法根据映射文件生成表
session的update要求新的用来替换的瞬态对象必须携带唯一标识
delete()方法:
删除实体对象所对应的数据库中的记录,删除的对象状态必须是持久态
查找:
直接得到持久态对象就是查询:
Aa=(A)seesion.get(A.class,唯一标识);~~~单行查询~~获得a以后可以用a.seta()来进行修改,session.delete(a)可以被删除。
删除后处于瞬态。
get()方法:
当程序找不到对象时返回的是null,我们用null判断可以处理异常
load()方法:
当程序找不到对象时返回的是底层代理直接返回异常
增:
session.save(Userinfo);
删:
session.delete(userinfo);一定要给出唯一标识。
改:
session.update(userinfo);
查:
Listlist=session.createQuery(“HQL语句”).list()
Hibernate的编辑:
编辑首先要获得要编辑的数据,有两种方式可以获得
第一种:
可以用javascript做编辑,这样可以提升性能不用再查询数据库因为要得到的数据页面上都有,(注意:
html页面尽量不要出现同名的属性,万一出冲突)
第二种:
传递id使用Servlet查询,单条查询直接返回持久化对象就行
(Userinfo)session.get(Userinfo.class,id)返回的就是持久化对象
当得到值以后:
可以直接使用EL表达式,jsp的内置表达式可以直接取值,去对象不能取结果集,因为不能循环
${userinfo.username}=request.getAtrbute("").username;
(注意:
查询修改一定要提交事务,否则数据库不会更改)
3.搭建Hibernate,建立HibernateAPI
1.先写个持久化类(属性,getter和setter函数,要写注释)
类注释:
@author作者
@see类体现的功能
@version开发版本未上线0.9
类成员注释:
/**/
类方法注释:
(后可用中文)
@see功能
@param参数
@return返回值
2.编写对应的xml。
后缀名写成.hbm.xml将持久化类映射到数据库
名字生成方式
名字类型
表里名字
新建xml文件,通过DTD使其为hibernate的XML配置文件。
在hibernate-mapping标签下有两个子标签,id和property。
Id是对表中主键的,id在文件中仅有一个,不支持复合主键。
id下有column和generator。
Column是表中的字段,generator设置主键生成方式,自增唯一使用native(可以在帮助文档中查找适合的生成方式,native是根据底层数据库的能力选择identity,sequence或者hilo中的一个)。
Property下有column,和id下的一样,但在property下还要设置属性对应的表中字段的类型,即type标签,也可以直接在property标签中设置。
3.右键工程从myeclipse选择添加hibernate配置文件(.cfg.xml)(添加启动参数:
数据库启动参数、显示、加载xml)
src是外部工程的classpath
hibernate.cfg.xml要放在src下面
在里面配置三种类型的启动参数
1.与连接数据库有关的启动参数
方言(dialet)为了让当前的框架更好的兼容数据库
2.第二种参数与hibernate本身的配置有关
true
update
3.第三种类型的启动参数与映射类型文件加载有关
4.创建一个Dao的接口:
里面写要实现的方法抽象方法;(就想业务逻辑bean的接口一样)
5.创建一个DaoBean类~实现接口中所有方法。
6.创建一个DaoFactory其中将DaoBean实例化后返回(就是一样工厂可以让所有方法好使,用静态类返回这样可以在servlet里直接用类名调用实现方法get。
。
DaoBean)《单例模式》session不是线程安全的不能成为成员变量,每一个都要重新建立,然后再建立事物
7.创建servlet。
里面创建类成员Dao每个都要有,用转型Dao=Factory.get..Bean()
4.$的功能,jquery的三种语法
a.$跟的是括号(),则跟传统js对象中document一样,可以自由的选择跟获取到页面任何元素,也可以创建元素。
#指id属性名字
$("#id"),选择页面上id叫做id的对象
基本等于doument.getElementById("id")
$("#id").html("你好")
.html("")写的那个
b.$.after();调用jquery底层的功能函数
$.attr(name,value);
$.attr("value","你好");把某元素的value属性变成你好
$("#id").attr("value","你好")混合语法
c.${}等于window.load=function(){}页面加载完出发函数
$("#da")选择d下的a元素
5.hibernate级联关系映射(高级映射)
.级联关系简介
首先,数据库的级联关系是靠约束实现的check
对于数据库来说两张表之间的关系有三种,
一对一,共享主键
一对多,外键约束,(一般在多建立外键,约束到普通字段)
多对多,“中间表约束”,(两个表的的主键放到一个表中去对应)
尽量不要建立物理约束,数据库维护会产生许多问题,尽量建立逻辑约束,靠自己维护。
能好用一对多的尽量不要使用多对多
两个表之间要产生级联关系不能在表里面产生关系,Hibernate级联原则。
要直接在model/xml里建立关系。
在Hibernate要实现两张表的级联关系,不能再数据库里配置关系,因为不是自己创建的,必须在类中进行配置,在映射关系中给于表述。
和数据库中表对应的映射叫做基本映射,Hibernate中的映射叫做高级映射。
Hibernate中一共有4中映射:
、、、
.一对一映射
如何建立一对一映射(单向)
第一步:
选择要产生关系的两个持久化类,在里面建立关系,如:
Person类要单向映射到IdCard类中则要在Person类中声明一个idcard的成员变量
Eg:
ClassPerson{
intid;
Stringname;
IdCardidcard;//IdCard这个叫做级联操作属性,很重要用处灰常大啊!
}
级联属性的作用:
a.通过这个成员进行级联操作
b.在xml映射文件中通过这个属性来完成级联关系的描述
第二步:
在映射文件中加入有关级联关系的属性在hbm中hibernate框架,提供了一些用来描述级联关系创建及配置的标志:
idcard
标签注解:
a.主键生成方式class=“foreign”(使用另外一个相关联的对象的标识符)上idcrad里面去找主键Person主动贡献idcard所以主键不是自己生成的而是共享idcard
b.标签表示获取java中的一个变量,或者给一个变量赋值
标签注解
a.ont-to-one的级联关系需要靠name所给的名字来实现,上面那个类name=“idcard”class表示你要实现一对一的持久化类
b.java通过hibernate加入的级联关系是逻辑关联,数据库本上没有添加上物理关联
true,添加物理约束,false只有逻辑约束,默认为false
c.fetch级联抓取方式,用innerjoin查询,而不是分开查询。
第三步:
写测试类生成表有关CreateDB.class中的
SchemaExportexport=newSchemaExport(cfg)
SchemaExport是数据模型导出类
export.create(true是否将没有创建的表Hibernate自定义的建表脚本发向数据库,true在数据库是否执行这个脚本);
校验hibernate启动时是否生成对应表,把所读到的数据模型创建出来
存储数据时,要将被映射的对象存到映射对象中
使用session.save(保存有关联一方对象);即可把他本身和它所包含的对象都存到数据库里面去
(双向)要在两个类中配置一对一的关系,两个类之间靠互换实例来进行关系访问的。
需要在双方实体类都设置映射属性、在映射文件中设置的标签关联到对方的表中去
.一对多单向映射
一方操作多方的实现步骤:
.选择要产生关系的两个持久化类,在里面建立关系,在一方中添加容器(最好是set)
B.在映射文件中加入有关级联关系的属性在hbm中hibernate框架,提供了一些用来描述级联关系创建及配置的标志:
·要在一方中设置映射关系如下
一对多要靠容器实现,则最外面的标签是,set里面的标识了所对应的多的一方的外键属性的名称,set里的标识所对应的多方的持久化对象的类名。
一对多单向总多方不需要配置xml。
C.编写配置文件Hibernate.cfg.xml,标识所要连接的数据库属性,和需扫描的映射文件。
D.编写配置类(同一对一)
E.在类中级联添加、查询的方式:
添加:
Classesclasses=newClasses();//建立一方对象
classes.setCname("8班");
Studentstudent=newStudent();//建立多个多方对象
student.setSname("大毛");
Studentstudent1=newStudent();//建立多个多方对象
student1.setSname("二毛");
Studentstudent2=newStudent();//建立多个多方对象
student2.setSname("三毛");
Setset=newHashSet();/*使用容器,Hash类中的方
set.add(student);法将多方存入;*/
set.add(student1);
set.add(student2);
classes.setStudent(set);
session.save(classes);//保存一方对象
查询:
Classesclasses=(Classes)session.get(Classes.class(类名,一定要加.class),2(类的id号));
Setset=classes.getStudent();//级联查询
Iteratoritor=set.iterator();//使用迭代器读取一中的多
while(itor.hasNext()){
Studentstudent=itor.next();
System.out.println("学生名"+student.getSname());//循环输出
}
多方操作一方的单向映射实现
A.选择要产生关系的两个持久化类,在里面建立关系,这时只需要在多方中添加类对象。
B.在映射文件中加入有关级联关系的属性在hbm中hibernate框架,提供了一些用来描述级联关系创建及配置的标志:
·要在多方中设置映射关系如下
Name表示在多方持久化类中映射属性的名称,column标识外键名称,多方给自己创建的外键,cascade表示级联方式
C.编写配置文件Hibernate.cfg.xml,标识所要连接的数据库属性,和需扫描的映射文件。
D.编写配置类(同一对一)
E.在类中级联添加、查询的方式:
.单向映射总结
《一方操作多方策略》
当一方操作多方的时候(级联关系由一方)做添加的时候7个sql
外键不允许为null时一方无法操作多方
《多方操作一方策略》
当多方操作一方昨天加的时候,产生4个sql,因为多方不需要额外拼写修改外键的语句:
即证明-->无论外键是否为空都可以操作
.一对多双向映射
配置过程即单向和双向两个都要配置,特别注意:
·一方和双方必须同时配置外键,并且双方建立的外键名字必须一样,否则多方会产生两个外键。
·互相加载语句都得写:
//互相都填好才行
Setset=newHashSet();
set.add(student);
set.add(student1);
set.add(student2);
classes.setStudent(set);
student.setClasses(classes);
student1.setClasses(classes);
student2.setClasses(classes);
·当双方两种关系都存在的时候hibernate框架默认的级联关系的维护方是:
一方来维护为级联关系的主控方(7个sql)
·但是一方主控有性能缺陷,所以要将主控权交给多方
要在一方的配置文件里······inverse="true"表示当前的一方反转去级联关系主控权
·查询一方后当session无法级联查询多方的数据
lazy="false"(查询容器)>
在查询一方时她的容器跟着被查询出的记录一起被加载出来,此时就算session被关闭容器内的东西也可以使用
但是!
!
!
会产生性能问题。
所以在数据量很大的时候尽量不能=要让lazy=“false”懒加载是hibernate为了解决性能问的一个创造。
.多对多映射-----ORM(对象关系映射)的优势在多对多的时候体现出来
第一步:
多对多需要产生关系表,整合外键
两个多方映射文件制定中间表名相同,外键名相同
《key》本表在关系表中外键名
(一对多时代表在本表中生成外键的名称)
多对多关系配置:
双方set都必须指定table,且table的名字必须一致
双方都有key标记,单独一方的key标记中的column名字应该对应另外一方的many-to-many中的column
6.HQL语言
.HQL说明
HQL(HibernateQueryLanguage)查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式。
.数据的检索方式
第一种:
OID(objectid),session.get()load();单挑查询
第二种:
HQL出现复杂查询时,不允许用太多嵌套hql语法类似于sql但是是面向对象的查询语言,sql面向数据库。
HQL语句在底层按照配置文件所给出的方言被转译成SQL语句后执行。
第三种:
面向对象的检索(通过ORM得到持久态),
第四种:
QBC条件拼接查询(简单好用查下)
第五种:
QBE多维查询(BI数据挖掘数据抓取数据分析多维分析)
第六种:
SQL原生SQL的检索方式hibernate封装了jdbc
.HQL的检索技术
实体查询
查询出来的都是持久态对象=表中的行(行查询,取值时按行循环取出对象).
有别名的或者按照别名来查询的情况下可以使用select,*不可以使用
会产生Hibernaten+1问题
原因:
使用iterate作为结果集,因为iterate支持数据库的查询缓存技术,方法默认不查数据库而是查数据缓存中区,当缓存中没有数据就拼sql去数据库中查询去。
产生n+1条语句。
list查数据库不查数据缓存,不支持数据缓存技术
解决方案:
先执行list会把数据放到缓存区去~
get和load方法的区别:
get不支持数据缓存,load查缓存
属性查询
查询出来的都是持久态对象的属性=表中的列(列查询)
<查询效率根据表结构的不同,列查询和行查询的效率不同>
单属性查询----返回当前属性类型
多属性查询----返回对象数组object[]
动态构造"selectnewStudent(id,username)fromStudent"用构造函数创建一个对象把查的属性封装到对象中
在持久化类中添加属性构造器,重载构造函数(实体构造器)
自动引包默认为真
hql语句中有没有select是实体查询和属性查询的重要区别。
条件查询
函数(组函数=聚合函数<结果集唯一>)count(*)sum()min()max()avg()like'%5%'
使用?
方式传递参数参数索引从0开始,传递的参数值不用单引号引起来,注意方法链变成
预处理:
session.createQuery("select?
").setParameter(0(第一个问号),"。
。
。
").list();有几个问好setParameter几次
动态参数的绑定及赋值:
(select...from...wherelike:
username).setParamter("username",...)
支持in,需要使用detParameterList进行参数传递
(select...from...wherein(:
username).setParameterList("username",newObject[]{1,2,....})
数据库底层函数有很多种