在学习MyBatis之前,我们需要先了解一下传统的JDBC编程,整个过程分为以下几步;
1,使用JDBC编程需要连接数据库,注册驱动和数据信息;
2,操作Connection,打开Statement对象;
3,通过Statement执行SQL,返回结果到ResultSet对象;
4,使用ResultSet读取资源,然后通过代码转化为具体的POJO对象;
5,关闭数据库相关资源;
使用传统的JDBC方式存在一些弊端,其一,工作量相对较大,我们需要先连接,然后处理JDBC事务, 还要负责数据类型转换,操作Connection对象,Statement对象,其二,我们要对JDBC编程可能产生的异常进行捕捉和处理;
而作为改进版的ROM框架,则是将数据库中的表和简单的JAVA 对象进行映射,这样的话,我们就无需对数据库的相关知识深入了解,便可以写出通俗易懂的程序,ORM还提供了同一的规则使得数据库的数据通过配置便可轻易映射到POJO上;
而作为ORM框架中的经典框架:Hibernate和MyBatis,这篇主要讲一下MyBatist框架,先说明一下为什么要用MyBatis而不用Hibernate,Hibernate的缺点:
1,全表映射带来的不便,比如更新时需要发送所有的字段;
2,无法根据不同的条件组装不同的SQL;
3,对多表关联和复杂SQL查询支持较差,需要自己写SQL,返回后,需要自己将数据组装为POJO;
4,不能有效支持存储过程;
5,虽然有HQL,但是性能较差,大型互联网系统往往需要优化SQL,而Hibernate做不到;
总结:对复杂的查询支持较差,不支持存储过程,很难优化;
下面是关于MyBatis的一个简单实例;
1,首先,我们需要有一个SqlSessionFactory来实现生成一个SqlSession会话,相当于一个工厂,我们知道,作为数据库连接框架,不管如何,我们都需要有一个数据连接源,里面存储着连接这个项目的数据库的相关参数信息,然后,我们把这些信息配置在xml文件中,然后用一个SqlSessionFactoryUtils工具类去把信息配置到SqlSessionFactory中,也就是说,将SqlSessionFactoryUtils比作一个是工厂的话,那么参数信息就相当于工厂的位置信息了,
2,然后,我们还需要通过你这个SqlSessionFactory工厂类来创建一个SqlSession会话,这个会话相当于JDBC中的connection对象,用来将你在项目中的操作信息进行会话式的保存,以及最后的提交和关闭。
3,最后,我们说了,ORM是基于面向对象的编程,所以我们还要有一个对象映射器来将数据库的对象与POJO数据模型进行映射来达到ORM的效果,同时,我们还需要定义接口来对应映射器中的每一次SQL操作,而这个接口是不需要有实现类的,可以看作,通过xml配置的映射器其实已经转化为了这些接口的实现类,所以我们还需要一些对应关系,像是哪一个映射器对应哪一个接口,如果接口要传入参数,映射器也要有相应类型的参数,返回什么类型的参数这三个方面要做好对应关系;
废话不多说,直接上代码;
首先是数据库信息源配置信息;
mybatis-config.xml
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd.mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias = "role" type = "com.learn.chapter2.po.Role"/> </typeAliases> <environments default = "development"> <environment id = "development"> <transactionManager type = "JDBC"> <property name = "autoCommit" value = "false"/> </transactionManager> <dataSource type = "POOLED"> <property name = "driver" value = "com.mysql.jdbc.Driver"/> <property name = "url" value = "jdbc:mysql://localhost:3306/mybatis"/> <property name = "username" value = "root"/> <property name = "password" value = "learn"/> </dataSource> </environment> </environments> <mappers> <mapper resource = "com/learn/chapter2/mapper/roleMapper.xml"/> </mappers> </configuration>
下面这个是SqlSessionFactory类的底层实现原理;里面提到了如何通过SqlSessionFactory类创建SqlSession类;
public class SqlSessionFactoryUtil{ private static SqlSessionFactory sqlSessionFactory = null; private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class; private SqlSessionFactoryUtil(){} public static SqlSessionFactory initSqlSessionFactory(){ String resource = "mybatis-config.xml"; InputStream inputStream = null; try{ inputStream = Resources.getResourceAsStream(resource); }catch(IOException e){ Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SEVERE,null,ex); } synchronized(CLASS_LOCK){ if(sqlSessionFactory == null){ sqlSessionFactory = new SqlSessionFactoryBuilder().build(input Stream); } } return sqlSessionFactory; public static SqlSession openSqlSession(){ if(sqlSessionFactory == null){ initSqlSessionFactory(); } return SqlSessionFactory.openSession(); } } }
接下来是一个POJO类,用来做映射用的;
public class Role{ private long id; private String roleName; private String note; public Long getId(){ return id; } public void setId(Long id){ this.id = id; } public String getRoleName(){ return roleName; } public void setRoleName(String roleName){ this.roleName = roleName; } public String getNote(){ return note; } public void setNote(){ this.note = note; } }
接下来我们还需要一个映射器;RoleMapper.xml;
<?xml version = "1.0" encoding = "UTF-8"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper.dtd"> <mapper namespace = "com.learn.chapter2.mapper.RoleMapper"> <select id = "getRole" parameterType = "long" resultType = "role"> select id ,role_name as roleName,note from t_role where id = #{id} </select> <insert id = "insertRole" parameterType = "role"> insert into t_role(role_name,note) values (#{roleName},#{note}) </insert> <delete id = "deleteRole" parameterType = "long"> delete from t_role where id = #{id} </delete> </mapper>
然后,我们还需要一个接口,注意接口的方法要和XML映射文件的id保持一致;
public interface RoleMapper{ public Role getRole(Long id); public int deleteRole(Long id); public int insertRole(Role role); }
而最后,我们只需要一个Main方法来调用整合就行了;
public class Chapter2Main{ public static void main(String[] args) throws Exception{ SqlSession sqlSession = null; try{ sqlSession = SqlSessionFactoryUtils.openSqlSession(); //这里的RoleMapper.class是一个接口类来的; RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Role role = new Role(); role.setRoleName("testName"); role.setNote("testnote"); roleMapper.insertRole(role); roleMapper.deleteRole(1L); sqlSession.commit(); }catch(Exception e){ System.err.println(ex.getMessage()); sqlSession.rollback(); } finally{ if(sqlSession != null) sqlSession.close(); } } }