Jdbc&Hibernate&MyBatis&IBatis

来源:互联网 发布:中央电视10套网络直 编辑:程序博客网 时间:2024/05/18 23:26

1.Hibernate工作原理

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

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

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

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

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

  6.persistent operate持久化操作

补充说明:

  1.瞬时态 持久态  托管态

  2.load()和get()的区别

    区别1:如果数据库中,没有userId的对象。如果通过get方法加载,则返回的是一个null;如果通过load加载,则返回一个代理对象,如果后面代码如果调用user对象的某个属性(比如user.getPassword())会抛出异常:org.hibernate.ObjectNotFoundException;

     区别2:load支持延迟加载,get不支持延迟加载。

  3.save()和saveUpdate()区别

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

  8.关闭Session和SesstionFactory

2.Hibernate优势

  1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。

  2.Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作

  3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。

  4.hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

3.Hibernate性能优化

    大体上,对于HIBERNATE性能调优的主要考虑点如下:

  1)数据库设计调整:a) 降低关联的复杂性b) 尽量不使用联合主键 c) ID的生成机制,不同的数据库所提供的机制并不完全相同 d) 适当的冗余数据,不过分追求高范式

    2)API的正确使用(如根据不同的业务类型选用不同的集合及查询API)

  3)HQL优化:1.建立索引;2.sql优化;

1.少用通配符;2.不用模糊查询,少用%开头,如果以它开头,索引就会失效;3.不用not in,not exits,<>;5.使用where子句过滤行;

6.索引;7.使用where不是having;8.使用unionall而不是union;9.使用exits而不是in;10.使用exits而不是distinct。11.建立视图  

 相关补充:如何看待where 1=1

优点:where 1=1;这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句。

缺点:因为添加了"1=1"的过滤条件以后数据库系统无法使用索引等优化查询策略,数据库系统将会被迫对每行数据进行扫描(也就是全表扫描)来比较此行是否满足顾虑条件,当表中数据量比较大的时候查询速度会非常慢。 

where 1=0可以用于快速建立表结构。

   4)主设置参数(日志,查询缓存,fetch_size, batch_size等)

      a)查询缓存,同下面讲的缓存不太相同,他是针对HQL语句的缓存,即完全相同的语句再次执行时能利用缓存数据。不过,查询缓存在一个交易系统(数据变更频繁,查询条件相同的机率并不大)中可能会起反作用:他会白白耗费大量的系统资源但却难以派上用场。

      b)fetch_size,同JDBC的相关参数作用类似,参数并不是越大越好,而应根据业务特征去设置

      c) batch_size同上。

      d) 生产系统中,切记要关掉SQL语句打印。

  5)映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)

      a)数据库级缓存:这级缓存是最高效和安全的,但不同的数据库可管理的层次并不相同,比如,在ORACLE中,能在建表时指定将整个表置于缓存当中。

      b) SESSION缓存:在一个HIBERNATESESSION有效,这级缓存的可干预性不强,大多于HIBERNATE自动管理,但他提供清除缓存的方法,这在大批量增加/更新操作是有效的。比如,同时增加十万条记录,按常规方式进行,非常可能会发现OutofMemeroy的异常,这时可能需要手动清除这一级缓存:Session.evict及Session.clear

      c)应用缓存:在一个SESSIONFACTORY中有效,因此也是优化的重中之重,因此,各类策略也考虑的较多,在将数据放入这一级缓存之前,需要考虑一些前提条件:

i. 数据不会被第三方修改   ii. 数据不会太大 iii. 数据不会频繁更新(否则使用CACHE可能适得其反) iv. 数据会被频繁查询   v. 数据不是关键数据(如涉及钱,安全等方面的问题)。

 缓存有几种形式,能在映射文件中设置:read-only(只读,适用于非常少变更的静态数据/历史数据),nonstrict-read-write,read-write(比较普遍的形式,效率一般),transactional(JTA中,且支持的缓存产品较少)

      d) 分布式缓存:同c)的设置相同,只是缓存产品的选用不同,在目前的HIBERNATE中可供选择的不多,oscache, jbosscache,目前的大多数项目,对他们的用于集群的使用(特别是关键交易系统)都持保守态度。在集群环境中,只利用数据库级的缓存是最安全的。

      f)延迟加载——当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。

Hibernate2:实体延迟加载:通过使用动态代理实现/集合延迟加载:通过实现自有的SET/LIST,HIBERNATE提供了这方面的支持

Hibernate3:提供了属性的延迟加载功能

  6)事务控制策略(事务方式的选用,事务隔离级别及锁的选用)

       a)事务方式选用:如果不涉及多个事务管理器事务的话,不必使用JTA,只有JDBC的事务控制就能。

       b) 事务隔离级别:参见标准的SQL事务隔离级别

       事物隔离级别有哪些,事务特性是什么?

事物有7种传播特性 (事务是可以传播的...)

(1)propagation_required支持当前事务如果当前的逻辑处理有事务 则用当前的事物 没有就开启一个事物

(2)propagation_support支持当前事务 有就用 没有就不用

(3)propagation_new_required总是开启新的事务

(4)propagation_mondatory必须要有事务没有就抛异常

(5)propagation_never不要事务 有的话就抛异常

(6)propagation_not_support总是非事务执行 有事物就挂起

(7)如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

2.数据库的隔离级别(未提交读,提交读,可重复读,序列读)

1)未提交读 会出现脏读(当一个事务访问了数据 并进行了修改 ,第二个事务操作了修改了的数据 但是第一个事务回滚了 )

2)提交读  不可重复读 (第一个事务在多次访问一个数据的中间没结束事务另一个事务修改了该数据则第一个事务出现访问显示的数据不一样)

3)可重复读 幻读  (一个事务修改了了所有的数据  但是第二个事务往里面增加了一条数据 当第一个事务在访问的时候发现还有数据没修改出现一种幻觉)

       c)锁的选用:悲观锁(一般由具体的事务管理器实现),对于长事务效率低,但安全。乐观锁(一般在应用级别实现),如在HIBERNATE中能定义VERSION字段,显然,如果有多个应用操作数据,且这些应用不是用同一种乐观锁机制,则乐观锁会失效。因此,针对不同的数据应有不同的策略,同前面许多情况相同,非常多时候我们是在效率和安全/准确性上找一个平衡点,无论怎么,优化都不是个纯技术的问题,你应该对你的应用和业务特征有足够的了解。

4.Hibernate五大核心(类/接口)简述

  1.Configuration接口的作用是对Hibernate进行配置,以及对它进行启动。(加载hibernate.cfg.xml)并创建一个SessionFactory对象。

  2.SessionFactory接口负责初始化Hibernate,充当数据存储源的代理,并负责创建Session对象。SessionFactory是线程安全的。

  3.Session接口是Hibernate应用使用的主要接口。Session接口负责执行被持久化对象的CRUD操作(增删改查)。Session对象是非线程安全的且Session相当于jdbc的connection。

  4.Query与Criteria接口负责执行各种数据库查询。

  5.Transaction接口是一个可选的API,负责操作相关的事务。

5.Hibernate、Ibatis、Jdbc三者的区别

  Hibernate属于全自动,MyBatis/Ibatis属于半自动,Jdbc属于手动,从开发效率上讲hibernate>MyBatis/IBatis>jdbc,但从执行效率上讲jdbc>MyBatis/IBatis>Hibernate,因为jdbc是手工写sql语句,程序员对sql的控制能力更大,可以根据业务需要进行优化,而ibatis虽然也可以对sql进行优化,但他里面将resultset封装为实体的过程中采用了反射机制,所以一定程度上影响了性能,而hibernate因为高度封装所以开发效率相对较高,但正因为这个原因,所以程序员在对sql语句的控制和优化方面相对比较弱,而且在将resultset封装成实体的过程中也采用了反射机制,所以在性能方面较低。

  Hibernate和jdbc主要区别就是,hibernate先检索缓存中的映射对象(即hibernate操作的是对象),而jdbc则是直接操作数据库。

    MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索,而采用简单的 XML或注解用于配置和原始映射,将基本数据类型、Map 接口和 Java的POJOs映射成数据库中的记录。

   MyBatis的前身就是iBatis,iBatis本是apache的一个开源项目,MyBatis是把实体类和sql语句之间建立了映射关系,而Hibernate在实体类和数据库之间建立了映射关系。

6.谈谈你对MyBatis的理解

  MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。

  MyBatis 主要完成两件事情:

          1.根据 JDBC 规范建立与数据库的连接;

          2.通过Annotaion/XML+JAVA反射技术,实现 Java对象与关系数据库之间相互转化

7.Mybatis总体流程

  (1)加载配置并初始化

      触发条件:加载配置文件

      配置来源:一处是配置文件,一处是Java代码的注解

     将SQL的配置信息加载成为一个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置)并存储在内存中。

  (2)接收调用请求

      触发条件:调用Mybatis提供的API

      传入参数:为SQL的ID和传入参数对象

      处理过程:将请求传递给下层的请求处理层进行处理。

  (3)处理操作请求

       触发条件:API接口层传递请求过来

       传入参数:为SQL的ID和传入参数对象

       处理过程:

    (A)Mybatis会根据SQL的ID查找对应的MappedStatement对象;

   (B)根据传入参数对象解析MappedStatement对象得到最终要执行的SQL和执行传入参数;

   (C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果;

   (D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果;

    (E)释放连接资源。

  (4)返回处理结果

     将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。

8.Mybatis功能架构

  (1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

  (2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

  (3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

9.JDBC编程步骤

      1.通过Class.forName("com.mysql.jdbc.Driver")加载MySQL驱动

      2.通过DriverManager.getConnection(Stringurl,String user,String pass)获取数据库连接

     3.通过Connection对象创建Statement对象,Connection对象创建Statement对象的方法有如下三个:  

                createStatement():创建基本的Statement对象。   

                 preparedStatement(Stringsql):根据传入的SQL语句创建预编译的Statement对象。  

                 prepareCall(Stringsql):根据传入的SQL语句创建CallableStatement对象。

     4.使用Statement对象执行SQL语句。所以Statement都要如下三个方法来执行SQL语句:

           boolean execute(String sql) throwsSQLException:可以执行任何SQL语句,但比较麻烦。   

           int executeUpdate(String sql) throwsSQLException:主要用于执行DML和DDL语句。执行DML语句返回受SQL语句影响的行数,执行DDL语句返回0。   

           ResultSet executeQuery(String sql)throws SQLException:只能执行查询语句,执行后返回代表查询结果的ResultSet对象。

     5.操作结果集。如果执行的SQL语句是查询语句,执行后返回代表查询结果的ResultSet对象,该对象里保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果。ResultSet对象主要提供了两类方法:   一类:next、previous、first、last、beforeFirst、afterLast、absolute等移动记录指针的方法。   另一类:getXxx(),用于获取记录指针指定行,特定列的值。该方法既可以使用列索引作为参数,也可以使用列名作为参数。使用列索引作为参数性能更好,使用列名作为参数可读性更好。

     6.回收数据库资源,包括关闭ResultSet、Statement和Connection等资源。

   相关链接:http://blog.163.com/quanquan127@126/blog/static/6884772520126285319546/ 

0 1
原创粉丝点击