个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈

一、hibernate优势

hibernate让你不用写sql了,这不单可以让你的应用更好移植其它数据库,更主要的是让程序员更专注业务逻辑、数据关系、对象关系等。hibernate对一对多,多对多关系实现是非常好的。很关键一点,它支持lazy,可以让你的数据只在需要的时候被加载,听起来很完美。hibernate还有一个更牛的就是HQL,这是完全可以把查询映射到你OO模型的查询语言,和mybatis的映射比起来,还是更方便和更强大的。

1、@Lazy注解是什么?

@Lazy注解用于标识bean是否需要延迟加载,源码如下:

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {/*** Whether lazy initialization should occur.*/boolean value() default true;
}

只有一个参数,默认是true,也就是说只要加了这个注解就会延迟加载。

2、@Lazy注解怎么使用

没加注解之前主要容器启动就会实例化bean,如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);

创建user实例

而加上@Lazy注解则必须在第一次调用的时候才会加载如下:

@Scope
@Lazy
@Bean(value="user0",name="user0",initMethod="initUser",destroyMethod="destroyUser")
public User getUser(){System.out.println("创建user实例");return new User("张三",26);
}
AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
User bean2 = applicationContext2.getBean(User.class);
创建user实例
实例1 === User [userName=张三, age=26]

@Lazy注解注解的作用主要是减少springIOC容器启动的加载时间

二、hibernate劣势

看完优势之后,感觉hibernate无所不能了,无敌是多么的寂寞。处理大量数据或者大并发情况的网络服务感觉不是很好用,那么现在开始说说hibernate的问题。

1、难以使用数据库的一些功能

hibernate将数据库与开发者隔离了,开发者不需要关注数据库是Oracle还是MySQL,hibernate来帮你生成查询的sql语句,但问题来了,如果你想用某种数据库特有的功能,或者要让查询的sql完全符合你的心意,这就难了。如果使用hibernate,虽然它能对生成的查询进行一定程序的定制,但就有点隔靴挠痒的感觉了,而且你开发起来付出的代价更大。至于hibernate对native sql的支持,还是挺完善的,这种native sql还能返回non-managed entity,不走hibernate的cache,优化是搞定了,但如果整个项目都这么整,那还是用mybatis吧。

很多时候,我们都有一个需求:得到数据库服务器的当前时间。这是因为本机时间和服务器时间是有差别的。各种数据库都提供了函数来获得,比如,mysql,可以用“select now()”。hibernate也提供了一个函数current_timestamp(说起timestamp,个人认为数据库的timestamp做的很差,它居然和datetime是一个数量级的(精确度),这怎么可以用来表示真正的stamp啊!)。可是,你却无法用直接使用“select current_timestamp()”来获得服务器的当前时间,你还必须加上一个查询的表!比如,“select current_timestamp() from tbl_Good”。个人十分郁闷,我只是想用这个简单功能而已,为什么我一定要知道数据库里面的表格呢????更何况还必须建立映射。。。。。。

不是我不明白,这世界太复杂了 。每样产品都是拼命的复杂化,其实,它们实在是忽略了一般的用户只需要一小部分功能而已。默认的功能应该是能够满足普通用户的常见需求的,那样才算是一个好的产品。我不认为hibernate做到了这点。

2、满足不了程序对cache的需求

很多web服务,对cache的依赖是非常大的,hibernate自带的cache按理说也是很强大的,但还是满足不了很多需求。

3、耦合度高

hibernate的确是在你项目开发的时候节约了很多时间,但是它对你的业务逻辑模型和数据库模型互相依赖的程度太高了。短期没啥问题,但随着项目的变迁,这些都会改变,在维持这种仅仅耦合的关系的时候,你会发现你的代码特别脆弱,随便改一处数据库的schema,整个java项目可能要改几十次。而且现在mybatis的自动mapping做的也很好,开发起来也没花多长时间,等项目进入中后期,你需要大量定制和优化查询的时候,mybatis的开发效率就更明显了。

4、debug难

作为一个后端程序员,我比较喜欢每一行代码我都精确知道它到底在干什么。尤其是数据库访问的代码,往往系统的瓶颈就在这些地方产生,每一行都不能小看。我看过hibernate早期版本的部分代码,比我想象的复杂和强大很多。的确很多地方Hibernate可以强大的只用一行代码解决很多问题,但比如说一个update()或者save()到底做了什么,这里既有hibernate本身的逻辑,也有你应用的逻辑,如果这一行产生了问题,你该如何去做?我个人觉得这是很难搞的,还不如一开始费点事,用mybatis这种。

作为一个程序员,我始终坚持认为改代码比改配置文件容易。

5、hibernate更新大批量数据

(1)hibernate批量更新customers表中大于零的所有记录的age字段:

Transaction transaction = session.beginTransaction();
Iterator customers=session.find("from Customer c where c.age>0").iterator();
while(customers.hasNext()){     Customer customer=(Customer)customers.next();     customer.setAge(customer.getAge()+1);
}
transaction.commit();
session.close();  

如果customers表中有一万条年龄大于零的记录,那么session的find()方法会一下子加载一万个customer对象到内存中。当执行tx.commit()方法时,会清理缓存,hibernate执行一万条更新customers表的update语句:

update CUSTOMERS set AGE=? …. where ID=i;     

(2)以上hibernate批量更新方式有两个缺点

  • 占用大量内存空间,必须把一万个customer对象先加载到内存,然后一一更新他们。
  • 执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新一万个Customer对象,频繁的访问数据库,会大大降低应用的性能。

(3)为了迅速释放1万个Customer对象占用的内存,可以在更新每个Customer对象后,就调用Session的evict()方法立即释放它的内存:

Transaction transaction = session.beginTransaction();
Iterator customers=session.find("from Customer c where c.age>0").iterator();
while(customers.hasNext()){     Customer customer=(Customer)customers.next();     customer.setAge(customer.getAge()+1);     session.flush();     session.evict(customer);
}
transaction.commit();
session.close();  

在以上程序中,修改了一个Customer对象的age属性后,就立即调用Session的flush()方法和evict()方法,flush()方法使hibernate立刻根据这个Customer对象的状态变化同步更新数据库,从而立即执行相关的update()语句;evict()方法用于把这个Customer对象从缓存中清除出去,从而及时释放它占用的内存。

但evict()方法只能稍微提高批量操作的性能,因为不管有没有使用evict()方法,Hibernate都必须执行1万条update语句,才能更新1万个Customer对象,这是影响批量操作性能的重要因素。假如Hibernate能直接执行如下SQL语句:

update CUSTOMERS set AGEAGE=AGE+1 where AGE>0;   

那么以上一条update语句就能更新CUSTOMERS表中的1万条记录。但是Hibernate并没有直接提供执行这种update语句的接口。应用程序必须绕过Hibernate API,直接通过JDBC API来执行该SQL语句:

Transaction transaction = session.beginTransaction();
Connection con=session.connection();
PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGEAGE=AGE+1 where AGE>0 ");
stmt.executeUpdate();
transaction.commit();  

以上程序演示了绕过Hibernate API,直接通过JDBC API访问数据库的过程。应用程序通过Session的connection()方法获得该Session使用的数据库连接,然后通过它创建 PreparedStatement对象并执行SQL语句。值得注意的是,应用程序仍然通过Hibernate的Transaction接口来声明事务边 界。 
如果底层数据库(如Oracle)支持存储过程,也可以通过存储过程来执行Hibernate批量更新。存储过程直接在数据库中运行,速度更加快。在Oracle数据库中可以定义一个名为batchUpdateCustomer()的存储过程,代码如下:

create or replace procedure batchUpdateCustomer(p_age in number) as
begin
update CUSTOMERS set AGEAGE=AGE+1 where AGE>p_age;
end;  

以上存储过程有一个参数p_age,代表客户的年龄,应用程序可按照以下方式调用存储过程:

Transaction transaction = session.beginTransaction();
Connection con=session.connection();
String procedure = "{call batchUpdateCustomer(?) }";
CallableStatement cstmt = con.prepareCall(procedure);
cstmt.setInt(1,0); //把年龄参数设为0
cstmt.executeUpdate();
transaction.commit();  

从上面程序看出,应用程序也必须绕过Hibernate API,直接通过JDBC API来调用存储过程。

6、hibernate删除大批量数据

Session的各种重载形式的update()方法都一次只能更新一个对象,而delete()方法的有些重载形式允许以HQL语句作为参数,例如:

session.delete("from Customer c where c.age>0");  

如果CUSTOMERS表中有1万条年龄大于零的记录,那么以上代码能删除一万条记录。但是Session的delete()方法并没有执行以下delete语句

delete from CUSTOMERS where AGE>0;  

Session的delete()方法先通过以下select语句把1万个Customer对象加载到内存中:

select * from CUSTOMERS where AGE>0;  

接下来执行一万条delete语句,逐个删除Customer对象:

delete from CUSTOMERS where ID=i;
delete from CUSTOMERS where ID=j;
delete from CUSTOMERS where ID=k;  

由 此可见,直接通过Hibernate API进行Hibernate批量更新和Hibernate批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用存储过程,是hibernate批量更新和批量删除的最佳方式。

素小暖讲Spring JdbcTemplate

三、群众的眼光的雪亮的,千万不要逆天而行

四、被喷之后的一些感悟

感觉就是一场批斗大会,我深深的感觉到才疏学浅的无奈,我真的只是想好好学习而已,希望若干年后,我还能初心不改。

作为一个初级程序员而言,没有必要花费过多的时间去证明技术的无用论,我并没有对hibernate这个框架进行深入的研究,只是在肤浅的层面的一些个人感悟。

框架本身并没有对错一说,只有适合不适合,任何框架都有其自身的能力范围,hibernate封装了很多有用的API给我们,降低了操作数据库的难度和复杂度,同时也减少了模板代码的数量,但hibernate留给开发者的可操作空间相对mybatis少了很多;mybatis框架使用起来更加灵活,开发者可以自定义查询语句,但增加了模板代码量,看起来并没有hibernate边界。两种框架在便捷与灵活两个指标上做出了取舍和妥协,这不能说是框架的错。对于一个框架而言,需要有自身专注的领域和设计愿景,不可能面面俱到,就如这位大哥所言:

使用任何一种技术框架,都需要贴合现实的业务需求以及自身的技术能力。当你还没有深入的去了解一门技术或者当前业务需求无法与框架契合时,不要盲目的批判框架的好坏。

附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读/书籍书单大全:

(点击右侧 即可打开个人博客内有干货):技术干货小栈
=====>>①【Java大牛带你入门到进阶之路】<<====
=====>>②【算法数据结构+acm大牛带你入门到进阶之路】<<===
=====>>③【数据库大牛带你入门到进阶之路】<<=====
=====>>④【Web前端大牛带你入门到进阶之路】<<====
=====>>⑤【机器学习和python大牛带你入门到进阶之路】<<====
=====>>⑥【架构师大牛带你入门到进阶之路】<<=====
=====>>⑦【C++大牛带你入门到进阶之路】<<====
=====>>⑧【ios大牛带你入门到进阶之路】<<====
=====>>⑨【Web安全大牛带你入门到进阶之路】<<=====
=====>>⑩【Linux和操作系统大牛带你入门到进阶之路】<<=====

天下没有不劳而获的果实,望各位年轻的朋友,想学技术的朋友,在决心扎入技术道路的路上披荆斩棘,把书弄懂了,再去敲代码,把原理弄懂了,再去实践,将会带给你的人生,你的工作,你的未来一个美梦。

看完保准你明白为什么很多人不愿意用hibernate了?相关推荐

  1. 硬件:笔记本电脑7大分类总结,看完你就明白了!

    今天给大家分享笔记本电脑7大场景分类,看完你就明白了! 游戏本 游戏本最早由外星人和微星推出,在90年代就引起了众多游戏玩家的热捧.目前游戏本在笔记本电脑市场可谓是超级火爆,基本每个大厂商都推出了专门 ...

  2. 计算机显示器的三原色是,显示器参数看不懂?看完你就明白啦!

    原标题:显示器参数看不懂?看完你就明白啦! 对于电脑性能最直观的感受,就是通过显示器来感受.现在的各种显示器选择很多,各种参数也很多,无论是游戏.绘图.影视还是普通的商务用显示器都有不同的需求,因此选 ...

  3. 怎样发量暴增_发量少怎么办如何增加发量?看完你就明白了

    发量少怎么办如何增加发量?看完你就明白了 随着社会压力的增大,很多疾病都跻身于医学界,脱发就是最常见的疾病之一,尤其是脂溢性脱发!之前我们讲到过,脂溢性脱发从中医角度来看主要是分为临泣穴脱发和百会穴脱 ...

  4. 计算机专业对应的职业,这十个高薪职业对应哪些大学专业?看完你就明白啦

    原标题:这十个高薪职业对应哪些大学专业?看完你就明白啦 每年高考结束后,报考大学填报专业渐渐成为广大考生和家长最头疼的事情,报考大学还好说一些,毕竟每一位高三考生心中都根据自己的实际情况,曾经设想过几 ...

  5. 你的Scrum迭代够精益吗?看完就全明白了

    你的Scrum迭代够精益吗?看完就全明白了 原文 http://www.jackyshen.com/2017/08/02/is-your-Scrum-lean-enough/ Scrum与产品创新 V ...

  6. 游戏伤害计算机,阴阳师:输出和防御之间的各种计算,看完就能明白游戏的伤害机制...

    原标题:阴阳师:输出和防御之间的各种计算,看完就能明白游戏的伤害机制 小伙伴们大家好,今天小编给大家科普一下游戏输出和防御之间的各种计算公式吧,相信在清楚伤害计算之后大家对各种属性的搭配也会有更好的理 ...

  7. 三大方面对比两种企业邮箱的功能,看完你就明白了

    企业邮箱有收费和免费的两种,那么应该选择哪一种呢? 今天我们从三大方面对比两种企业邮箱的基本功能,看完你就明白了. 1.容量方面: 收费企业邮箱无限容量,免费企业邮箱中容量最大的只有5G,还有2.3G ...

  8. 计算机删除的照片怎么恢复数据,怎么恢复电脑里删除的照片?看完你就明白的...

    怎么恢复电脑里删除的照片?看完你就明白的 2019年06月25日 18:15作者:黄页编辑:黄页 分享 怎么恢复电脑里删除的照片?现如今办公广泛在使用电脑进行,电脑上也存储着很多重要的照片数据,如果在 ...

  9. 清华计算机2017学硕,2017级清华大学研究生来自于哪些大学?看完你就明白啦!...

    原标题:2017级清华大学研究生来自于哪些大学?看完你就明白啦! 清华大学,作为我国高校中的顶尖学府,是很多学生心中的梦想之地,每年的高考中,只有各省的前几十名才有机会被清华大学录取.但是研究生,作为 ...

最新文章

  1. windows兼容Linux php,支持windows与linux的php计划任务的实现方法
  2. html编写组织结构,编写模块化的CSS:CSS文件组织结构
  3. Runtime底层原理--动态方法解析总结
  4. macOS 10.14 mojave安装低版本iTunes 12.6.x
  5. 为什么 头条 宇宙条_“当宇宙行遭遇黑洞……“【59期省联社微信传播力榜单】...
  6. PHP中将首字母大写的函数,在PHP中,使用()函数来将单词首字母转换为大写。
  7. 给定一个整数序列,求中位数
  8. asp.net添加自定义用户控件并传值
  9. 大数据分析可以用哪些营销策略
  10. Python3 configparser值为多行时配置文件书写格式
  11. CESIUM加载glb的模型
  12. java gbk文件转utf8_java 将GBK编码文件转为UTF-8编码
  13. 第五章 线性回归 学习笔记上
  14. .axf文件_「嵌入式笔记」hex文件、bin文件、axf文件的区别?
  15. 常用24位颜色表转换成16位颜色值,让16位lcd使用
  16. Flutter图片裁剪
  17. 安卓打造自己的日历控件
  18. eve服务器关闭维护几天,关于维护请问,EVE每次维护的具体时间是多 – 手机爱问...
  19. java json字符串转JSONObject对象、转JAVA对象、转List<T>对象
  20. #计算机网络与应用:某中学校园网方案设计

热门文章

  1. Linux下检测FTP服务并开启FTP服务
  2. JS中的可枚举属性与不可枚举属性
  3. 联合早报网论坛,被称为“东方芝加哥”的武汉,你曾被谁抛弃。
  4. 古剑奇谭网络版服务器正在维护,古剑奇谭ol11月29日更新了什么 古剑网络版更新维护公告...
  5. mysql 如何解锁_Mysql如何解锁?
  6. 瑞星RAC-1350行为管理设备体验
  7. 买英伟达RTX 30 系显卡送《穿越火线》大礼包,你心动了吗?
  8. C# Winform自动卸载软件
  9. 2017-2018-2 20179207 《网络攻防技术》第六周作业
  10. 昂达11Pro如何安装Android,折腾下战三年,11款Macbook Pro安装Catalina步骤指南