hibernate,mybatis,beetlsql 全面比较
hibernate,mybatis,beetlsql 全面比较
闲大赋 发表于2年前
hibernate,mybatis,beetlsql 全面比较
  • 发表于 2年前
  • 阅读 3492
  • 收藏 32
  • 点赞 3
  • 评论 20

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 这是我主观的一个综合评分,总共分为12个单项,每个单项最高5分,最低0分。注意,评价只包含这些软件提供的标准功能,不包含第三方提供的功能。

这是我的一个综合评分,总共分为12个单项,每个单项最高5分,最低0分。注意,评价只包含这些软件提供的标准功能,不包含第三方提供的功能,如代码生成等。

 

开发效率

hibernate  能获取数据库metadata,因此简单的sql操作,如插入,更新,删除,翻页等,都可以自动完成。但因为概念复杂,经常会导致开发人员会写sql,能写java,但不会写hibernate情况出现(关系配置或者hql),导致开发效率反而降低。

 

 

 

session.save(user);
String hql= "from bank.Person person where person.id.country = 'AU' "
Query query = sessin.createQuery(hql);



mybatis  必须手工写sql,效率较低,有第三方工具能自动生成才勉强提高了开发效率

beetlsq l 同样具有hibernate 的功能,但不要求配置或者annotation。所以认为开发效率比hibernate高,是因为beetlsql 本身使用不容易出错,不像hibernate那样概念复杂,容易使用错误,导致实际开发速度降低. 在写sql文件的时候,基于MD+beetl的也比myabtis 的xml 要快很多. 

 

sqlManager.save(user);
List<User> list = sqlManager.select("user.queryMaxAgeUser",User.class,paras);
//or UserDao是一个开发者定义的接口,通过代理实现DAO
UserDao dao = sqlManager.getMapper(UserDao.class);
List<User> list  dao.queryMaxAgeUser(paras)

 

 

跨多种数据库

hibernate  支持几乎所有数据库,通过自动生成的sql(插入,删除,翻页等),hql,来完成跨数据库操作,但对于数据库之间确实不同地方,hibernate无力处理,所以只有4分
mybatis  几乎没有考虑过跨数据库功能,配置文件里可以通过if标签来做判断,但这种技术鸡肋的很。
beetlsql ,目前支持Oracle,Mysql,Postgres,SQLServer,SQLLite,H2。同样提供了自动生成sql完成插入,删除,翻页等跨数据库的功能,beetl脚本来完成一些跨数据库操作。另外,beetlsql独立管理sql文件,sql放在根目录下,特定数据库sql放在以数据库命名的子目录下。如果数据库sql确实有一样地方,可以用特定数据库sql覆盖默认的sql。

 

 

 

 

维护性

hibernate  : hibernate本生复杂性导致了维护比较难。对于一些简单的重构,hibernate代码不需要改动。对于复杂的sql(hql)改动,hibernate比较费劲
mybatis  :可以适应复杂的sql改动,但表重构等,必须修改mapper 配置文件里的sql。
beetlsql : 同时具备hibernate 和 myabtis 在维护性方面的优点。支持重构,支持代码外维护sql。 beetlsql的md格式使得维护sql像读文档一样。同myabtis一样,支持将sql文件的sql语句自动映射成dao方法。

 

 

 

QQ截图20160217182303.png

 

 

系统启动耗时

hibernate  :启动需要加载数据库的metadata,加载pojo,加载配置文件,然后校验等操作,启动很耗时
mybatis  : 需要做一个基本的配置文件加载,以及各个mapper文件加载,系统第一次访问的时候会慢
beetlsql :只简单的加载了数据库的metadata,不做任何校验,启动几乎不消耗时间

 

 

 

 

错误提示

hibernate  由于本生ORMapping的复杂性.所以提示也很复杂。另外无论是xml配置还是annotation配置,如果有出错提示,也很难明白错误提示意思。HQL 也是这样,错误提示也并不理想
mybatis  : myabtis 错误提示最难搞懂,因为他基于xml解析和ognl 表达式都不是他自己的,所以我们会看到各种莫名其妙的提示。

如下,本来应该是resultType,但写成resultMap

 

 

 

<select id="getGrantCount" resultMap="Integer"  parameterType="Map">


错误提示尽管可以理解,但非常不直观,没有告诉你哪行错了,你只能配置文件所有地方才能排查这个手误

 

Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for cn.xxx.IGiftStatisticCacheService.Integer



beetlsql : 基于beetl模板语言,哪个配置文件哪行错了,错误原因是什么,提示的非常清楚,而且是中文的

 

 

如下一个sql配置,if语句多了一个d

 

 

 

select * from User where 1 =1  
@if(isNotEmpty(age)d){
and age = #age#
@}

 

 

 

错误提示如下

 

>>11:14:10:缺少符号(PARSER_MISS_ERROR):d 位于2行 资源:user.queryUser_page
多余输入 'd' 期望 RIGHT_PAR
1|select * from User where 1 =1
2|@if(isNotEmpty(age)d){
3|and age = #age#
4|@} 

 

 

模型支持

hibernate ,只支持pojo,而且由于有关系约束,导致开发不够快捷
mybatis  :pojo和map都支持,map支持可以快速支持一些小的功能开发
beetlsql :pojo和map都支持,另外混合模型,使用较少的pojo完成大量的查询操作而无需为模型添额外的属性,因此模型支持比myabtis要好。

 

 

 

List<User> list = sqlManager.select("user.queryXXX",User.class,paras);
List<Map> list = sqlManager.select("user.queryXXX",Map.class,paras);
//如果user继承了Tail接口,支持混合模型.如下例子可以通过user.get("roleName ") 访问角色名,这对于web项目来说,很好用
List<User> list = sqlManager.excute("select u.*,r.name  roleName from user u,role r ... ",User.class,paras);

 

 

学习曲线

hibernate  毫无疑问最难掌握的是hibernate,这是公认的,他的别扭之处是明明就是个sql 操作,非要让开发人员先转成对象,然后再转成sql(实际上,sql语言已经屏蔽了操作数据库的复杂性了),看看hibernate有多少书和文档就知道他的复杂性
myabtis : 很简单,除了写mapper文件,可能需要学一下怎么写,但大概也就3-5天时间。myabtis作者当时的出发点也是写一个“不要一本书来说明的dao工具”,他做到了,但做的还不够好。
beetlsql : API仅仅在SQLManager里,一看就明白。sql文件采用md格式,去除了xml那种繁琐,并且使用beetl作为模板语言,非常简单,1天就能完全掌握。 对于数据库这种访问技术来说,本不应该出现所谓的“砖家”,但hibernate有,这是不正常的。所以,hiberante评分最低,beetlsql最高。

 

 

 

 

对DBA友好

hibernate  : 此工具是仇视DBA的,自然DBA也不喜欢hibernate。在这就不谈了。
myabtis :sql文件单独管理,采用xml方式,相对友好,但xml方式过于繁琐了,像常见的"<" 符号,myabtis不得不专门处理
beetlsql : sql 既可以出现在代码里,也可以在sql文件里,由于采用md+beetl 格式,比myabtis更好,DBA看beetlsql的sql文件,就像阅读文档一样

 

 

 

 

与其他工具友好

hibernate  :由于是采用容器管理bean,因此在容器里使用第三方工具,和容器外使用第三方工具,效果不一样,比如hibenate独有的Open Session In View 问题,还有 Session Has Closed ...
myabtis :无容器管理,所以怎么用都顺手
beetlsql :同myabtis,对其他工具很友善

 

 

 

 

性能

没有具体比较过,但考虑三者工具都涉及到sql模板解析,MetaData 获取和分析,ResutlSet 的Mapping操作,java反射等,因此,性能差不多。我将在以后给出具体性能对比。再考虑到数据库操作,dao基本上可以忽略不计,所以性能都给予5分

 

 

 

 

数据库主从支持

hibernate  : 不支持,需要借助第三方路由中间件
myabtis : 支持,但需要做一些简单的编码,以切换数据源
beetlsql :支持数据库主从配置,无需开发人员编码。beetlsql默认根据sql是查询还是更新决定去主从库,也可以根据事务决定数据库主从,如只读事务就去从库。beetlsql 既能适合一个初创项目,也适合项目飞速发展的巨大用户量情况。当然,超大用户量,这就超出了beetlsql的功能了。

 

 

 

 

OR Mapping

hibernate  : 实体,关系都通过配置完成OR Mapping,包含了一对多,多对多,继承等各种关系的实现。但正如我在一篇文章里吐槽过OR Mapping那样,尽管hibernate此项做的非常好,但没什么用。
myabtis : 实体,关系也通过配置来完成,但因为这是后期加的功能,所以用的并不好
beetlsql :支持实体映射,不支持关系映射,但支持关系映射查询,支持一对一,一对多,多对多的查询和懒加载

 

 

 

 

BeetlSQL一分钟介绍

由于beetlsql 是个新工具,所以简单用一个例子说明beetlsql

//初始化部分,通过跟框架结合,如通过spring ioc直接注入SqlManager

 

 

 

MySqlStyle style = new MySqlStyle();
MySqlConnectoinSource cs = new MySqlConnectoinSource();
SQLLoader loader = new ClasspathLoader("/org/beetl/sql/test");
SQLManager sql = new SQLManager(style,loader,cs,new DefaultNameConversion(), new Interceptor[]{new DebugInterceptor()});

 

//直接使用sqlmanager 的api操作
User user = ....;
sql.insert(user);
User query = new User();
query.setStatus(1);
List<User> list = sql.template(User.class,query);
// 查询user.sql 文件的mySelect sql模板
List<User> list = sql.select("user.mySelect",User.class,query) ;



beetlsql 也封装了SqlManager,提供了dao 接口

 

 

 

public interface UserDao extends BaseMapper<User> {

public User findById(@Param("id") Integer id);
public int getCount();
public void setUserStatus(User user);
public Integer setAge(@Param("id") Integer id,@Param("age") Integer age);

 

}

然后,在业务逻辑里可以这么使用,使得dao更容易维护

 

 

UserDao dao = sql.getMapper(UserDao.class);
dao.insert(user);  //使用BaseMapper 内置的方法
dao.setAge(12, 18); // 调用user.sql文件里的 setAge sql模板



user.sql 是一个md格式文件

 

setAge
===
* 更改用户年纪
update user set age = #age# where id=#id#
共有 人打赏支持
闲大赋
粉丝 935
博文 80
码字总数 70868
作品 9
评论 (20)
拐子
支持
拐子
beetl重度用户
jasonkavay
不错,不错,赞!博主,我们做了一个帮助博主推广博客的app叫同行说,只需复制文章链接即可发布给更多程序员们看到哦,欢迎体验哈,一起发扬分享精神~
redblueme
楼主给力~
你是红薯派来的逗逼吗
这得分图改的我给满分,毫无PS痕迹!
zzuqiang
感觉挺不错的、了解一下!!!
曾超0215
1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好
你的快递
对比比较片面, 明显偏向 #BeetlSQL#, #Hibernate#的特性讲的也太粗糙了. 理解博主作为#BeetlSQL#作者,为#BeetlSQL#说说好话.
yong9981
您好,我是jSqlBox ( https://git.oschina.net/drinkjava2/jSqlBox ) 项目的作者,能看一下这个项目吗?
其中有我个人对BeetlSql和其它一些常见持久化工具的横向评分比较,BeetlSql总体上做的还是不错的,但主要有以下问题:1)Sql不支持重构,如果字段名修改将不得不手一个个更正,不支持重构就抵消了ORM带来的好处,ORM的缺点和原生Sql的缺点两头都占全了。 2)引入模板语言也是一种侵入性 3)表和字段的配置是固定的,不能在运行期动态生成和修改。
闲大赋

引用来自“yong9981”的评论

您好,我是jSqlBox ( https://git.oschina.net/drinkjava2/jSqlBox ) 项目的作者,能看一下这个项目吗?
其中有我个人对BeetlSql和其它一些常见持久化工具的横向评分比较,BeetlSql总体上做的还是不错的,但主要有以下问题:1)Sql不支持重构,如果字段名修改将不得不手一个个更正,不支持重构就抵消了ORM带来的好处,ORM的缺点和原生Sql的缺点两头都占全了。 2)引入模板语言也是一种侵入性 3)表和字段的配置是固定的,不能在运行期动态生成和修改。
看了你对beetlsql的评价,总体评价还是很高,有些地方我有不同意见,第一,beetlsql支持orm查询而不像JAP那样全支持,但就orm查询来说,甚至比jpa,hibernate更强,你将beetlsql 和 不支持orm的dbutil 一个分数,这不对。在跨数据一样,比如统计分析函数,不同的数据库是不一样的,只能写不同的sql,JPA是无法完美做到的,beetlsql,则可以按照数据库类型来寻找特定sql

另外,你说sql重构,但就你的例子来说,你也并不支持sql重构,表明修改,列名修改无法通过重构工具完成,这点大家都是一样的

第三,你认为模板是侵入性,那你看看你实例代码里:
List users = Dao.queryForEntityList(User.class, select(), u.all(), ",", e.all(), from(), u.table(), ",",
e.table(), " where ", oneToMany(), u.ID(), "=", e.UID(), bind(u.EMAILS(), e.USER()));
谁对sql更有倾入性一目了然呢

另外,无论是mybatis还是beetsql,模板不是关键,关键是将sql单独在文件里维护,如beetlsql在md文件里维护,这样上百行的,带有复杂判断的 sql也一目了然。模板方式还为重构提供了可能,只是现在我没有精力去做一个sql文件的重构功能插件而已。

最后,我跟mybatis 是一派别,认为sql非常重要,我推测你和jooq,jpa是一派别,认为java很重要

yong9981
闲大赋您好,这个打分是比较主观的,我对ORM的评分标准是如果能将SqlResult映射到JavaBean上就有了基本的ORM了,dbutils是有这个功能的。如果不考虑成熟度,BeetlSQL应该和MyBatis一个等级,打3分确实偏低,BeetlSQL打分低主要是因为我不喜欢这种用法:List<ProductOrder> orders = (List<ProductOrder>)user.get("productOrder"); 这对重构支持不好,如果productOrder更名为goodsOrder怎么办? 要是写成user.get(ProductOrder.class)就好了。其它的回复我一并放在你的项目issue下了:http://git.oschina.net/xiandafu/beetlsql/issues/270,我们可以在那里讨论,谢谢。
青梅煮茶

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好
赞成!怀疑博主对Hibernate没有深入学习:smiley:
beykery

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好
其实在我看来,还没有出现能超越hibernate的orm,作者这个评分实在是。。。有点说不过去
beykery
看了这个文章我觉得是对hibernate深深的误解啊。
首先mybatis这种就不值得说了吧,在我看来基本上没啥优点,使用比较复杂。
hibernate被吐槽成这样我觉得不应该啊,hql可以很好的满足要求,加上它完善的缓存支持,差不多可以满足你绝大部分需求,如果实在是需要sql,其实也是可以获得原始的sql功能的。
至于hibernate那些复杂的关系,一对多多对多等,你也可以不用,其实它就是外键,并不好维护,直接舍弃就可以了。自己维护他们之间的关系。并没有带来什么复杂难懂的东西啊。
jaune161

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好
SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?
闲大赋

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好

引用来自“jaune”的评论

SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?
beetlsql 按照数据库类型管理sql,因此可以兼容任何数据库,而代码不需要变动,相对于hiberante,hql不可能兼容数据库,而写sql呢,需要在java代码里根据数据库类型用不同sql代码,所以,就多数据库来讲,hibernate得分并不高
曾超0215

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好

引用来自“jaune”的评论

SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?
支持多数据库是指一次编写,任何数据库都可以执行。 不是有多少数据库,写多少种类型的sql。
曾超0215

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好

引用来自“jaune”的评论

SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?

引用来自“闲大赋”的评论

beetlsql 按照数据库类型管理sql,因此可以兼容任何数据库,而代码不需要变动,相对于hiberante,hql不可能兼容数据库,而写sql呢,需要在java代码里根据数据库类型用不同sql代码,所以,就多数据库来讲,hibernate得分并不高
如果多一个项目要增加兼容一个数据库,按照你的管理方式,是不是需要把之前的几百甚至几千个sql按照新的数据库类型重写一遍。 这样的还叫兼容数据库吗,还叫跨数据库吗。 单单一个分页查询,就能让你修改到吐血了。 一次编写 随处运行的才叫兼容数据库。
闲大赋

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好

引用来自“jaune”的评论

SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?

引用来自“曾超0215”的评论

支持多数据库是指一次编写,任何数据库都可以执行。 不是有多少数据库,写多少种类型的sql。
并非是全写,只是写出不同的地方,这样可以接受,尤其是做产品的,部署在客户不同类型数据上
闲大赋

引用来自“曾超0215”的评论

1. 多数据库分数比hibernate要高,有点说不过去吧
2. Hibernate在同一个session中发送重复的数据库访问请求,会自动做缓存处理

对比还是要客观些的好

引用来自“jaune”的评论

SQL自己写的,理论上是可以兼容任何支持JDBC的数据库的,不是吗?

引用来自“闲大赋”的评论

beetlsql 按照数据库类型管理sql,因此可以兼容任何数据库,而代码不需要变动,相对于hiberante,hql不可能兼容数据库,而写sql呢,需要在java代码里根据数据库类型用不同sql代码,所以,就多数据库来讲,hibernate得分并不高

引用来自“曾超0215”的评论

如果多一个项目要增加兼容一个数据库,按照你的管理方式,是不是需要把之前的几百甚至几千个sql按照新的数据库类型重写一遍。 这样的还叫兼容数据库吗,还叫跨数据库吗。 单单一个分页查询,就能让你修改到吐血了。 一次编写 随处运行的才叫兼容数据库。
当然是只写出不同的部分就可以了,另外,hibernate并不能编写一次,用在不同的数据库上,除非你的应用太简单...
×
闲大赋
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: