1.简介:
MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现,是一个基于Java的持久层ORM关系映射框架。需要使用的Jar包:mybatis-3.0.2.jar(mybatis核心包)。mybatis-spring-1.0.0.jar(与Spring结合包)。
MyBatis的前身是ibatis,但是在配置sql的语法上有明显的区别,并且spring目前的版本封装mybatis,至于mybatis-spring.jar文件也是mybatis团队复杂开发的jar包,用于和spring整合。之前ibatis的源码托管方是apache,而mybatis是google。
每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。
ORM关系映射:对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQ L 语句打交道,只需简单的操作实体对象的属性和方法。
2.原理流程
1.MyBatis应用程序Configuration对象根据XML配置文件或注解创建SqlSessionFactory工厂,获取一个SqlSession,加载SQL配置信息,生成一个个MappedStatement对象(包括传入参数映射配置、执行的sql语句、结果映射配置),并存储在内存中
2.SQL解析,SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句
(调用方法时,会接收到SQL的ID和传入对象,MyBatis会根据SQL的ID找到对应的MappedStatement,然后根据传入的参数对象对MappedStatement进行解析,解析后可以得到最终需要执行的SQL语句和参数)
3.SQL执行,完成对数据的增删改查,得到数据库操作结果
4.结果映射将操作结果按照映射配置进行转换,转换成HashMap、JavaBean等
5.事务提交,用完之后关闭SqlSession,返回结果。
开发流程:
3.环境搭建
A.添加依赖
mysql-connector-java-5.1.35、mybatis-3.4.1
B.设置主配置文件
config.xml文件放在resources文件夹底下
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <!-- 提供mybatis框架的常用设置,包括数据库数据源等 --> 6 <configuration> 7 <!-- 设置别名 --> 8 <typeAliases> 9 <!-- 设置某个实体类的别名 --> 10 <!-- <typeAlias type="com.rong.entity.Dept" alias="Dept"/> --> 11 <!-- 设置某个包中的类都支持别名,该包下的类的别名都会设置成去掉包名,只是用类名作为别名 --> 12 <package name="com.rong.entity"/> 13 </typeAliases> 14 15 16 <!-- 设置数据库数据源环境 可以多个 17 default表示默认使用的是哪个环境 18 --> 19 <environments default="mysqlEnvironment"> 20 <!-- 21 id:设置当前环境的身份id 22 transactionManager:设置事务管理器 type:设置用哪个事务管理器 JDBC是使用默认JDBC的事务管理自动提交 23 --> 24 <environment id="mysqlEnvironment"> 25 <transactionManager type="JDBC"></transactionManager> 26 <!-- 数据源配置 27 type:设置数据源的类型 POOLED表示使用连接池策略 28 --> 29 <dataSource type="POOLED"> 30 <property name="driver" value="com.mysql.jdbc.Driver"/> 31 <property name="url" 32 value="jdbc:mysql://localhost:3306/utf8?useUnicode=true&characterEncoding=utf-8"/> 33 <property name="username" value="root"/> 34 <property name="password" value="123123"/> 35 </dataSource> 36 </environment> 37 </environments> 38 <!-- 配置映射配置文件 没有配置,则会出现mapper失败的异常 39 resource:加载的映射配置文件路径 40 --> 41 <mappers> 42 <mapper resource="com/rong/dao/deptMapper.xml"/> 43 <mapper resource="com/rong/dao/deptVoMapper.xml"></mapper> 44 </mappers> 45 </configuration>
4.SqlSession实现CRUD
SqlSession sqlSession; @Before public void before() throws IOException{ //通过mybatis的api读取主配置文件 Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); //创建造SqlSessoin工厂的对象 SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); //造工厂 SqlSessionFactory sqlSessionFactory = factoryBuilder.build(reader); //生产sqlSession SqlSession类与JDBC的Connection类似 sqlSession = sqlSessionFactory.openSession();//开启事务 System.out.println(sqlSession.getConnection()); } @After public void after(){ sqlSession.commit(); sqlSession.close();//关闭连接资源 } @Test public void testSelect(){ //selectOne 查询结果为唯一对象的时候使用 statement参数为当前调用的sql映射文件中的sql语句对象id, //parameter 是参数 Dept dept = sqlSession.selectOne("findDept", 10); System.out.println(dept); } //int insert = sqlSession.insert("saveDept",dept ); //int update = sqlSession.update("updateDept", dept); //int delete = sqlSession.delete("deleteDept",110); */ @Test public void testFindAll(){ List<Dept> list = sqlSession.selectList("findAll"); for (Dept dept : list) { System.out.println(dept); } } @Test public void testFindMap(){ List<Object> list = sqlSession.selectList("findMap"); System.out.println(list); for (Object object : list) { Map<String,Object> map = (Map<String, Object>) object; Set<String> set = map.keySet(); for (String key : set) { System.out.print(key+":"+map.get(key)+" "); } System.out.println(); } }
1 /** 2 * dept模块的数据访问层接口 3 * Mapper映射器实现: 4 * 1.方法名必须与对应的mapper映射xml文件中的sql的id一致 5 * 2.映射xml文件的namespace必须与当前接口(Mapper映射器)的全限定名一致 6 * 3.通过sqlSession对象的getMapper(Mapper映射器) 获取映射器对象 mybatis会自动根据当前的接口 通过动态代理 7 * 生产子类对象,并且自动实现调用方法 8 * @author Administrator 9 * 10 */ 11 public interface DeptMapper { 12 13 Dept findDept(Integer id);//根据id查询部门 14 15 void saveDept(Dept dept); 16 17 void updateDept(Dept dept); 18 19 void deleteDept(Integer id); 20 21 List<Dept> findAll(); 22 23 List<Map<String,Object>> findMap(); 24 }
<!-- 提供了sql映射配置信息,mybatis通过该配置来实现数据库表和实体类之间的映射关系 mapper是整个sql映射配置文件的根元素 namespace:设置命名空间 应该与当前项目的模块中的dao接口全限定名对应 --> <mapper namespace="com.rong.dao.DeptMapper"> <!-- 根据id查询部门信息 sql文件是直接写在当前映射文件中的 select设置查询的SQL id:该sql的标记,是一个唯一标识 resultType:设置返回值类型 需要填写全限定名 com.rong.entity.Dept 或者是别名 Dept 使用别名需要先设置 parameterType:设置参数类型 参数个数唯一 可以是全限定名或者是mybatis提供的简写类型 #{deptno}是mybatis的表达式 #{}是占位符 deptno是传入的参数 单一个参数,mybatis会自动传递过来赋值 使用java提供的类型的全限定名 可使用简写 如 java.lang.Integer ->integer 首字母改小写 --> <select id="findDept" resultType="Dept" parameterType="integer"> select deptno,dname,loc from dept where deptno=#{deptno} </select> <!-- insert用于插入sql操作 当执行该sql,mybatis会根据#{deptno}从当前传入的对象上调用get方法获取该属性值 ,所以需要属性与括号中的值对应 --> <insert id="saveDept" parameterType="Dept"> insert into dept values(#{deptno},#{dname},#{loc}) </insert> <update id="updateDept" parameterType="Dept"> update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno} </update> <delete id="deleteDept" parameterType="integer"> delete from dept where deptno=#{deptno} </delete> <!-- 查询所有记录 resultType为当前一条记录对应的java的类型 --> <select id="findAll" resultType="Dept"> select deptno,dname,loc from dept </select> <!-- 查询一张表中的部分字段信息 或 多张表关联查询的结果 可以通过 返回map来实现 --> <select id="findMap" resultType="hashMap"> select dname,loc from dept </select> </mapper>
5.结果对象属性与数据库表字段不一致情况
<mapper namespace="com.rong.dao.DeptVoMapper"> <select id="findDeptVo" parameterType="integer" resultMap="deptMap"> select deptno,dname,loc from dept where deptno=#{deptno} </select> <insert id="saveDeptVo" parameterType="DeptVo"> insert into dept values(#{id},#{deptName},#{location}) </insert> <!-- resultType:当数据库表字段与实体类的属性名一致的情况下,mybatis会自动的生成一个resultMap来实现对应的关系映射 resultMap自定义关系映射 : 当结果对象的属性与数据库表字段不一致的情况下,需要自己指定关系映射 type:设置哪个实体类进行关系映射 id:唯一标记 result:设置当前的某个数据库字段与实体类某个属性的对应关系 property:设置属性 column:设置字段 javaType:该属性的类型 可以全限定名或简写(类名首字母小写) 基本数据类型情况下可以忽略 jdbcType:该字段的数据库类型 必须使用指定的数据库类型名(全大写) 基本数据类型情况下可以忽略 --> <resultMap type="DeptVo" id="deptMap"> <result property="id" column="deptno" javaType="integer" jdbcType="INTEGER"/> <result property="deptName" column="dname" javaType="string" jdbcType="VARCHAR"/> <result property="location" column="loc" /> </resultMap> </mapper>
MyBatis实现分页查询
/** * 分页功能,通过mybatis的api实现 * selectList("findAll",null,new RowBounds(0, 2)):带三个参数的方法 第一个参数是sql的id 第二个参数是条件 * 第三个参数是rowBounds对象 * 查询所有部门信息,每页显示两条,显示出第一页 */ @Test public void testFindByPage(){ List<Dept> list = sqlSession.selectList("findAll",null,new RowBounds(0, 2)); for (Dept dept : list) { System.out.println(dept); } }
6.Mapper映射器
接口中的方法和映射文件中定义的语句一一对应。接口方法的名称必须和语句id完全相同,接口方法的返回值和参数和相应的语句相对应
将映射文件的命名空间改为对应的映射文件的类名
SqlSession上调用getMapper方法,并传入要获取的Mapper类
SqlSession sqlSession; DeptVoMapper mapper; @Before public void before(){ sqlSession = MybatisUtil.openSession(); mapper = sqlSession.getMapper(DeptVoMapper.class); } @After public void after(){ sqlSession.commit(); sqlSession.close(); } @Test public void testFindVo(){ DeptVo deptVo = mapper.findDeptVo(10); System.out.println(deptVo); }