MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

实现基本的数据库操作功能的流程如下:

  1. 编写xml文件,配置运行环境。
  2. 通过IO流载入xml文件,创建SqlSessionFactory对象(会话工厂)。
  3. 由会话工厂,创建SqlSession对象(会话)。
  4. 通过SqlSession对象,操作数据库。注意增删改操作需要提交事务,否则对数据库做出的修改不会更改数据库中的记录。
  5. 最后需要关闭SqlSession对象和IO流,释放资源。

一、xml配置文件

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

1.MybatisConfig.xml

Mybatis的全局配置文件,主要用于配置Mybatis的运行环境(事务管理器、数据源等)。具体详情可见Mybatis说明文档

下面通过一个简单的示例,来简要说明这个配置文件。

 <?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>
<!--引入外部properties文件 -->
<properties resource="db.properties"></properties>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="url" value="${url}"/>
<property name="driver" value="${driver}"/>
<property name="poolMaximumActiveConnections" value="${maxActive}"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
  1. 头文件(1~2行):第1行是xml声明,声明该xml文件的字符集为UTF-8;第2行是DTD文件类型声明(外部DTD),用于约束该xml文件的结构。引用的DTD约束的格式为<!DOCTYPE 根元素 SYSTEM "DTD文件路径">(本地文件),或<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件URL">(公共文件),这里是约束configuaration元素的结构为链接中的DTD文件所约束的那样。
  2. properties元素(5行):这里是用于引入外部properties文件。其实还可以在properties元素中定义一些属性,但不建议这么做,最好还是把所有属性放在外部文件中。
  3. environments元素(7~20行):用于配置要创建的SqlSessionFactory实例的环境。每个数据库对应一个SqlSessionFactory实例,每个SqlSessionFactory实例只能选择一种环境(environments元素中可以定义多个environment元素)。
    • 第7行:默认的环境id。
    • 第8行:定义一个environment元素,并设定环境id。
    • 第10行:事务管理器的配置,可选"JDBC"或"MANAGED"。【注:Spring+Mybatis不需要配置事务管理器,因为Spring会用自带管理器覆盖这些配置】
      • "JDBC":直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
      • "MANAGED":不提交或回滚一个连接,而是让容器来管理事务的整个生命周期,默认情况下它会关闭连接。
    • 第12~18行:数据源的配置。第12行是配置数据源类型,内置了"UNPOOLED","POOLED"和"JNDI";第13~18行是设定数据源。
      • "UNPOOLED":不使用数据库连接池。只有driver,url,username,password,defaultTransactionIsolationLevel五个属性,其中最后一个属性是指默认的连接事务隔离级别。
      • "POOLED":使用数据库连接池。除了"UNPOOLED"中的5个属性之外,还多了一些连接池属性,比如poolMaximumActiveConnections(最大活动连接数)、poolMaximumIdleConnections(最大空闲连接数)等(详见说明文档)。
      • "JNDI":为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。只需"initial_context"和"data_source"两个属性。
      • 另外,也可以将type设置为一个数据源类,使用任何第三方数据源。
  4. mappers元素(22~24行):用于设定映射文件路径。可以通过classpath相对路径、文件系统绝对路径设定映射文件,还可以通过类名、包名设定映射接口。

2.StudentMapper.xml

sql映射文件,主要用于实现数据库操作的具体细节。此文件需要在MybatisConfig.xml中加载。

下面通过一个简单的示例,来简要说明这个配置文件。

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.cage.student.StudentDAO"> <insert id="addStu" parameterType="cn.cage.student.Student">
INSERT INTO students
(name,qq,major,entrytime,gra_school,id_jnshu,daily_url,desire,bro_jnshu,knowfrom)
VALUES
(#{name},#{qq},#{major},#{entryTime},#{school},#{jnshuId},#{dailyUrl},#{desire},#{jnshuBro},#{knowFrom})
</insert> <delete id="delStuById" parameterType="long">
DELETE FROM students WHERE
id=#{id}
</delete>
<delete id="delStu" parameterType="cn.cage.student.Student"></delete> <update id="updateStu">
UPDATE students SET
name=#{stu.name},qq=#{stu.qq},major=#{stu.major},entrytime=#{stu.entryTime},gra_school=#{stu.school},id_jnshu=#{stu.jnshuId}
,daily_url=#{stu.dailyUrl},desire=#{stu.desire},bro_jnshu=#{stu.jnshuBro},knowfrom=#{stu.knowFrom}
WHERE id=#{id}
</update> <select id="queryStuById" resultMap="stuMap">
SELECT
id,create_at,update_at,name,qq,major,entrytime,gra_school,id_jnshu,daily_url,desire,bro_jnshu,knowfrom
FROM students WHERE id=#{id}
</select>
<select id="queryStuByName" resultMap="stuMap">
SELECT
id,create_at,update_at,name,qq,major,entrytime,gra_school,id_jnshu,daily_url,desire,bro_jnshu,knowfrom
FROM students WHERE name=#{name}
</select>
<select id="queryStuByJnshu" resultMap="stuMap">
SELECT
id,create_at,update_at,name,qq,major,entrytime,gra_school,id_jnshu,daily_url,desire,bro_jnshu,knowfrom
FROM students WHERE major=#{major} and id_jnshu=#{jnshuId}
</select>
<select id="queryStu"></select> <resultMap type="cn.cage.student.Student" id="stuMap">
<constructor>
<arg column="name" javaType="String" jdbcType="VARCHAR" />
<arg column="major" javaType="String" jdbcType="VARCHAR" />
<arg column="id_jnshu" javaType="int" jdbcType="INTEGER" />
</constructor>
<id property="id" column="id" />
<result property="createTime" column="create_at" />
<result property="updateTime" column="update_at" />
<result property="qq" column="qq" />
<!-- 此处虽然javaType为String,jdbcType为DATE,但并不需要特别的转换就可以映射 -->
<result property="entryTime" column="entrytime" />
<result property="school" column="gra_school" />
<result property="dailyUrl" column="daily_url" />
<result property="desire" column="desire" />
<result property="jnshuBro" column="bro_jnshu" />
<result property="knowFrom" column="knowfrom" />
</resultMap> </mapper>

>>关于类文件的别名:在MybatisConfig.xml的Configuration中,添加属性typeAlias即可:

<typeAlias type="cn.cage.Student" alias="Student"/>
  1. 头文件(1~2行):同上,这里是约束mapper元素的结构为链接中的DTD文件所约束的那样。
  2. 命名空间(3行):最基本的意义,是给这个mapper命名用于区分;更为高级的用法,则是接口绑定(面向接口编程)。namespace的命名方式分为两种:完全限定名和短名称。本例中使用的就是完全限定名。使用短名称时,必须确保这个短名称在系统中是唯一的,否则只能使用完全限定名。
    • 接口绑定:将namespace设为DAO接口,将接口中的方法都通过mapper中的元素实现(元素id与接口方法一一对应),就可以不用写DAO实现类,Mybatis会通过绑定自动找到要执行的sql语句。
  3. mapper顶级元素(4~61行):mapper中有8个顶级元素,分别是insert,delete,update,select(映射增删改查语句),sql(重用sql语句块),resultMap(描述如何从结果集中加载对象),cache(缓存配置),cache-ref(其他namespace缓存配置)。
    1. insert、delete、update(5~23行):基本格式就是<元素名 元素属性>sql语句</元素名>。其中,元素名即为insert/delete/update中的一个,可设定的元素属性有9个,这里只列出5个,一般设定1,2即可。在sql语句中,用#{}表示占位符,执行时将#{}替换为?,然后将括号内的参数传递给?。
      常用元素属性:(详见说明文档
      1. id:元素标识。
      2. parameterType:接受的参数类型,可为完全限定名或别名。默认为unset。传入多个参数时,这个属性应忽略,在#{}中直接以各参数名表示。(如:18~23行)
      3. flushCache:为true时,调用sql会清空本地缓存和二级缓存。在insert,delete,update中默认为true,在select中默认为false。
      4. timeout:驱动程序等待数据库返回结果的最大时间,超出则抛出异常。默认为unset。
      5. statementType:可选STATEMENT/PREPARED/CALLABLE,分别让Mybatis使用Statement,PreparedStatement,CallableStatement。默认为PREPARED。
    2. select(25~40行):基本格式同上。select可设定的元素属性有13个,除了上述的5个属性之外,还有2个常用属性。当数据库列名与POJO属性名不一致时,可以在sql语句中使用别名(as),或使用resultMap。
      1. resultType:此select语句的返回值类型。如果返回集合,应该写集合包含的类型。
      2. resultMap:外部resultMap的引用。和resultType不能同时使用。
    3. resultMap(42~59行):基本属性有id,type和autoMapping,分别是本resultMap的标识,对应的POJO类,是否自动映射。
      resultMap有6个可用元素:(详见说明文档
      1. constructor:在类实例化时,注入结果到构造方法中。其中,idArg是ID参数(详见下一条),arg是注入到构造函数的普通结果。
        其中,idArg和arg常用属性如下:

        • column:对应数据库中的列名。
        • javaType:完全限定名/别名。映射到HashMap时必须指定,其他时候可以省略。
        • name:构造函数的形式参数名。
      2. id:id会将结果标记为标识符(给结果取个名字),以便在比较对象时使用。这可以提升整体性能,特别是缓存和嵌入结果映射(比如联合映射) 。
      3. result:注入到属性的普通结果。
        id和result的常用属性如下:
        • property:POJO类中的属性名。
        • column:对应数据库中的列。
        • javaType:完全限定名/别名。映射到HashMap时必须指定,其他时候可以省略。
      4. association:关联。
      5. collection:集合。
        主要处理多个表之间的联合映射。
      6. discriminator:鉴别器。可以根据某一列结果的值的不同,来决定接下来的行为(比如将另一列的结果映射到某个POJO属性)。
        4,5,6三个属性本例中无需使用,暂不详细介绍。详情见说明文档

二、Java代码

通过StudentMapper.xml进行DAO接口绑定后,不需要编写接口的实现类,就能直接根据接口规定的参数列表传入参数,进行数据操作。值得注意的是,如果不编写实现类的话,接口中增删改函数的返回值设定是无用的,只能返回SqlSession类中对应函数指定的返回值类型。

数据库操作在代码中的实现步骤大体如下:

  1. 创建IO流,通过Resources类中的getResourceAsStream方法载入全局配置文件(MybatisConfig.xml)。
  2. 由SqlSessionFactoryBuilder对象的build方法,创建SqlSessionFactory对象。
  3. 由SqlSessionFactory对象的openSession方法,创建SqlSession对象。
  4. 由SqlSession对象,操作数据库。
  5. 关闭SqlSession对象,然后关闭IO流。

下面主要讲解一下通过SqlSession对象操作数据库的内容。

1.SqlSession类中的常用方法

目前主要用到过的方法有:

  1. insert,delete,update:对数据库进行增/删/改操作。注意:进行了这些操作之后,必须调用commit()提交事务,否则数据库记录不会改变。
    返回值:int,操作所影响的行数。
    参数:("sqlID",param):
    1. sqlID:StudentMapper.xml中对应的sql元素的id,若有多个mapper,可以通过mapper.sqlID的形式指定。
    2. param:若对应的接口函数只需要传入一个参数,直接将这个参数传入即可。【最好用变量的形式传入。直接传常量可能会导致类型转换异常】
      若需传入多个参数,则应该用HashMap<String,Object>传入参数。其中,String是mapper.xml中的参数名(#{xx}),Object是参数值。将多个参数放入map后,将map作为参数传入即可。
  2. commit():刷新批处理语句并提交数据库连接。在增删改之后必须调用。
  3. selectOne("sqlID",param):参数意义同上。返回值:mapper.xml中规定的返回值类型。
  4. selectList("sqlID",param):同上。返回值:List<E>,其中E为mapper.xml中规定的返回值类型。
  5. close():关闭会话,释放资源。

2.注意事项

  1. POJO类中的构造方法的参数类型,如果是基本数据类型,应该写成其包装类的形式(比如int写为Integer)。因为mapper.xml中的javaType会自动转为完全限定名(比如int转为java.lang.Integer)。如果在resultMap中定义了constructor元素,映射到POJO类时会是完全限定名的类型,如果构造方法中的参数类型不是包装类,就会报错(找不到参数类型为xxx的构造函数)。
  2. 务必在insert/delete/update之后执行commit!否则一切操作都不会在数据库中生效!

最后,对上述内容举例说明:上述配置文件的测试代码。

 /**
* @FileName:MybatisStuImpl.java
* @description:
* @author Cage Yang
* @version
* Modified Date:2017年8月23日
* Why & What is modified: <修改原因描述>
*/
package cn.cage.student; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test; /**
* @ClassName MybatisStuImpl
* @description 测试通过Mybatis接口绑定自动生成的数据操作类的运行情况。
* @author Cage Yang
*/
public class MybatisStuImpl {
static InputStream in = null;
static SqlSession sqlSession = null; /**
* @description 创建出SqlSession实例
* @throws java.lang.Exception
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
String resource = "MybatisConfig.xml";
in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
sqlSession = sqlSessionFactory.openSession();
} /**
* @description 释放资源
* @throws java.lang.Exception
*/
@AfterClass
public static void tearDownAfterClass() throws Exception {
sqlSession.close();
in.close();
} @Test
public void testAddStu() {
Student stu = RandomStudent.getStudent();
stu.setMajor("java");
stu.setJnshuId(1501);
assertEquals("插入失败!", 1, sqlSession.insert("addStu", stu));
sqlSession.commit();
HashMap<String, Object> param = new HashMap<String, Object>();
param.put("major", "java");
param.put("jnshuId", 1501);
Student stu2 = sqlSession.selectOne("queryStuByJnshu", param);
assertEquals("插入错误,或查询byJnshu出错", stu, stu2);
} @Test
public void testDelStuById() {
long id = 4;
Student student = sqlSession.selectOne("queryStuById", id);
System.out.println(student.getEntryTime());
assertEquals("删除失败!", 1, sqlSession.delete("delStuById", id));
sqlSession.commit();
assertNull("删除错误,或查询byId出错", sqlSession.selectOne("queryStuById", id));
} @Test
public void testUpdateStu() {
long id = 5;
Student stu = sqlSession.selectOne("queryStuById", id);
stu.setDesire("哈哈哈哈哈哈哈哈");
HashMap<String, Object> param = new HashMap<String, Object>();
param.put("stu", stu);
param.put("id", id);
assertEquals("更新失败!", 1, sqlSession.update("updateStu", param));
sqlSession.commit();
assertEquals("更新错误,或查询byId出错", "哈哈哈哈哈哈哈哈", ((Student) sqlSession.selectOne("queryStuById", id)).getDesire());
} @Test
public void testQueryStuByName() {
List<Student> list = sqlSession.selectList("queryStuByName", "王五");
for (Iterator<Student> iterator = list.iterator(); iterator.hasNext();) {
Student student = (Student) iterator.next();
if (student.getJnshuId() == 1111) {
assertEquals("查询byName出错", "2017-08-06", student.getEntryTime());
}
}
}
}

JUnit4测试代码

三、与Spring-JdbcTemplate的比较

1.Mybatis必须用IO流载入xml配置文件,JdbcTemplate可以直接载入。

2.Mybatis可以无需编写数据操作类、通过配置文件绑定接口,JdbcTemplate必须编写类实现数据操作接口。

3.Mybatis可使用自带数据源类,JdbcTemplate只能使用外部数据源类。

4.mapper中的元素:增删改查元素对应StudentDAOImpl中的各实现方法,resultMap对应JdbcTemplate中的QueryStuRowMapper。

Mybatis说明文档:http://www.mybatis.org/mybatis-3/zh/getting-started.html

l

MyBatis框架概述的更多相关文章

  1. 03 Mybatis框架---学习笔记1--框架的概念及优势

    1.框架的概念 框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统.简单说就是使用别人搭好的舞台,你来做表演.而且,框架一般是成熟的,不断升级的软件.框架是我们软件开发中的一套解决方 ...

  2. Mybatis框架(未完待续)

    1.框架概述:                        它是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题.好处:框架封装了很多的细节,使开发者可以使用极简的方式实现功能.大大提高开 ...

  3. SSM(Spring+SpringMVC+Mybatis)框架环境搭建(整合步骤)(一)

    1. 前言 最近在写毕设过程中,重新梳理了一遍SSM框架,特此记录一下. 附上源码:https://gitee.com/niceyoo/jeenotes-ssm 2. 概述 在写代码之前我们先了解一下 ...

  4. (转)MyBatis框架的学习(二)——MyBatis架构与入门

    http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图: 下面作简要概述: S ...

  5. Spring Boot:整合MyBatis框架

    综合概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单 ...

  6. Mybatis框架(9)---Mybatis自定义插件生成雪花ID做为表主键项目

    Mybatis自定义插件生成雪花ID做为主键项目 先附上项目项目GitHub地址 spring-boot-mybatis-interceptor 有关Mybatis雪花ID主键插件前面写了两篇博客作为 ...

  7. 1、MyBatis框架底层初涉

    1.拜年 哈哈,现在是过年了,祝大家新年好. 本来大过年的是不打算碰电脑的,(抢票除外,三疯同学现在还没抢到票,然后突然又延长假期了).现在疫情严重,被堵家里不能出去了.不能为国家做贡献,但是起码不能 ...

  8. MyBatis框架基础详细开发流程

    MyBatis 项目已托管到GitHub,大家可以去GitHub查看下载!并搜索关注微信公众号 码出Offer 领取各种学习资料! 一.框架概述 1.1 什么是框架? 软件的半成品,解决了软件开发过程 ...

  9. SpringBoot+MySQL,如何整合并使用MyBatis框架

    概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. MyBatis 可以使用简单的 ...

随机推荐

  1. awk打印第n个参数到最后一个技巧/将n行组成一列

    打印第n参数到最后一个参数 文本的NF不等,即字段长度不固定,想截取从$3到$NF 第一反应是使用循环 [root@localhost ~]# echo "1 2 3 4 5" | ...

  2. 什么是Servlet,Servlet的作用,生命周期,如何创建、配置Servlet

    什么是Servlet,作用是? servlet是一个基于java技术的WEB组件,运行在服务器端,我们利用 sevlet可以很轻松的扩展WEB服务器的功能,使它满足特定的应用需要.servlet由se ...

  3. Django中不返回QuerySets的API -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  4. 15_Python函数名本质

    函数名的本质 函数名实质上就是函数的内存地址 def wrapper(): pass print(wrapper) 1.引用是什么? 当我们定义a=1的时候,系统会开辟一块内存空间来保存1,然后用a变 ...

  5. 细说Django的admin

    在admin.py中只需要将地Model中某个类注册,即可在Admin中进行增删查改的功能,例如: admin.site.register(models.UserInfo) 这种方式比较简单,如果想要 ...

  6. iOS-Wonderful 完美颜色库

    开发中颜色的使用也是非常频繁的,这里推荐一个dsxNiubility大牛写的颜色库:Wonderful:它的好用就是很清楚的把每个常用的颜色进行了由浅到深的分层,让我们使用时可以根据自己对颜色的深浅直 ...

  7. getopt for windows

    Glibc库里有个getopt用于解析命令行参数,挺方便的,下面的是别人从Glibc源码的获取的几个getopt相关的文件,已经将平台相关的修改掉,windows下可以调用,本来是要用没用到就没去看正 ...

  8. BZOJ 2055: 80人环游世界 [上下界费用流]

    2055: 80人环游世界 题意:n个点带权图,选出m条路径,每个点经过val[i]次,求最小花费 建图比较简单 s拆点限制流量m 一个点拆成两个,限制流量val[i],需要用上下界 图中有边的连边, ...

  9. Angular+ionic2+Echarts 实现图形制作,以饼图为例

    step1:添加插件echart; npm install echarts --save package.json文件中会在dependencies中添加echarts,如下图: step2:运行cm ...

  10. JDBCTemplate与模板设计方法(二)

    前言:上一篇博客介绍了模板方法模式,并且给出了一个小demo,简单对模板方法进行了实现,接下来我们把目光转向spring的源码JDBCTemplate,看一看spring是如何对jdbc进行高度封装的 ...