声明:本文只是本人的一点拙见,不喜勿喷。

欲速则不达,欲达则欲速!

一、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)
@Documentedpublic @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
beginupdate 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批量更新和批量删除的最佳方式。

hibernate 一对多_为什么很多人不愿意用hibernate了?相关推荐

  1. hibernate 无法保存timestamp_为什么很多人不愿意用hibernate了?

    点击上方蓝色字体,选择"标星公众号" 优质文章,第一时间送达 上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家(已修复) 下一篇:昨天分享资料不小心把百度网盘深处 ...

  2. 为什么很多人不愿意用hibernate了?

    关于SQL和ORM的争论,永远都不会终止,我也一直在思考这个问题.最近温习了一遍SSH框架,发了动弹,和广大猿友进行了深刻的探讨,被喷的五体投地,感慨万千,于是就有了今天这篇文章. 声明:本文只是小编 ...

  3. 看完保准你明白为什么很多人不愿意用hibernate了?

    个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 一.hibernate优势 hibernate让你不用写sql了,这不单可以让你的应用更好移植其它数据库,更主要的是让程序员更专注业 ...

  4. hibernate mysql 注解_【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)

    前言 本文将基于注解配置, 集成Spring 4和Hibernate 4,开发一个增删改查应用,涉及以下内容: 创建Hibernate实体 保存数据到mysql数据库中 在事务transaction内 ...

  5. win7字体_微软将终止支持win7,为什么现在还有很多人不肯升级到win10呢?

    在中国发展高层论坛上,李彦宏曾表示中国用户更加开放,对隐私问题没那么敏感,在很多情况下愿意用隐私交换便捷性和效率.从某种程度上来讲,这也反映了中国用户对升级到win10的态度.何出此言呢? 在&quo ...

  6. gem意思_出道10年,很多人不知道邓紫棋英文名GEM背后含义

    原标题:出道10年,很多人不知道邓紫棋英文名GEM背后含义 如果没有太关注港台歌手,大家对邓紫棋的出道.成名印象大概是2014年1月,她参加湖南卫视<我是歌手第二季>节目并演唱了众多让人印 ...

  7. Excel 有哪些可能需要熟练掌握而很多人不会的技能2

    8. 仪表盘 最终效果 在某个单元格中输入数值(0-100),红色的指针会随之而动 该案例不是很切题,应用也很局限,所以删去了操作步骤.该例成品可至前面提到的网盘地址中下载.若有兴趣研究详细做法,请私 ...

  8. Excel 有哪些可能需要熟练掌握而很多人不会的技能?

    Excel 有哪些可能需要熟练掌握而很多人不会的技能? 回答有些长,为节约大家的时间,我选取了一个经典案例,辅以详细的说明(中文版 Excel2013)放在开头,没时间看全部回答的品一下这个案例就好了 ...

  9. 如何看待”很多人不读书一样当老板挣大钱”的说法?

    2019独角兽企业重金招聘Python工程师标准>>> 我个人觉得读书是有用的,而那些说读书无用的人只是他读的书太少,还不能够拿出来"用",其次是读书有没有用不是 ...

最新文章

  1. 语言运行速度的一次测试
  2. 电源系统中纹波和噪声的处理
  3. 基于Xml 的IOC 容器-将配置载入内存
  4. bouncycastle NoSuchFieldError:xxx 版本冲突
  5. LeetCode 2105. 给植物浇水 II(双指针)
  6. 中文只占一个字符_长寿的人,3个部位可能“发红”,哪怕只占一个,身体还算健康...
  7. Ceilometer - Install the API behind mod_wsgi
  8. 前端开发 AMD 和 CMD 的规范区别
  9. Linux下编译安装Jsoncpp及应用实例
  10. Odoo 去掉 恼人的 上午和下午
  11. rman归档日志备份到磁盘并恢复的测试
  12. php更改文件为只读,word只读模式怎么修改
  13. jpa 动态查询条件 数组_利用JPA+querydsl实现多条件动态查询
  14. 郑州中小幼计算机初中级,郑州市中小幼计算机等级考试大纲.doc
  15. 铱金属配合物Ir(dpbpa)2bphen+PF6-|Ir(dtbpa)3|Ir(dtq)2bpy+PF6-的合成
  16. bzoj 1491: [NOI2007]社交网络
  17. php 微信支付 ca证书,微信企业付款 CA证书出错,请登录微信支付商户平台下载证书...
  18. SU操作说明--SU格式转SEGY格式
  19. Web 基础——Nginx(二)
  20. 软件测试/测试开发丨Java or Python?测试开发工程师如何选择合适的编程语言?

热门文章

  1. 反向工程解析QQ扫码登录的OAuth2流程
  2. Ipmi 远程管理工具
  3. ios中蓝牙自动连接出现硬件提示框的问题
  4. HTML中嵌入FLV视频文件
  5. 我需要完全理解这部分代码才能确保它能够正常工作,如果由我来修复代码中的问题,我是不会这么写的,因此希望你也不要这么来写(转)...
  6. windows系统上安装与使用Android NDK r8d(二)
  7. 深入理解C#的装箱和拆箱
  8. javascript ~~canvas url blob转换
  9. 人工智能丰收时代,传统营销企业如何应对?
  10. Confluence 6 目录中的数据库