为什么很多人不愿意用hibernate了?
最近想温习一遍JAVA框架,理所当然的从最基本的SSH开始整合,然而亲身体会了一下hibernate的可怕之处。
一、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,尤其是需要处理大量数据或者大并发情况的网络服务,那么现在开始说说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、写入和查询语句不执行
写个简单的session.save(obj)语句,你却发现它并不执行。原来是因为数据库表是事务表,所以,需要把这个语句放到事务里面执行。这个还好说。
过不不久,你发现query查询居然没有执行!你把hibernate生成的sql放数据库里,居然还好用,它也不是老不出,一段时间之后,它就执行了,会给你一个结果。查询语句居然不是实时的...... 在google了很长时间之后(半天),才看到一个说法:把查询语句用事务封装起来。于是这么做了,发现hibernate能够马上执行查询语句了。
6、执行本地sql语句返回结果奇特
数据库中有几个表,,需要进行左连接访问,用sql很简单,但是。当你打算使用hql的时候,你会发现,配置那个麻烦啊,没有执行写sql来的简单,我在做SSH的项目练习,至今还没搞定左连接。所以,你想直接写sql语句,期待hibernate能够像普通JDBC那样执行,返回一个正确的结果,然并卵,hibernate返回的结果。。。
数据库表里面有一个字段类型char(4),里面的值都是“good”,可是,hibernate查询回来的居然只有一个字符:“g”。只好查看hibernate的ref里面的Native Sql那章了,看到有如下的例子:
sess.createSQLQuery("SELECT * FROM CATS") .addScalar("ID", Hibernate.LONG) .addScalar("NAME", Hibernate.STRING) .addScalar("BIRTHDATE", Hibernate.DATE)
你才知道,你需要使用addScalar方法来指定某个返回字段的类型!注意的是,方法里面的第一个参数是返回字段的名称。哦,你恍然大悟。立马这样修改了自己的代码,慢着,你突然发现居然只返回了你使用addScalar指定了类型的几个字段!原来,hibernate就是这样处理的,你要返回的每个字段都必须使用addScalar指定!
7、写入数据库字符串乱码
简单的数据库,简单的表格,简单的字段,是字符串类型,utf-8编码。用hibernate写入正常文本,写进去就变成乱码了。显然是编码不一致的问题。hibernate里面居然没有说明如何配置。好在网络上有人说可以在hibernate的配置文件里面加上一句配置:
<property name="connection.characterEncoding">UTF-8</property>
这句配置并不是给hibernate用的,它会传递给底层的jdbc。告诉jdbc字符串是utf-8的编码。可能有的数据库会需要你再配置一个(以上配置mysql可以):
<property name="connection.useUnicode">true</property>
三、群众的眼光的雪亮的,千万不要逆天而行
相关博文
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
云原生与无服务器架构是云计算的未来吗?——云计算的演进
云原生与无服务器架构是云计算的未来吗?——云计算的演进 作为“十三五”重点规划产业之一,云计算到底是什么?又会怎样发展?最近兴起的云原生(Cloud Native)和无服务器架构(Serverless)又与云计算有什么关系?本文将以云计算的发展为路线,为大家科普云计算的概念与现状,无论读者是开发、测试、抑或是产品、管理者都能在本文中有所收获。 纵观整个服务器的发展历程,可以分为三阶段,自建服务器时代、服务器托管与租赁时代、云计算时代。 自建服务器时代 早期的计算机主要分为两种使用方式,组织自建机房与租用,自建机房很好理解,就是买一台放在公司自己用,租用一般是制造商提供租赁使用,按时付费,是不是有点今天云服务器的意思? 早期的IBM 650要价50万美金,或可以每月3500 美金的价格出租。 服务器托管与租赁时代 至 Web 时代来临,IT 公司大量采用 B/S(浏览器/服务端) 架构,客户端越来越轻量化,大部分资源存储在服务端,导致服务器需求激增,于是服务器托管业务应运而生,早期多为 ISP 即互联网服务提供商(Internet Service Provider)承接,简单来说就是买一...
- 下一篇
MySQL 8.0.19 版本发布
MySQL 8.0.19 版本发布了,这是 2020 年第一个小版本。 主要更新内容: 帐户管理说明 审核日志说明 编译说明 配置说明 弃用和移除说明 错误处理 功能和操作员注意事项 INFORMATION_SCHEMA注意 钥匙圈注意事项 记录笔记 包装注意事项 SQL语法说明 sys架构说明 线程池注释 X插件说明 添加或更改功能 修正错误 更新说明:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-19.html
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Hadoop3单机部署,实现最简伪集群
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7安装Docker,走上虚拟化容器引擎之路