mybatis和hibernate的区别

3月前发布

在java开发中我们用的两种两种主流框架组合为SSM,Spring,SpringMVC,MyBatis和SSH,Struts2,Spring,Hibernate.可见两种组合中都有Spring的参与,可见Spring是个至关重要的角色。今天我们先来看看两种数据库框架之间到底有什么区别。

那么这道面试题有多经典呢,经典到不具备任何专业能力HR可能都会问你这个问题,虽然她压根儿不知道答案!她会参照他们学的什么狗屁理论判断你回答问题的时候的紧张程度来判断你对这个问题的掌握程度。看上去有点扯,有时候总有几个倒霉蛋会碰上这种事情的。

先来看一下MyBatis的LOGO.

不知道这是个什么东西,好像愤怒的小鸟。下面是hibernate的

Hibernate看起来稍微有点严肃,它们在实际使用情况中是否也想表面上看上去那样子?

Mybatis不是一个完全ORM框架,什么是ORM框架呢?Hibernate就是ORM框架,开个玩笑。它的全名叫做Object Relational Mapping,Object 对象。Relational 关联的。Mapping映射。所以大概中文意思是对象关联映射?没有人在乎它叫什么名字,我们只关心它在使用过程中是一个怎样的东西。ORM就是将Java中的对象与数据库中的表关联对应起来。那么MyBatis也将mapper中的入参啊,结果集啊都封装到Java的Pojo类里面了,怎么还不算完全ORM框架呢?就这要说Hibernate到底有多优秀了,Hibernate的概念中Java对象拥有三种状态。瞬时状态,游离状态,持久状态,当这些状态发生改变时,Hibernate框架会自动的对数据库发送sql语句,从而完成对数据库的操作。是不是很神奇呢?这里也有一个小小的问题,有没有想要学习Hibernate的朋友,如果想的话请在评论中留言。因为相对于MyBatis,Hibernate更加的复杂,沉重。它有QBC,HQL,SQL三种查询方式,这也就意味着我们在sql语句优化时会遇到一定的困难,还要它的抽取策略,处理表的关系时也是尤为复杂。一般的中小型项目中,MyBatis的性能足以应付,所以现在中小公司大多数都会采用MyBatis这种技术来进行持久层的开发。

同时学习MyBatis的学习成本大大小于Hibernate,我们只需要编写原生的sql就能完完全全的将数据库的控制权掌握在自己手里,灵活度较高。但是我们在数据库进行移植时,会比较麻烦,如果将mysql的数据一直到oracle上,那么sql也要发生相应的变化,虽然有一种可能自动转换sql的软件,但是项目大的情况下也时很费心费力的,然后Hibernate不同。在它的配置文件里面可以选择数据库方言,意思就是说自动生成mysql还是oracle的sql语句。它能够自动处理数据库更换的情形,非常方便。同时MyBatis分别需要在mapper文件里或者通过注解的方式对每一个实体类编写sql语句,在大的也算是一种不小的工作量,这也就是大型复杂的项目中不适合应用MyBatis的原因。

针对不同方法中的冗余代码,MyBatis给出了一种解决方案叫做Mapper动态代理开发。请看下图,我们通过创建一个接口来调用MyBatis通过动态代理生成实现类。

创建了一个只有一个方法的接口,但是这个接口可不是随意创建的。下面我们再一下mapper文件,会发现 咦?

该接口的规则是1.首先接口的方法名与mapper文件中id名相同。2.入参与mapper中入参相同。3.返回值与mapper结果集类型相同。4.接口与mapper的namespace命名空间一致。下面我们创建接口的实现类

创建了吗?没创建啊,看图中的mapper是通过SqlSession.getMapper();创建的。那么该实现类拥有哪些方法?

它除了继承了Root类Object的方法,实现的只有我们刚刚才接口编写的方法。然后我们执行这个方法

已经查询到结果了,那么我们并没有使用sqlsession执行sql语句啊,到底在哪一步执行的呢?在方法mapper.findUserById()时,先找到接口UserMapper,通过方法名,入参类型等找到对应在mapper中的方法,根据参数及结果集的类型及数量自动调用执行sql语句。现在对比之前的是不是简化了很多呢?除此之外在接口内部的方法的入参返回值等我们可以用pojo的包装类型。意思就是说这次我们的上面例子的入参是ID,Integer类型,那么我如果想要把入参改成username呢?如果我们mapper文件中的入参改为User是不是就不需要在更换入参是修改mapper了呢?可以吗?当然可以了。因为MyBatis可以完成自动关联映射的。

接下来补充一下SqlMapConfig中的每个标签用法。

有一个properties标签,它是做什么用的呢。他能读取我们的配置文件,并转化为一种KV数据结构,从而我们在页面可以使用EL表达式通过K来读取V。请看下方图片

jdbc.driver就是Key,后面的com.mysql.jdbc.Driver就是我们的驱动全包名也就是V。其实面向对象也不一定要把所有的东西都封装起来,我本人更喜欢直接写在SqlMapConfig.xml页面里。可能因为有的人Linux环境下不会用vim编辑器改xml中的内容,所有他们会单独用一个文本格式储存数据库连接信息。

还要另一个标签叫做Settings,它是用来配置全局参数的,用途就是设置框架懒加载或二级缓存的。那么这里要说说什么是懒加载了,就是当数据未被访问时,不会去加载它,只有被访问到才加载。那么MyBatis一级缓存又是什么呢?一级缓存是将我们每一条与数据库连接的session内部查询到得数据做成快照,缓存到本地,和IE浏览器一样,当我们频繁访问同样数据时,第二次框架不会再去执行sql而是返回快照中的内容。二级缓存涉及到session跨域共享,通常我们使用redis数据库做分布式缓存。

下面我们看一下typeAliases这个标签

type属性是想要起别名的类,必须用全包名,我这个是比较简单的,正常的应该是com.xxx.package.className ,alias写想要取得别名然后我们在mapper文件中替换,请看下图

比较鸡肋的标签,有的人可能在会在这里使用拼音来作别名,我更喜欢使用全包名。Sun公司的人在研发java语言时核心思想就是使用全名,Java从来没有任何一个核心类库时英文缩写,见名知意。有使用过linux的朋友会知道,它的shell就有4种,内部命令更是全部缩写,有首字母缩写也有发音缩写,也有的缩写可能是通过摘要算法得出的,所以让人非常难以理解。必须说ls你可能想象不到它其实是list,完全不符合我们中国人语言逻辑,我们用的计算机,cpu,操作系统内核等全都是老外发明的,这让我们应用起来十分痛苦,如果有中文计算机的出现,那它的价值相对于平民百姓来说要远远高于所谓的什么天河二号,量子计算机等骗纳税人钱的幌子。

那么针对于Pojo包下,实体类过多的情况下,机智的开发人员相出了一套解决方案,请看下图

我们这里采用父包或基包的匹配机制,其包含该包下递归扫描所有子包。下面请看mapper中的写法

这里的别名因为我们不能手动指定,所有的别名都是类名的大小写通用。意思就是说可以写成uSEr或UsEr的形式,但是不可以颠倒顺序。其原理是字符串分割实现的。这种方法真的很方便啊,那么我们是否也能通过指定包名来指定mapper文件的位置呢?请看下图

我们指定mapper文件的方式有三种,还可以直接指定mapper包名。首先resource,需要写相对路径,url就是绝对路径。那么class是什么呢?class需要写我们mapper接口的全包名,我们找到接口以后有什么用,需要执行的sql语句又没有写在接口里。其实它还有一个附加条件,那就是接口名必须与mapper映射文件名相同,切存放于同一目录下。就是说我的接口名字叫做UserMapper,它的映射文件必须叫做UserMapper.xml。配置package也是同样的要求,也需要接口名与mapper文件名相同切位于同一目录下,这样它能递归扫描包下所有接口,在通过接口名找mapper文件,因为已经位于同一目录下了,所有只要加上.xml即可加载到mapper文件。

以上呢就是mybatis的基本使用方法了,大家有不明白的地方可以在下方回复,学习中工作中遇到的bug,问题等也可以在评论中提问。

举报/反馈
© 版权声明
THE END
喜欢就支持以下吧
点赞0 分享
评论 抢沙发

请登录后发表评论