zoukankan      html  css  js  c++  java
  • hibernate的实现原理以及延迟加载

    Hibernate是怎样实现呢?主要是依据反射机制。

          现在以一次数据库查询操作分析Hibernate实现原理。

          假设有一个用户表(tbl_user),表中字段有id,name,sex。同时有一个实体类(User)与其相对应,查询语句是:  select * from User。

    1.在项目启动时,Hibernate配置文件中的内容已经存储在容器中,存储着表与实体中的关系。

    2.在执行select * from User 时,会根据反射机制先找到User的全路径名称,进而找到容器中User对应的配置。

    3.由于配置文件中的实体属性与数据库中的字段是对应的,Hibernate会将select * from User 这个hql语句根据不同的数据库方言解析成不同的SQL语句(select * from tbl_user)。

          大致过程就是这样,当然,器内部实现的具体过程是比较复杂的,在使用Hibernate进行数据库操作时,应注意级联、延迟加载、缓存的使用。

                

    简单来说就是,利用反射原理,将实体类中的字段按照xml配置或者annotation解析成一条或者多条sql语句,然后放入数据库执行,说的简单点,就是这么个原理,但是内部实现比较复杂.

    原理:

    1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件

    2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息

    3.通过config.buildSessionFactory();//创建SessionFactory

    4.sessionFactory.openSession();//打开Sesssion

    5.session.beginTransaction();//创建事务Transation

    6.persistent operate持久化操作

    7.session.getTransaction().commit();//提交事务

    8.关闭Session

    9.关闭SesstionFactory

    这个就是原理,不是流程。主要就是一个基于JDBC的主流持久化框架,一个优秀的ORM实现,对JDBC访问数据库的代码做了封装,很大程度上监护了DAO层的编码工作。

    hibernate缺点:

    总的来说,hibernate的缺点主要有以下几点:

    一、由于对持久层封装过于完整,导致开发人员无法对SQL进行优化,无法灵活使用JDBC的原生SQL,Hibernate封装了JDBC,所以没有JDBC直接访问数据库效率高。要使用数据库的特定优化机制的时候,不适合用Hibernate 

    二、框架中使用ORM原则,导致配置过于复杂,一旦遇到大型项目,比如300张表以上,配置文件和内容是非常庞大的,另外,DTO满天飞,性能和维护问题随之而来

    三、如果项目中各个表中关系复杂,表之间的关系很多,在很多地方把lazy都设置false,会导致数据查询和加载很慢,尤其是级联查询的时候。

    四、Hibernate在批量数据处理时有弱势,对于批量的修改,删除,不适合用Hibernate,这也是ORM框架的弱点

    Hibernate是ORM框架(object-relation maping对象关系映射),它是用来实现JDBC的功能,但是它不能替换JDBC,它是在JDBC基础上实现的,即Hibernate中已经把JDBC封装了,最终的代码是到HIbernate在传递到JDBC在于数据库交换,所以性能没有JDBC直接与数据库交互快.

    延迟加载:

    一.什么是懒加载?他的作用?

    延迟加载,也叫懒加载,它是Hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。

    Hibernate中主要是通过代理(proxy)机制来实现延迟加载。它的具体过程:Hibernate丛数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据,hibernate并不是数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都是默认值;只有在真正需要使用该对象的数据时才创建这个真实对象,真正从数据库中加载它的数据,这样在某些情况下,就可以提高查询效率。

    有如下程序代码:

    User user=(User)session.load(clazz, id);//直接返回的是代理对象

    System.out.println(user.getId());//没有发送sql语句到数据库加载

    user.getName();//创建真实的User实例,并发送sql语句到数据库中

    注意:1.不能判断User=null;代理对象不可能为空

    代理对象的限制:和代理关联的session对象,如果session关闭后访问代理则抛异常。session关闭之前访问数据库

    2.getId()方法不行因为参数为ID,getClass()方法不用访问数据库就可以得到的数据

    Hibernate中默认采用延迟加载的情况主要有以下几种

    1,当调用session上的load()加载一个实体时,会采用延迟加载。

    2,当session加载某个实体时,会对这个实体中的集合属性值采用延迟加载

    3当session加载某个实体时,会对这个实体所有单端关联的另一个实体对象采用延迟加载。

    二.关闭延迟加载

           延迟加载确实会给程序的查询效率带来好处,但有时明确知道数据需要立即加载,如果Hibernate先默认使用延迟加载,而后又必须去数据库加载,反而会降低效率

    1.     加载单个实体,如果不需要延迟加载,就可以使用session的get()方法。

    2.     当session加载某个实体时,不需要对这个实体中的集合属性值延迟加载,而是要立即加载。这是可以在映射文件中这个集合的配置元素(set bag list)添加属性lazy=false;

    3.     当session加载某个实体时,不需要对这个实体所单端关联的另一个实体对象延迟加载,就可以在影射文件中针对这个单端关联的配置元素(<one-to-one><many-to-one>)添加lazy=false;

    能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。

  • 相关阅读:
    Excel中substitute替换函数的使用方法
    如何在Excel中提取小数点后面的数字?
    提升单元测试体验的利器--Mockito使用总结
    SpringMVC项目读取不到外部CSS文件的解决办法及总结
    java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
    Spring-data-redis操作redis知识总结
    优雅高效的MyBatis-Plus工具快速入门使用
    Thrift入门初探(2)--thrift基础知识详解
    Thrift入门初探--thrift安装及java入门实例
    spring事件驱动模型--观察者模式在spring中的应用
  • 原文地址:https://www.cnblogs.com/hadoop-dev/p/8274497.html
Copyright © 2011-2022 走看看