我的java框架学习笔记hibernate复…

来源:互联网 发布:pandorabox建站 编辑:程序博客网 时间:2024/06/05 18:01
这个hibernate的框架主要是看黑马黎活明老师(现任传智播客CEO)的视频,不愧是资深的系统架构师,把EJB引入中国,国内最早期android学习视频录制教学者,虽然没有面授过,但是在黑马,黎老大的名声还是很想的,不得不说他的普通话很不标准,但是丝毫不影响他讲课的深度,讲一遍自己敲一敲代码都能出来的。。不多说,直接贴代码:
  #初级入门: 开发一个hibernate的完整步骤:

1 首先配置好hibernate.cfg.xml配置文件,就像struts.xml配置文件一样;

2新建一个Java类。即一个JavaBean,用于接收数据库中数据,封装进该javabean中;

3为该javabean配置映射配置文件;将该javabean与数据库中的关系配置下;

4 hibernate.cfg.xml中加入映射文件配置项;

记住javabean必须要满足Javabean中的条件,即要有缺省得构造方法;

其次最 好要在该javabean中要设置一个id号,作为数据表的主键,更好的发挥Hibernate的特性;

而且javabean不能定义为final;否则不能实现懒加载特性;

为什么呢?因为所谓的懒加载就是说他会给我们创建一个该类的子类对象,无论有没有查到,我们要的对象时存在的,但是对象中没有数据;有可能会抛出懒加载异常;

而被定义成final,就不能有子类;


 在我们要用到Hibernate的类中该怎么使用呢?

1 Configuration对象创建,记住要是hibernate包中的;

2 cfg.config();加载配置文件;

3 产生SessionFactory对象,从cfg.buildSessionFactory();中获取;使用的是工厂设计模式;

这个类类似于JDBC的驱动类;

4 取得Session对象通过SessionFactory对象获取;factory.openSession();类似于jdbc中的Connection

5 获得并打开事务处理对象;Transactionaction=session.beginTransaction();

action.begin();

6创建对象,并设置相应字段属性的值;

7然后保存该对象;session.save(obj);

8提交事件;action.commit();

9关闭session


工具类我们一般都是写成final的,不希望别人来继承他;

一个员工只能属于一个部门,而一个部门有许多员工;

从部门方面来说,一个部门有多个员工,即一对多;

而从员工来说,多个员工对于一个部门,即多对一;

从映射关系来讲:一个部门对应多个员工,即员工可以定义成一个集合,

该集合是员工的集合,(使用泛型);作为部门类的成员;

映射配置文件应该这样:

 

 

 

 

多个员工对应一个部门,即多对一,将部门定义为员工类的成员;

映射配置文件应该这样:

 

配置一对一映射关系文件该这样;不妨假设Person为主表;IdCard为从表;

Personid是自己的主键,也是IdCard的主键;

person.hbm.xml:

其他类似;主要是这点;

 

IdCard.hbm.xml

 

 

person

 

 

 

其他一样

Hibernate中使用查询语句时,如果仅仅是为了查询数据库时,不涉及到修改数据库,则可以不用

开启事务,因为不涉及到数据的修改;

学习Hibernate如何处理对象之间的关联关系的底层细节时,可以从两方面去思考:

1如何将对象之间的关系保存在数据库中

2如何检索出关联的对象!!!

Hibernate的检索策略:

1立即检索

  lazy属性设置为false

在类级别上,一般采用立即检索,因为在加载了持久化对象后会立即使用它;

当在关联级别上也使用立即加载时,为了减少查询次数,可以采用Hibernate的批量检索功能;

即在标签上设置batch-size属性设置大小;因为如果不设置批量检索的话,有多少个关联对象就会产生多少次查询语句;而设置了批量检索,则只会产生一条查询语句;即

select * from  user where id=1;

select * from user  where id=2;

......不使用batch-size

select * from user where id in(1,2,..);

同时不管class标签的lazy的属性设置为何值,也就是说不管类级别启用何种检索策略;

当使用Session实例的get方法时,都是立即加载;

总上所述:在类级别上推荐使用立即加载,而在关联级别上推荐使用延迟加载;如果不考虑类级别采用何种检索策略,

且想立即检索持久化对象时,可以使用Session实例的get方法实现;


2延迟检索

 lazy属性设置为true

在关联级别上,一般采用延迟检索,因为在加载了持久化对象后大多不会立即访问其关联对象,况且当关联对象数量巨大时,

将其装载入内存开销也很大,这是开发高效Hibernate应用所需注意点地方;

延迟检索是hibernate3.0的默认检索策略;所谓延迟检索策略就是等到要访问的时候才装载和初始化指定的对象,





如果是在Session实例关闭之前没有初始化延迟检索出来到对象,Session实例关闭后在访问时,就会抛出异常,

因此启用了延迟检索策略后在访问指定对象前应确保其已被成功初始化;

为了确保延迟检索的对象在Session关闭后仍然能够被正常访问,可以使用HibernateisInitialized(Objectobj);

判断是否被加载,然后在调用Initialized();方法加载指定对象!!


3迫切左外连接检索;

 就是充分利用SQL的外连接查询功能,减少select语句的数量,提高检索效率;在Hibernate中要使用迫切左外连接检索策略,

 只需将所属标签outer-join属性设置为true即可实现;

同时值得注意的是,当使用session.createQuery("from.....").list();查询所有的对象时,迫切左外连接检索;将被忽略,即不生效,有lazy属性决定!!!

HQL查询:

1当只检索对象的部分属性时,Hibernate返回的不是持久化对象,而是关系数据,这些数据不被Session实例缓存,

因此可以被JVM垃圾回收机制回收;大大提高了查询的性能,减少了内存资源的消耗!!!

部分使用HQL查询语句:

1 使用其内置函数selectcount(*),sum(user.money),avg(user.age),min(user.age) from User asuser;

同时使用list方法可以取得上面四个所需的函数结果值;

Iteratoriteratoy=query.list().iterator();

2条件查询:

 from User as user where user.usernamelike:username and user.nickname=:nickname;

 like---包含某个字符的

 

 from User as user where user.age>20 anduser.nickname is not null;

 is not null----不为空;

  

  from User as user where(user.age between 10 and30) and user.username in(:name,:name2)

  

  from User as user where user.id like'1%'  and user.nickname like 'li_'

 %%_都表示占位符;

  

  select distinct user.username form User asuser;

 过滤重复内容!!!

3分页查询

  session.setFirstResult(index); 从哪个对象开始,默认为0,即id号从几开始;

  session.setMaxResults(number);//设置每次查询最多查多少个;


 一般配置文件中的属性名与bean中的属性名不一致时,会出现致命的异常错误;



Configuration 用于初始化Hibernate,他可以提供数据库的链接等等

config.config();

config.buildSessionFactory();

session类似于JDBC中的connection

数据库的表结构,一般都是innodb引擎;他支持事务;

session中有些方法是可以用来持久化某个类的;比如saveloadget等等

需要注意的是这些对象的所处的状态:

User.class 可以这样写,说明classUser对应的字节码类中的一个非私有静态成员;

关于Hibernate的底层原理:

1 首先我们必须给Hibernate提供相应的配置文件,取名按照其命名规范hibernate.cfg.xml

这个配置文件中包括数据库的连接信息包括方言,驱动类所在的位置等等;同时包括需要被持久化层操作的

类或者说bean对象的映射文件,一般都是跟bean在同一个路径下;

2当我们要使用其用来保存或者获取某个bean对象时,对于我们程序员来讲我们操作的是一个个的Bean

由于我们对这个bean进行了描述(映射文件);当我们调用Hibernate的增删改查的方法时,Hibernate根据我们给出的

数据库驱动类,来生成相应的数据库查询语言,由于Hibernate内部是对JDBC进行了封装,所以他对数据库的操作很清楚,而我们

程序员可以对数据库语言不熟悉,只要了解掌握了Hibernate就可以了。其他的就交给Hibernate去处理,这样有很大的好处,比如说

当某个公司的底层数据库换了,他只要改变相应的数据库驱动类就可以了原来的dao层无需改动,而如果不采用持久层框架的做法

即,直接面向数据库编程时,写出来的dao层使随着数据库走的,数据库换了,dao层得跟着换;



其底层执行的流程是

1采用configure();方法对配置文件进行加载和解析,底层采用的dom4j技术解析,将解析出来的数据库信息传递给创建数据库连接的类

从而连上数据库,当然这底层必然使用了反射技术,同时如果有配置了映射文件就对映射文件进行解析,当程序员调用到增删改查

的方法时,根据对配置文件进行解析和数据库类型及版本的判断产生相应的数据库查询语句,然后跟数据库打交道;返回的数据(如果有的话)

一般都是一个个的对象,这也是根据映射文件来的;

在增删改查的过程中,如果需要事务的,自行开启;

如果我们在配置文件中配置了自动创建表时,hibernate也会给我们创建表;



HibernateTemplate:采用的是模版方法设计模式和策略模式来实现相同代码的抽象封装与提取,提高代码的复用性;


JTAJavaTransaction ArchitectureJava事务体系架构;

实现跨数据库的事务管理;


session:生命周期比较短,一般都是一个请求的生命周期;非线程安全的,底层对jdbcconnection进行封装;

一个session对应一个connection

SessionFactory:线程安全,对应一个数据库;一般在整个系统生命周期内有效;底层封装了一个

数据库连接池;

hibernate不适合的地方:

1 不适合OLAPOn-LineAnalytical Processing联机分析处理,以查询分析数据为主的系统;适合OLTPon-linetransaction processing :联机事务处理;

2对于一些关系模型设计不合理的老系统,也不能发挥hibernate优势。

3数据量巨大,性能要求苛刻的系统,hibernate也很难达到要求,批量操作数据的效率也不高。


最佳实践:

细粒度的持久类;

映射最好是双向的,最好是一对多和多对一;

事务:

全局事务:JTA,涉及多个数据库的链接与操作;

本地事务:针对只涉及一个数据库;

JTA:实现全局事务的原理是一个二次提交协议;具体来说就是

JTA:有一个事务容器,List,各数据库的某个事务完成并提交,其实是提交给这个List集合;

并且这个集合中真对某个事务是否提交成功有一个boolean值记着,一旦有哪个事务提交不成功则

该集合所有的事务都不成功,所有的操作都要回滚;

也就是我如果我们开启JTA全局事务,我们提交时,其实是提交给JTA,由它来统一管理我们的事务;

只有所有的事务都提交给JTA并且都成功的话,JTA才会真正的提交给数据库,来完成数据库的操作;

一对多的情况:多的一方为关系维护端,负责外键字段的更新;


0 0