`
cloudtech
  • 浏览: 4610334 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

、 只要openSession一次,hibernate内部就会连接数据库一次,所以在代码中opesnSession的次数,越多效率越低

阅读更多

Hibernate课堂笔记

1Hibernate是什么

Hibernate是一个数据库的操作框架

1.1Jdbc的缺点

ljdbc的效率比较低

每一次请求,打开连接、发送sql语句,在数据库中解析sql语句等需要消耗大量的资源。

重复性代码特别多

每一次都需要关闭connection,statement,rs

Jdbc没有做到面向对象编程

没有做到数据缓存

现在世界上数据缓存做的很不错的框架(hibernate,oscache,ehcache)

Oscacheehcache都有页面缓存

*就是把页面上的数据缓存到本地磁盘上

*当应用程序再次访问的时候,直接从磁盘上读取数据就

可以了

*页面缓存不适合做更新特别频繁的数据

1.2Jdbc的优点

是最底层的操作数据库的框架,所以在java的层面上说速度最快

Jdbc做到了connectionpool

1.3Hibernate优点

l面向对象编程

lHibernate的底层也是由jdbc实现的

lHibernate的数据缓存做的相当棒

lHibernate做到了connectionpool

1.4Hibernate缺点

Hibernate不会让程序员干涉sql语句的生成,sql语句是hibernate内部操作jdbc生成的,所以在一个项目中,如果对sql的优化要求比较高,这个时候,不适合用hibernate

如果一张表的数据量特别大(千万级别以上),也不适合用hibernate

2Hibernate的学习内容

l学习hibernatecrud操作

l持久化对象的状态

l一对多和多对多(重点)

l数据缓存(一级缓存、二级缓存、查询缓存)(重点)数据缓存的特点

lHql语句

3hibernatecrud操作

3.1类与表的映射关系

3.2Hibernate配置文件的加载方式

3.2.1方式一

注意:

1、配置文件的名称必须是hibernate.cfg.xml

2、把hibernate.cfg.xml文件必须放在classpath

3.2.2方式二

注意:

1、利用该方法配置文件的名称可以随意写

2、路径可以随意放

3、Resource代表路径名称+文件名称

注意:hibernate的事务默认不是自动提交的

3.3crud操作注意事项

3.3.1session.get方法

1、要使用session.get方法,那么相对应的持久化类中必须保证有一个无参的构造函数

2、该方法的第二个参数与持久化类中的主键的类型要保持一致。

3、Session.get方法的第二个参数的形参:Serializable.因为只有这样才能接受所有的数据库的主键的类型

3.3.2session.update

参数可以是session.get方法得到的对象,也可以是新创建的对象,但是cid的值必须和数据库的值相对应。

4Hibernate流程

5sessionFactory

1、sessionFactory中存放配置文件和映射文件的所有的信息

2、一个数据库有且仅有一个sessionFactory

3、sessionFactory是一个单例的对象

4、sessionFactory是一个重量级别的类,只加载一次

5、sessionFactory是一个线程安全类

6主键的生成机制

考虑hibernate主键的生成机制可以从三方面去想:

客户端

Hibernate内部可以生成主键

数据库内部的机制生成主键

6.1Incrment

1、获取主键的最大值,然后加1

2、主键的类型必须是数字类型

3、第一步的过程是由hibernate内部做的

4、发出selectmax(cid)fromClasses这样的sql语句,所以效率比较低

5、主键的值是连续的

6.2Identity

1、适用于数字类型

2、数据库表本身的自动增长

3、主键是在数据库内部生成的

4、表必须得设置为自动增长

6.3Assigned

由程序员自己设置生成

6.4Uuid

hibernate内部生成一个唯一的字符串

7Hibernate类型

Hibernate内部实现了从java类型到数据库类型的映射,所以在映射文件中选择java类型比选择hibenate类型效率要高

8对象的状态

对象的状态的定义

临时状态的对象:刚创建的对象

持久化状态的对象:该对象和session已经发生交互了

脱管状态的对象:由和session的交互变为和session的脱离

8.1案例1

说明:

1、第39行代码发出了update语句

2、在执行第36行代码的时候,利用session.get方法提取出来一个对象,该对象是持久化状态的对象

3、处于持久化状态的对象不用执行session.update方法

4、session.save和session.update方法都是把一个对象的状态变成持久化状态

8.2案例2

说明:

1、在执行40行代码的时候不会发出update语句,因为修改后的数据和原来的数据是一样的。

2、在hibernate内部,会生成该对象的一个镜像文件,在执行update方法的时候,

会查看镜像文件,如果一致,则不执行update,如果不一样才要执行update语句

8.3案例3

说明:

1、第51行代码把classes对象由临时状态转变成持久化状态

2、在第53行代码之前不用执行session.update方法

8.4案例4

说明:

159行的session67行的session是两个session

261行产生的classes67行产生的session直到程序结束没有发生关联

3、一个对象是否是持久化对象是针对一个session而言的

8.5案例5

分析:

1、当执行82行代码的时候,把classes从持久化状态的对象转化成脱管状态,这个时候和session没有关联了

2、在执行84行代码的时候没有执行update语句

3、要想执行update语句,必须使classes成为持久化状态的对象,所以执行update方法

8.6对象状态转化图

说明:

只有持久化状态的对象才能和session发生交互

9Hibernate对象关系

研究:

1、crud的操作

2、外键(面向对象:关系)

9.1一对多单项

9.1.1Cascade

1、cascade只能出现在多表中

2、针对一对多的情况

在保存或者更新classes的时候,针对student应该做什么样的操作

9.1.1.1案例1

分析:因为classesstudent都是临时状态,所以应该是在保存classes的同时保存student

9.1.1.2案例2

分析:

1、因为在客户端和在映射文件中都有设置级联,所以cascade是起作用的

2、在上述代码中,因为classes的一般属性并没有发生改变,所以针对classes不会发出update语句

3、因为classes的集合发生改变了,而且级联起作用,所以hibernate内部会去检查classes中的集合的状态,因为集合中多了一个数据,所以增加了一个student

4、级联操作是对象与对象的操作

9.1.1.3案例3

当提交的时候,因为是级联操作,因为对student的一般属性发生了改变,所以在更新classes的时候更新了student

9.1.1.4总结

1、级联是对象与对象之间的操作,和关系无关

2、对一个对象进行操作的同时,怎么样操作级联对象,看级联对象是否是持久化对象(看级联对象对应数据库是否有数据),如果是持久化对象,则执行update操作,如果是临时状态的对象,则执行insert操作

9.1.2Inverse

对象对关系是否维护

上述的图的意思为Classes是否要维护student表的关系(外键),如果inversefalse,则维护,如果为true,则不维护

9.1.2.1案例1

分析:

1、该例子从数据库的角度分析,把sid2的值的外键修改一下就可以了

2、从hibernate的角度是修改关系

3、查看classes.hbm.xml映射文件中,classes能否修改classesstudent之间的关系。

4、因为关系的修改就是一个update操作而已,所以没有必要解除关系。

5、第136行代码是从classes端维护关系。如果从student端维护关系,那

代码应该是student.setClasses();

9.1.2.2案例2

分析:

1、根据映射文件可以得出classes维护关系

2、在对classes进行删除、增加、修改的时候同时要操作student

3、因为classes负责维护关系,所以在删除掉classes之前,hibernate内部会自动执行解除所有的关系的操作

9.1.2.3案例3

分析:

1、解除班级和所有学生之间的关系实际上就是把classes中的集合清空。

2、Classes.setStudents(null)这个时候hibernate内部会直接把关系设置为null,效率最高,根本不需要去查student

9.1.3总结

1、因为是一对多的单项,所以只能是classes维护关系

2、Classes维护关系,所以客户端的代码应该是通过classes对关系进行建立或者解除

3、只要涉及到关系的操作就得发出update语句,用来更新关系。所以用classes维护关系效率并不高

4、一对多,用一的一方维护关系,效率比较低。当数量级别比较大的时候,会发出nupdate语句

9.2一对多的双向

9.2.1案例1

分析:

1、通过映射文件可以看出,在Student.hbm.xml文件中,不存在外键,意味着如果通过student建立与classes的联系,在hibernate内部是做不到。

2、Student.getClasses会报空指针异常,得不到,因为没有联系

3、通过classes操作student,看classes.hbm.xm文件,通过student操作classes

student.hbm.xml文件

4、所以在classes.hbm.xml文件和student.hbm.xml文件中都必须体现外键

9.2.2案例2

分析:

1、通过代码34行可以得出是通过student联系classes,所以看student.hbm.xml

2、35行代码是保存学生,因为在34行代码中通过student建立了与classes之间的关系,所以在插入学生的同时,在hibernate内部自动维护了关系

3、用学生端维护关系,不需要发出update语句

4、一对多,多的一方维护效率比较高

9.3多对多

9.3.1学习重点

1、映射文件的创建和持久化类的创建

2、关系

说明:

1、关系的操作

建立关系就是在第三张表中插入一行数据

解除关系在第三张表中删除相应的一行数据

改变关系

1、修改相应的行的数据

2、先删除再增加

3、多对多谁维护关系效率都一样,都得对第三张表发出相应的SQL语句

9.3.2练习

9.3.2.1案例1

分析:

1、因为要级联,因为是通过course级联,所以在course.hbm.xml文件中,针对set集合,应该设置cascade属性

2、因为多对多谁维护关系效率都一样,所以在两个映射文件中都维护关系

3、第53行代码,即级联又维护关系

9.3.2.2案例2

分析:

1、经过需求分析可以得出应该是修改学生和课程之间的关系

2、因为在学生类中存在的是课程的集合,而课程类中存在的也是学生的集合

3、集合不存在修改,所以修改关系就等于先解除后增加

4、通过哪个端修改关系都可以,但是要统一

10性能

10.1懒加载(延迟加载)

概念:需要时加载

10.1.1 类的懒加载

分析:

1、利用session.load方法就是类的延迟加载

2、利用session.load方法产生的是代理对象,利用session.load方法的出来的对象只有id值(标识符属性)

3、当得到具体的属性的时候才要发出sql语句

4、类的延迟加载只针对一般属性有效

5、必须在session关闭之前把数据提取出来

10.1.2集合的懒加载

分析:

1、集合的懒加载,只有在根据一的一方加载多的一方的情况下才要讨论这种情况

2、如果采用默认的加载方式,就是集合的懒加载

3、在遍历集合的时候才要发出sql语句

4、如果在set元素中lazyfalse

1、在执行31行代码的时候,发出两条sql语句

第一条查询的是classes

第二条查询的是根据cid查询student

5、集合的懒加载还有一个值为extra,更进一步的懒加载

分析:因为不需要加载student的属性,只需要一个函数的结果,所以就发出了上面的sql语句

10.1.3单端关联的懒加载

因为单端关联只加载一个数据,所以用默认情况做就可以了

False/proxy(true)/no-proxy

10.2抓取策略

根据一方怎么样提取关联端

根据一的一方怎么样提取多的一方

根据多的一方怎么样提取一的一方

10.2.1方式

前提条件:针对集合

懒加载

抓取策略

Sql语句

True/false/extra

Join(子查询除外)

发出一条,把所有的数据全部加载了

True/false/extra

select

在遍历集合的时候才要发出sql语句,这个时候发出n+1sql语句/在加载classes的时候就把student的数据加载出来了/extra在这里等同于true

True/false/extra

subselect

如果检测到由子查询,则用subselect

说明:

1、如果第一页面只有一的一方的数据,然后根据超级连接才要显示多的一方的数据,这种情况用select或者subselect

2、如果页面上既有一的一方的数据也有多的一方的数据,用join是比较好的选择。

1select默认的

1、先查询班级(cid:1,2,3)

2、根据班级中的每一个cid去查相应的学生

2subselect子查询

根据需求分析先写出sql句,只要sql语句中含有子查询,那么肯定是子查询的效率比较高

3join连接

1、如果根据需求分析,得出的sql语句含有子查询,这个时候用join(左外连接)

不起作用

3、如果没有子查询,则利用join的方式(左外连接),就可以一次性的把一和多的数据全部查询出来

10.3懒加载与抓取策略的结合

10.4Session

10.4.1Session的产生方式

10.4.1.1openSession

分析:

1、只要代码中遇到sessionFactory.openSession,那么在hibernate内部就会新创建一个session

2、只要openSession一次,hibernate内部就会连接数据库一次,所以在代码中opesnSession的次数,越多效率越低

3、只要执行sessionFactory.openSession一次就会产生一次连接

4、Hibernate中的事务是依赖session

5、最好一个方法只有一个session

10.4.1.2currentSession

分析:

1、在特别复杂的项目中,一个service方法可以操作很多内容,而这些内容有可能涉及到很多框架,而框架对于hibernate的操作对于程序员来说是不可见的

2、但是要想使上面的service方法运行成功,必须在一个事务环境下运行

3、要想在一个事务环境下运行,必须只有一个session

4、把当前线程绑定到session是一个特别好的解决方案

注意:

只要用到当前线程产生的session,crud操作必须在事务的环境下运行

当前线程的session还和事务绑定,这样可以提高安全性能

当事务提交的时候,当前线程中的session关闭了

用当前线程产生的session,不需要手动关闭session

配置方式:

hibernate.cfg.xml文件中

在代码中利用sessionFactory.getCurrentSession就可以实现了

10.4.2Session的生命周期

10.4.3Session中的缓存

10.4.4安全

说明:

1、不同的客户端访问有不同的线程,不同的线程就有不同的session,特定的数据在特定的session

2、一个数据只能让一个客户端拥有

3、把session绑定到当前线程中解决了session中数据线程安全的问题

11Hibernate错误分析

11.1错误一

分析:

l在配置文件中加载该文件,但是路径写错了,找不到

l该文件根本没有加载到配置文件中

11.2错误二

分析:

当生成sql语句的时候,利用get方法获取值,这个时候,需要映射文件中的name属性拼接成get方法,然后利用java的反射机制赋值,拼接的时候出错了,所以属性找不到。

11.3错误三

分析:说明持久化没有找到,持久化类没有找到并不一定意味着该类不存在,有可能映射文件路径写错了

以上两个错误结合一起,就是总结出:

在映射文件中,class元素的name属性的值写错了

11.4错误四

hibernate的配置文件中,映射文件的路径写错了

11.5错误五

分析:

1、有可能在映射文件中,class元素的name属性的值写错了

2、在客户端session.save进行操作的时候,因为操作的是持久化对象,所以该对象所在的类必须是映射文件中class元素的name属性,如果不一致,也会报这样的错误

11.6错误六

分析:

Session.get方法两个参数,第二个参数的类型必须与持久化类中的主键的类型保持一致。

11.7错误七

分析:

表本身默认的值,没有支持自动增长

11.8错误八

客户端截图:

分析:根据64行代码可以判断出classesstudents建立关联

映射文件:Classes.hbm.xml

总体分析:

1、把session.save(classes)这样的保存称为显示保存

2、在保存classes的同时保存student,保存student的操作是由hibernate内部完成的,我们把这样的操作称为隐式保存

3、在classes.hbm.xml文件set元素中并没有配置cascade

4、只有在客户端建立classesstudent之间的关系,然后在映射文件中再次确认关联(cascade)两个地方都配置了,级联保存才能有效

5、因为在classes.hbm.xml文件中,没有针对studentcascade,所以student对象处于临时状态,hibernate是不允许这种情况出现的

6、这个错误只有在多表的情况下才有可能产生

11.9错误九

session关闭以后还要视图从数据库中提取数据就会报这样一个错误。

解决方案:

session关闭之前把数据全部提取出来

分享到:
评论

相关推荐

    hibernate操作数据库笔记

    //该方法会立即加载/获取数据(只要调用该方法就会立即向数据库发出查询语句),该方法只在内部缓存查找数据,如果内部缓存中没有数据就直接去数据库查询,当数据库中没有要查询的数据时返回null (6).load(Class ...

    hibernate精华教程

    1)配置环境,加载hibernate的jar文件,以及连接数据库连接使用的jar文件,并配置CLASSPATH环境变量。 2)写POJO类(普通的java类) 3)写hibernate所需的配置文件,hibernate.cfg.xml ,Xxxxx.hbm.xml 4)调用...

    Hibernate3使用经验

    ---------------Hibernate3.0 配置-------------- 1.Hibernate中配置参数 /** * 注意:HQL中使用参数的方法: * 1.根据参数名称来设置参数:匹配名称; * 2.根据参数位置来设置参数:匹配位置; */ //根据参数名称来...

    Hibernate1

    对 Hibernate 初体验 1.新建一个java工程,...但运行上面的测试类之后,我们查看一下数据库中student表,表中将会多一条数据。 Hibernate的初体验就说到这,相信通过上面的例子,我们对hibernate大致有了一些了解了。

    hibernate实现分页查询

    hibernate 分页查询的实现 hibernate 内置的有分页功能 有三个参数 thisnumber一个是当前页数 sumcount是一页显示多少条数据 sql是用来查询的sql语句 public List getPageList(int thisNumber, int sumCount, ...

    hibernate session.doc

    delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一...

    hibernate 学习笔记

    hibernate 学习笔记: 了解hibernate的基本概念 配置hbm.xml cfg.xml 快速入门案例3: 从domain-xml-数据库表 hibernate的核心类和接口 openSession()和getCurrentSession() 线程局部变量...在web项目中开发hibernate

    Spring4.0+Hibernate4.0+Struts2.3整合案例

    1、Spring 3.x 对 Hibernate 4.x 不提供 HibernateDaoSupport,所以在dao的实现层注入SessionFactory 2、报错:org.hibernate.HibernateException: No Session found for current thread 意思是必须在...

    struts2.3.x+spring3.1.x+hibernate3.6 demo

    十分抱歉,上次整合的是一个半成品,spring3.1和hibernate4.1目前为止我测试了,整合过程中有很多问题!关键问题有几个,第一个HibernateDaoSupport这个没有了,在使用hibernateTemplate的时候,报错误:java.lang....

    SessionFactory.getCurrentSession与openSession的区别

    博文链接:https://shaqiang32.iteye.com/blog/201918

    springmybatis

    sessionFactory 用的,里面主要包含了数据库连接相关东西,还有 java 类所对应的别名,比如 <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 这个别名非常重要,你在 具体的类的映射中,比如User...

    hibernate经典文档

    hibernate 经典文档,学习hibernate 必备的文档,深入浅出,非常实用,强烈推荐!

    Springboot调用Oracle存储过程的几种方式.docx

    将项目中部分需要调用存储过程的部分用entityManagerFactory.unwrap(SessionFactory.class).openSession()来获取Session实现后发现项目访问数据库超过十次就会挂掉,原因是Springboot连接池数量默认为10,猜测是每次...

    J2EE利用Hibernate采用B/S架构网页设计

    sessionFactory.openSession() : null; threadLocal.set(session); } return session; } /** * Rebuild hibernate session factory * */ public static void rebuildSessionFactory() { try { ...

    无垠式代码生成器最新功能与文档增强版0.7.22

    1)增加代码自动保存功能,在代码生成物中含有sgs文件夹,内有以 <项目名>_original.sgs命名的生成生成物的SGS源码。 2)增强SGS编译器,使其支持call magic魔法语句,自动生成棱柱列表,便利开发。 3)增强修复S2SH...

    Hibernate查询语言

    如果要将很多对象持久化,你必须通过经常的调用 flush() 以及稍后调用 clear() 来控制第一级缓存的大小。 Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( ...

    NHibernate中的Session示例源代码

    NHibernate中的Session示例源代码,适合对NHibernate的使用有一定的了解,并想了解NHibernate源代码及其软件结构的人。

    Hibernate3.2.6ga 支持Session修改Schema

    修改Hibernate3.2.6ga可以动态通过Session设置Schema Session session=sf.openSession(); session.setSchema("SchemaName"); session.save........ ....... .......

    Java常见面试题208道.docx

    123.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么? 124.hibernate 实体类必须要有无参构造函数吗?为什么? 十三、Mybatis 125.mybatis 中 #{}和 ${}的区别是什么? 126.mybatis 有几种分页方式...

    Java面试宝典2020修订版V1.0.1.doc

    13、在数据库中查询语句速度很慢,如何优化? 44 14、数据库三范式是什么? 44 15、union和union all有什么不同? 45 16、char、varchar2、varchar有什么区别? 45 17、Oracle和Mysql的区别? 46 18、Oracle语句有多少...

Global site tag (gtag.js) - Google Analytics