书籍参考:《JavaEE互联网轻量级框架整合开发》 ——作者:杨开振 电子工业出版社
参考博客:https://blog.csdn.net/firejuly/article/details/8190229
MyBatis和Hibernate同为ORM框架,它们都有各自的特点,都是目前市面上比较流行的Java持久层框架,那么它们之间有什么不同,还有它们各自的优点和缺点又在哪里呢,下面慢慢道来。
MyBatis的优势在于灵活,它几乎可以代替JDBC,同时提供了接口编程,目前Mybatis的数据访问层DAO(Data Access Object)是不需要实现类的,它只需要一个接口和XML(或注解)。Mybatis提供自动映射,动态SQL,级联,缓存,注解,代码和SQL分离等特性,使用方便,同时也可以对SQL进行优化。因为它具有封装少,映射多样化,支持存储过程,可以进行SQL优化等特点,使得它现在成为Java互联网中首选的持久层框架
Hibernate也有它无可替代的优势,由于Mybatis和Hibernate都是持久层框架,都会涉及数据库,所以先定义一个数据库表——角色表(t_role)
根据这个角色表,我们再创建一个POJO和这张表对应起来
public class Role {
private Integer id;
private String roleName;
private String note;
/** setter and getter**/
}
无论是Mybatis还是Hibernate都是依靠某种方法,将数据库的表和POJO映射起来的,这样程序猿就可以操作POJO来完成相关的逻辑了。
要将POJO和数据库映射起来需要给这些框架提供映射规则,所以下一步要提供映射的规则,如图
在Mybatis或者Hibernate中都可以同XML或注解提供映射规则,这里采用XML方式
我们把POJO对象和数据库表相互映射的框架成为对象关系映射(Object Relational Mapping,俗称ORM)框架。Mybatis和Hibernate都是ORM框架,只是Hibernate是完全面向POJO的,而Mybatis则不是。
Hibernate基本不再需要编程SQL就可以通过映射关系来操作数据库,是一种全表映射的体现。而Mybatis则需要我们提供SQL去运行
先看看Hibernate将POJO和数据库表对应的映射文件
首先,对POJO和表t_role进行了映射配置,把两者映射起来了。然后,对POJO进行操作,从而影响t_role表的数据,比如对其增删查改,如下代码所示
Session session=null;
Transaction tx=null;
try{
//打开Session
session=HibernateUtil.getSessionFactory().openSession();
//开启事务
tx=session.beginTransaction();
//POJO
//增加
Role role=new Role();
role.setRoleName("rolename1");
role.setNote("note1");
session.save(role);
//查询
Role role2=(Role)session.get(Role.class, 1);
//修改
role2.setNote("备注");
session.update(role2);
//删除
session.delete(role2);
tx.commit();
}catch(Exception ex){
if(tx != null && tx.isActive()){
tx.rollback();
}
ex.printStackTrace();
}final{
if(session != null && session.isOpen()){
session.close();
}
}
这里我们并没有看到SQL语句,因为Hibernate会根据映射关系来生成对应的SQL语句,程序猿不必精通SQL语句,只要懂得操作POJO就能够操作对应的数据库表了。
这在管理系统时代是十分有利的。因为对于管理系统而言,首先在于实现业务逻辑,然后才是性能,所以Hibernate成为了那个时代的主流持久框架
Mybatis与Hibernate不同在于,Mybatis不屏蔽SQL语句,优势在于程序猿可以自己制定SQL语句,无需Hibernate自动生成规则,这样能够更加精确地定义SQL,从而优化性能。更符合目前移动互联网高并发,大数据,高性能,高响应的要求。
与Hibernate一样,Mybatis也需要一个映射文件把POJO和数据库对应起来,如下代码所示
delete from t_role where id = #{id}
insert into t_role(role_name,note) values (#{roleName},#{note})
update t_role
role_name = #{roleName}
note = #{note}
where id= #{id}
这里ResultMap元素用于定义映射规则,正式开发时候为了方便我们会使POJO和数据库字段之间满足一定规则,完成自动映射去省略掉ResultMap减轻开发量。
这里得注意,mapper元素中的namespace属性,它要和一个接口的全限定名一致,而里面的SQL的id也需要和接口定义的方法完全一致,如下定义一个接口用于文件映射
package com.learn.chapter1.mapper;
import com.learn.chapter1.pojo.Role;
public interface RoleMapper {
public Role getRole(int id);
public int deleteRole(int id);
public int insertRole(Role role);
public int updateRole(Role role);
}
定义好了接口,按我们以前的做法,是需要再为接口定义一个实现类。但是,在使用了Mybatis之后,就不需要再定义实现类了。完成增删查改的代码如下
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtil.getSqlSession();
RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
//查询
Role role=roleMapper.getRole(1);
//更新
role.setRoleName("new name");
roleMapper.updateRole(role);
//插入
Role role2=new Role();
role2.setRoleName("role2");
role2.setNote("备注");
roleMapper.insertRole(role);
//删除
roleMapper.deleteRole(5);
sqlSession.commit();
}catch(Exception ex){
ex.printStackTrace();
if(sqlSession!=null){
sqlSession.rollback();
}
}finally{
if(sqlSession!=null){
sqlSession.close();
}
}
比对一下显然MyBatis在业务逻辑上和Hibernate是大同小异的。其区别在于Mybatis需要提供接口和SQL语句,这意味着它的工作量会比Hibernate大,但是由于可以自定义SQL,映射关系,所以其灵活性,可优化性就超过了Hibernate。在互联网时代可优化性和灵活性是十分重要的,因为一条SQL语句的性能可能相差十几倍或几十倍,这对于互联网系统是十分重要的
在映射层而言,hibernate配置不需要接口和SQL,而Mybatis是需要的。
对于Hibernate而言,不需要编写大量的SQL,就可以完成映射,同时提供日志,缓存,级联等特性,此外还提供HQL对POJO进行操作,使用十分方便,但是它也有致命缺陷。
由于无需SQL,当多表关联超过3个时候,Hibernate的级联会造成太多性能的丢失,而且当关联的表多的时候,关联字段会根据特定的条件变化而变化,Hibernate无法支持这样的变化。性能最是关键,在互联网时代,如果响应过慢,会操作用户的丢失。
以上的问题,Mybatis就可以解决了,mybatis可以灵活定义查询语句,满足各种需求和性能优化的需要,这些是十分重要。但是Mybatis也有它的缺陷,Mybatis的工作量会比Hibernate大,通过手工编码,工作量会相对大些。