hibernate和Ibatis比较java
hibernate 是当前最流行的o/r mapping框架,它出身于sf.net,如今已经成为jboss的一部分了。
ibatis 是另一种优秀的o/r mapping框架,目前属于apache的一个子项目了。
相对hibernate“o/r”而言,ibatis是一种“sql mapping”的orm实现。
hibernate对数据库结构提供了较为完整的封装,hibernate的o/r mapping实现了pojo 和数据库表之间的映射,以及sql 的自动生成和执行。程序员每每只需定义好了pojo 到数据库表的映射关系,便可经过hibernate 提供的方法完成持久层操做。程序员甚至不须要对sql 的熟练掌握, hibernate/ojb 会根据制定的存储逻辑,自动生成对应的sql 并调用jdbc 接口加以执行。
而ibatis 的着力点,则在于pojo 与sql之间的映射关系。也就是说,ibatis并不会为程序员在运行期自动生成sql 执行。具体的sql 须要程序员编写,而后经过映射配置文件,将sql所需的参数,以及返回的结果字段映射到指定pojo。
使用ibatis 提供的orm机制,对业务逻辑实现人员而言,面对的是纯粹的java对象。
这一层与经过hibernate 实现orm 而言基本一致,而对于具体的数据操做,hibernate会自动生成sql 语句,而ibatis 则要求开发者编写具体的sql 语句。相对hibernate而言,ibatis 以sql开发的工做量和数据库移植性上的让步,为系统设计提供了更大的自由空间。
hibernate与ibatis的对比:程序员
1.ibatis很是简单易学,hibernate相对较复杂,门槛较高。
2.两者都是比较优秀的开源产品
3.当系统属于二次开发,没法对数据库结构作到控制和修改,那ibatis的灵活性将比hibernate更适合
4.系统数据处理量巨大,性能要求极为苛刻,这每每意味着咱们必须经过通过高度优化的sql语句(或存储过程)才能达到系统性能设计指标。在这种状况下ibatis会有更好的可控性和表现。
5.ibatis须要手写sql语句,也能够生成一部分,hibernate则基本上能够自动生成,偶尔会写一些hql。一样的需求,ibatis的工做量比hibernate要大不少。相似的,若是涉及到数据库字段的修改,hibernate修改的地方不多,而ibatis要把那些sql mapping的地方一一修改。
6.以数据库字段一一对应映射获得的po和hibernte这种对象化映射获得的po是大相径庭的,本质区别在于这种po是扁平化的,不像hibernate映射的po是能够表达立体的对象继承,聚合等等关系的,这将会直接影响到你的整个软件系统的设计思路。
7.hibernate如今已是主流o/r mapping框架,从文档的丰富性,产品的完善性,版本的开发速度都要强于ibatis。sql
----ibatis原理浅析数据库
对于iBATIS工做原理其实,若是使用iBATIS,iBATIS在后台也是运行这些相同的JDBC代码。iBATIS会获取数据库链接,设置SQL语句的参数,执行SQL语句,获取执行结果,并在最后关闭全部的资源。然而,你须要本身亲自编写的代码量却大大地减小了。代码清单2-3给出了使用iBATIS运行相同的SQL语句时你须要编写的代码。apache
2.1.iBATIS工做原理之于小型、简单系统缓存
小型应用一般只涉及一个数据库,只有一些至关简单的用户接口和领域模型。它的业务逻辑层很是简单,有时对一些简单的只涉及增查改删(CRUD:Create, Read, Update, Delete)操做的应用来讲甚至根本就不存在业务逻辑。iBATIS之因此很是适合于小型应用,有3个缘由。安全
第一,iBATIS本身就很小而且简单。它不须要服务器或者其余任何类型的中间件。不须要任何额外的基础设施(infrastructure)。iBATIS也没有任何第三方依赖。iBATIS的最简安装只须要2个JAR文件,总计不过375KB。除了须要配置一下你的SQL映射文件外,iBATIS不须要进行任何安装,所以只须要几分钟时间你就能够拥有一个可工做的持久层了。服务器
第二,iBATIS不会对现存应用的设计或者数据库结构强加任何影响。所以,若是你有一个小型系统,且已经部分实现或者甚至已经发布了,则你仍然能够重构你的持久层以使用iBATIS,这很是简单。由于iBATIS很简单,因此它根本不会使得应用的架构过度复杂。而若是使用对象/关系映射工具或者代码生成工具,由于它们都事先就对应用以及数据库的设计作了某些假设,所以它们不可能对应用的架构毫无影响。session
最后,只要你有过软件开发的经验,相信你就不会怀疑,任何一个小软件都几乎不可避免地有一天会成长为一个大软件。全部成功的软件都有进一步成长的趋势。这是一件好事,而咱们接下来想说的就是,iBATIS一样很是适合于大型系统,它甚至能够扩展以知足企业级应用的须要。架构
2.2 iBATIS工做原理之于大型、企业级系统
iBATIS就是为企业级应用而设计的。最重要的是,iBATIS在这个领域比之其余解决方案有着大量的优势。iBATIS最初的建立者只有从大型应用到企业级应用系统的开发经验。这一类系统一般都涉及不止一个数据库,且全部这些数据库都是不可控的。在第一章中咱们讨论了各类类型的数据库,包括企业级数据库、私有数据库和遗留数据库。做者建立iBATIS框架一个很重要的缘由就是针对这样的数据库。所以,iBATIS拥有许多使其很是适合于企业应用环境的特色。
其实iBATIS适用于大型系统中的第一个缘由咱们已经说过了,不过这个缘由的确很重要,因此咱们仍是想再强调一下:iBATIS没有对你的数据库模型和对象模型的设计作任何假设。不论你的应用中这两个模型之间是多么不匹配,iBATIS都能适用。更进一步,iBATIS没有对你的企业级应用的架构作出任何假设。不论你对数据库是根据业务功能纵向划分,仍是按照技术横向划分,iBATIS都容许你高效地处理数据并将它们整合到你的面向对象的应用中去。
第二点,iBATIS的某些特性使得它可以很是高效地处理大型数据集。iBATIS支持的行处理器(row handler)使得它可以批处理超大型记录集,一次一条记录。iBATIS也支持只获取某个范围内的结果,这就使得你能够只获取那些你当前亟需的数据。例如,假设你获取了10,000条记录,而你其实只须要其中的第500至600条,那你就能够简单的仅获取这些记录。iBATIS支持驱动提示使得执行这样的操做很是高效。
最后一点,iBATIS容许你用多种方式创建从对象到数据库的映射关系。一个企业级系统只以一种模式工做的状况是很是少见的。许多企业级系统须要在白天执行事务性的工做,而在晚上执行批处理工做。iBATIS容许你将同一个类以多种方式映射,以保证每一种工做都能以最高效的方式执行。iBATIS一样支持多种数据获取策略。例如,你能够选择对某些数据进行懒加载,也能够将一个复杂的对象图只用一条联合查询SQL语句就同时加载完毕,从而避免严重的性能问题。
以上所说的这些彷佛好像在自我推销了。那么,既然咱们已经进入了这种状态,为什么不继续深刻研究一下你须要使用iBATIS的理由呢?咱们会在2.3节作这件事情。而且为了公平起见,在2.4节中,咱们还会讨论一些你不该该使用iBATIS的状况。
--------hibernate缓存(转自:http://blog.csdn.net/woshichenxu/article/details/586361)
Hibernate缓存分为二级,第一级存放于session中称为一级缓存,默认带有且不能卸载。
第二级是由sessionFactory控制的进程级缓存。是全局共享的缓存,凡是会调用二级缓存的查询方法都会从中受益。只有经正确的配置后二级缓存才会发挥做用。同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。好比Query.iterate()方法、load、get方法等。必须注意的是session.find方法永远是从数据库中获取数据,不会从二级缓存中获取数据,即使其中有其所须要的数据也是如此。
查询时使用缓存的实现过程为:首先查询一级缓存中是否具备须要的数据,若是没有,查询二级缓存,若是二级缓存中也没有,此时再执行查询数据库的工做。要注意的是:此3种方式的查询速度是依次下降的。
由于Session的生命期每每很短,存在于Session内部的第一级最快缓存的生命期固然也很短,因此第一级缓存的命中率是很低的。其对系统性能的改善也是颇有限的。固然,这个Session内部缓存的主要做用是保持Session内部数据状态同步。并不是是hibernate为了大幅提升系统性能所提供的。
为了提升使用hibernate的性能,除了常规的一些须要注意的方法好比:
使用延迟加载、迫切外链接、查询过滤等之外,还须要配置hibernate的二级缓存。其对系统总体性能的改善每每具备立竿见影的效果!
(通过本身之前做项目的经验,通常会有3~4倍的性能提升)
执行条件查询时,iterate()方法具备著名的“n+1”次查询的问题,也就是说在第一次查询时iterate方法会执行知足条件的查询结果数再加一次(n+1)的查询。可是此问题只存在于第一次查询时,在后面执行相同查询时性能会获得极大的改善。此方法适合于查询数据量较大的业务数据。
可是注意:当数据量特别大时(好比流水线数据等)须要针对此持久化对象配置其具体的缓存策略,好比设置其存在于缓存中的最大记录数、缓存存在的时间等参数,以免系统将大量的数据同时装载入内存中引发内存资源的迅速耗尽,反而下降系统的性能!!!
另外,hibernate会自行维护二级缓存中的数据,以保证缓存中的数据和数据库中的真实数据的一致性!不管什么时候,当你调用save()、update()或 saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法得到一个对象时, 该对象都将被加入到Session的内部缓存中。 当随后flush()方法被调用时,对象的状态会和数据库取得同步。
也就是说删除、更新、增长数据的时候,同时更新缓存。固然这也包括二级缓存!
只要是调用hibernate API执行数据库相关的工做。hibernate都会为你自动保证缓存数据的有效性!!
可是,若是你使用了JDBC绕过hibernate直接执行对数据库的操做。此时,Hibernate不会/也不可能自行感知到数据库被进行的变化改动,也就不能再保证缓存中数据的有效性!!
这也是全部的ORM产品共同具备的问题。幸运的是,Hibernate为咱们暴露了Cache的清除方法,这给咱们提供了一个手动保证数据有效性的机会!!
一级缓存,二级缓存都有相应的清除方法。
其中二级缓存提供的清除方法为:
按对象class清空缓存
按对象class和对象的主键id清空缓存
清空对象的集合中的缓存数据等。
并不是全部的状况都适合于使用二级缓存,须要根据具体状况来决定。同时能够针对某一个持久化对象配置其具体的缓存策略。
适合于使用二级缓存的状况:
一、数据不会被第三方修改;
通常状况下,会被hibernate之外修改的数据最好不要配置二级缓存,以避免引发不一致的数据。可是若是此数据由于性能的缘由须要被缓存,同时又有可能被第3方好比SQL修改,也能够为其配置二级缓存。只是此时须要在sql执行修改后手动调用cache的清除方法。以保证数据的一致性
二、数据大小在可接收范围以内;
若是数据表数据量特别巨大,此时不适合于二级缓存。缘由是缓存的数据量过大可能会引发内存资源紧张,反而下降性能。
若是数据表数据量特别巨大,可是常用的每每只是较新的那部分数据。此时,也可为其配置二级缓存。可是必须单独配置其持久化类的缓存策略,好比最大缓存数、缓存过时时间等,将这些参数下降至一个合理的范围(过高会引发内存资源紧张,过低了缓存的意义不大)。
三、数据更新频率低;
对于数据更新频率太高的数据,频繁同步缓存中数据的代价可能和查询缓存中的数据从中得到的好处至关,坏处益处相抵消。此时缓存的意义也不大。
四、非关键数据(不是财务数据等)
财务数据等是很是重要的数据,绝对不容许出现或使用无效的数据,因此此时为了安全起见最好不要使用二级缓存。
由于此时“正确性”的重要性远远大于“高性能”的重要性。
通常系统中有三种状况会绕开hibernate执行数据库操做:
一、多个应用系统同时访问一个数据库
此种状况使用hibernate二级缓存会不可避免的形成数据不一致的问题,
此时要进行详细的设计。好比在设计上避免对同一数据表的同时的写入操做,
使用数据库各类级别的锁定机制等。
二、动态表相关
所谓“动态表”是指在系统运行时根据用户的操做系统自动创建的数据表。
好比“自定义表单”等属于用户自定义扩展开发性质的功能模块,由于此时数据表是运行时创建的,因此不能进行hibernate的映射。所以对它的操做只能是绕开hibernate的直接数据库JDBC操做。
若是此时动态表中的数据没有设计缓存,就不存在数据不一致的问题。
若是此时自行设计了缓存机制,则调用本身的缓存同步方法便可。
三、使用sql对hibernate持久化对象表进行批量删除时
此时执行批量删除后,缓存中会存在已被删除的数据。
分析:
当执行了第3条(sql批量删除)后,后续的查询只多是如下三种方式:
a. session.find()方法:
根据前面的总结,find方法不会查询二级缓存的数据,而是直接查询数据库。
因此不存在数据有效性的问题。
b. 调用iterate方法执行条件查询时:
根据iterate查询方法的执行方式,其每次都会到数据库中查询知足条件的id值,而后再根据此id 到缓存中获取数据,当缓存中没有此id的数据才会执行数据库查询;
若是此记录已被sql直接删除,则iterate在执行id查询时不会将此id查询出来。因此,即使缓存中有此条记录也不会被客户得到,也就不存在不一致的状况。(此状况通过测试验证)
c. 用get或load方法按id执行查询:
客观上此时会查询获得已过时的数据。可是又由于系统中执行sql批量删除通常是
针对中间关联数据表,对于
中间关联表的查询通常都是采用条件查询 ,按id来查询某一条关联关系的概率很低,因此此问题也不存在!
若是某个值对象确实须要按id查询一条关联关系,同时又由于数据量大使用了sql执行批量删除。当知足此两个条件时,为了保证按id 的查询获得正确的结果,可使用手动清楚二级缓存中此对象的数据的方法!!
(此种状况出现的可能性较小)
一、建议不要使用sql直接执行数据持久化对象的数据的更新,可是能够执行批量删除。(系统中须要批量更新的地方也较少)
二、若是必须使用sql执行数据的更新,必须清空此对象的缓存数据。调用
SessionFactory.evict(class)
SessionFactory.evict(class,id)
等方法。
三、在批量删除数据量不大的时候能够直接采用hibernate的批量删除,这样就不存在绕开hibernate执行sql产生的缓存数据一致性的问题。
四、不推荐采用hibernate的批量删除方法来删除大批量的记录数据。
缘由是hibernate的批量删除会执行1条查询语句外加知足条件的n条删除语句。而不是一次执行一条条件删除语句!!
当待删除的数据不少时会有很大的性能瓶颈!!!若是批量删除数据量较大,好比超过50条,能够采用JDBC直接删除。这样做的好处是只执行一条sql删除语句,性能会有很大的改善。同时,缓存数据同步的问题,能够采用 hibernate清除二级缓存中的相关数据的方法。
调用 SessionFactory.evict(class) ;SessionFactory.evict(class,id)等方法。
因此说,对于通常的应用系统开发而言(不涉及到集群,分布式数据同步问题等),由于只在中间关联表执行批量删除时调用了sql执行,同时中间关联表通常是执行条件查询不太可能执行按id查询。因此,此时能够直接执行sql删除,甚至不须要调用缓存的清除方法。这样作不会致使之后配置了二级缓存引发数据有效性的问题。
退一步说,即便之后真的调用了按id查询中间表对象的方法,也能够经过调用清除缓存的方法来解决。
根据我了解的不少hibernate的使用者在调用其相应方法时都迷信的相信“hibernate会自行为咱们处理性能的问题”,或者“hibernate会自动为咱们的全部操做调用缓存”,实际的状况是hibernate虽然为咱们提供了很好的缓存机制和扩展缓存框架的支持,可是必须通过正确的调用其才有可能发挥做用!!因此形成不少使用hibernate的系统的性能问题,实际上并非hibernate不行或者很差,而是由于使用者没有正确的了解其使用方法形成的。相反,若是配置得当hibernate的性能表现会让你有至关“惊喜的”发现。下面我讲解具体的配置方法.
ibernate提供了二级缓存的接口:
net.sf.hibernate.cache.Provider,
同时提供了一个默认的 实现net.sf.hibernate.cache.HashtableCacheProvider,
也能够配置 其余的实现 好比ehcache,jbosscache等。
具体的配置位置位于hibernate.cfg.xml文件中
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</property>
不少的hibernate使用者在 配置到 这一步 就觉得 完事了,
注意:其实光这样配,根本 就没有使用hibernate的二级缓存。同时由于他们在使用hibernate时大多时候是立刻关闭session,因此,一级缓存也没有起到任何做用。结果就是没有使用任何缓存,全部的hibernate操做都是直接操做的数据库!!性能能够想见。
正确的办法是除了以上的配置外还应该配置每个vo对象的具体缓存策略,在影射文件中配置。例如:
<hibernate-mapping>
<class name="com.sobey.sbm.model.entitySystem.vo.DataTypeVO" table="dcm_datatype">
<cache usage="read-write"/>
<id name="id" column="TYPEID" type="java.lang.Long">
<generator class="sequence"/>
</id>
<property name="name" column="NAME" type="java.lang.String"/>
<property name="dbType" column="DBTYPE" type="java.lang.String"/>
</class>
</hibernate-mapping>
关键就是这个<cache usage="read-write"/>,其有几个选择
read-only,read-write,transactional,等
而后在执行查询时 注意了 ,若是是条件查询,或者返回全部结果的查询,此时session.find()方法 不会获取缓存中的数据。只有调用query.iterate()方法时才会调缓存的数据。
同时 get 和 load方法 是都会查询缓存中的数据 .
对于不一样的缓存框架具体的配置方法会有不一样,可是大致是以上的配置
(另外,对于支持事务型,以及支持集群的环境的配置我会争取在后续的文章中中 发表出来)
总之是根据不一样的业务状况和项目状况对hibernate进行有效的配置和正确的使用,扬长避短。不存在适合于任何状况的一个“万能”的方案。
以上结论及建议均创建在本身在对 Hibernate 2.1.2中的测试结果以及之前的项目经验的基础上。若有谬处,请打家提出指正:)!
再谈谈Hibernate与Ibatis的区别,哪一个性能会更高一些
答: 1、Hibernate偏向于对象的操做达到数据库相关操做的目的;而ibatis更偏向于sql语句的优化。
2、Hibernate的使用的查询语句是本身的hql,而ibatis则是标准的sql语句。
3、Hibernate相对复杂,不易学习;ibatis相似sql语句,简单易学。
性能方面:
1、若是系统数据处理量巨大,性能要求极为苛刻时,每每须要人工编写高性能的sql语句或存错过程,此时ibatis具备更好的可控性,所以性能优于Hibernate。
2、一样的需求下,因为hibernate能够自动生成hql语句,而ibatis须要手动写sql语句,此时采用Hibernate的效率高于ibatis。