30分钟入门MyBatis

本文旨在用最通俗的语言讲述最枯燥的基本知识

当项目框架SSH(spring Struts hibernate)日落西山时,SSM(spring SpringMVC、MyBatis)就大行其道,大部分项目都渐渐转至SSM,所以mybatis也成了Java程序员的必学之术,本文就mybatis的语法作一次小小的总结,旨在让读者用最少的时间学会使用MyBatis。java

文章提纲:mysql

  1. 什么是MyBatis
  2. MyBatis的引入
  3. MyBatis的初始化配置
  4. MyBatis的SQL语法
  5. 运行原理和实操一波

1. 什么是MyBatis

MyBatis的前身是Apache的一个开源项目ibatis,后来迁移到Google code就更名为MyBatis。程序员

用网上已经说烂了的话来讲就是:spring

MyBatis是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎全部的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。sql

2. MyBatis的引入

  1. 若是是传统的的项目,则直接下载相应jar包引入到项目中便可,下载地址为:
http://central.maven.org/maven2/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar
  1. 若是为maven构建的项目,则只须要在pom.xml中加入如下依赖而后reimport一下便可:
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>
  1. 若是是gradle构建的项目,则只须要在配置中添加如下代码:
// https://mvnrepository.com/artifact/org.mybatis/mybatis
compile group: 'org.mybatis', name: 'mybatis', version: '3.4.6'

3. MyBatis的配置和初始化

在引入mybatis以后,接下来须要学习的mybatis的配置,虽然如今流行的框架像springboot等已经不须要用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>
        <!--定义一个变量为driver的属性,在下面就能够用${driver}来得到其属性值-->
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://10.0.0.111/test"></property>
    </properties>
    <!--定义不一样环境下的配置,便于区分生产、测试等环节的配置-->
    <environments default="development">
       <!--定义一个环境下的配置-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="root"/>
                <property name="password" value="1111"/>
            </dataSource>
        </environment>
    </environments>
    <!--用于设置mapper文件的引入-->
    <mappers>
        <!--resource方式引入mapper文件-->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

这是一个标准的mybatis的配置文件,不少状况下,这个配置已经,可是为了在之后的使用有更好的认识,下面讲解配置文件中configuration标签下的经常使用子标签:编程

  1. properties标签:用于定义一些通用属性,便于配置文件中使用
  2. settings标签:用于设置一些改变MyBatis运行时行为的配置
  3. environments标签:用于配置成适应多种环境
  4. mappers标签:用于mapper映射器的设置

下面分别对每一个标签作简单讲解:设计模式

1.properties标签

当咱们须要把一些值做为一个变量被配置中使用时,就能够在properties标签下增长一个property标签,其中属性name是指变量名称,属性value是值,如:缓存

<properties>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
 </property>

定义好以后,就能够在配置文件中使用了,如:springboot

<dataSource type="POOLED">
   <property name="driver" value="${driver}"/>
</dataSource>

1.settings标签

settings标签中的每个setting都是用于调整mybatis的运行行为,咱们在须要使用其中某些setting时加入便可,其经常使用的配置以及各个setting的解释以下:

<settings>
  #设置配置文件中的全部映射器已经配置的任何缓存,默认false。
  <setting name="cacheEnabled" value="true"/>
  #延迟加载的全局开关。当开启时,全部关联对象都会延迟加载,默认为false
  <setting name="lazyLoadingEnabled" value="true"/>
  #是否容许单一语句返回多结果集,默认为true
  <setting name="multipleResultSetsEnabled" value="true"/>
  #是否使用列标签代替列名,默认为true
  <setting name="useColumnLabel" value="true"/>
  #是否容许JDBC支持自动生成主键,默认为false
  <setting name="useGeneratedKeys" value="false"/>
  #指定 MyBatis 应如何自动映射列到字段或属性
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  #指定发现自动映射目标未知列(或者未知属性类型)的行为,默认NONE
  #NONE: 不作任何反应
  #WARNING: 输出提醒日志
  #FAILING: 映射失败 (抛出 SqlSessionException)
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  #配置默认的执行器。默认为SIMPLE
  #SIMPLE 就是普通的执行器;
  #REUSE 执行器会重用预处理语句; 
  #BATCH 执行器将重用语句并执行批量更新
  <setting name="defaultExecutorType" value="SIMPLE"/>
  #设置超时时间,它决定驱动等待数据库响应的秒数。 
  <setting name="defaultStatementTimeout" value="25"/>
  #为驱动的结果集获取数量(fetchSize)设置一个提示值  
  <setting name="defaultFetchSize" value="100"/>
  #是否容许在嵌套语句中使用分页。若是容许使用则设置为false。
  <setting name="safeRowBoundsEnabled" value="false"/>
  #是否开启自动驼峰命名规则(camel case)映射,默认为false
  <setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>

3. environments

environments是为了配置多环境数据源而生,在咱们定义好了各类环境以后,只须要在代码中设置从哪一个环境中加载数据源便可,或者修改environments标签中的default也能够达到切换环境的效果。
environments的基本配置以下:

<environments default="development">
  #定义一个名称为development的环境配置
  <environment id="development">
    #设置事务管理器的类型,有JDBC和MANAGED梁总
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    #数据源设置
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

当咱们须要增长一个环境配置时,只须要复制粘贴一份environment,修改其中属性的值便可。

4.mappers

mappers标签其实是用于高速mybatis从哪找到咱们写好的SQL语句,也就是映射文件。当咱们写好一个表对应的mapper.xml时,咱们只须要在mappers下增长一个mapper便可。

mappers查找mapper的方式有多种:

1. 根据mapper.xml文件定位:

这些mapper.xml在resources中的某个文件夹xxx中,则用resource属性设置

<mappers>
<mapper resource="xxx/AMapper.xml"/>
<mapper resource="xxx/BMapper.xml"/>
</mappers>
2. 根据映射器接口实现类的彻底限定类名:

当咱们在这些mapper.xml设置好了namespace以后,咱们能够经过映射器接口实现类的全路径类来设置,如在AMapper.xml设置namespace为com.xxx.dao.AMapper类以后,咱们在这里可使用class属性指定查找的mapper,但前提是:
AMapper.xml和AMapper.java必须在同一个包下。

<mappers>
<mapper class ="com.xxx.dao.AMapper"/>
<mapper class ="com.xxx.dao.BMapper"/>
</mappers>
3. 包映射

有人会说,若是咱们表有不少,这样一行一行的写不是很费劲吗,mybatis为了便于使用,提供了package的方式引入映射器,但前提
全部的mapper.xml和mapper.java必须在同一个包下。

<mappers>
  <package name="org.xxx.dao"/>
</mappers>

4. URL映射:

若是你的mapper不在项目中,而是放到了其余文件内,mybatis提供了经过URL的方式引入mapper.xml。

<mappers>
  <mapper url="C:///test/mappers/AMapper.xml"/>
  <mapper url="C:///test/mappers/BMapper.xml"/>
</mappers>

5. MyBatis的SQL语法

在现有的框架下编写代码,多数状况下都不须要理会mybatis底层的东西,而大量的工做都集中在编写mapper文件上。所以学会在mybatis下编写SQL语句是很是有必要的,咱们首先来看一个标准的mapper文件的格式:

<?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="com.xxx.dao.XxxMapper">
</mapper>

能够看出,一个mapper文件的根结构是mapper标签开始,而mapper标签中的namespace有什么用呢?他应该怎么写?

咱们知道,有一种编程思想叫作面向接口编程,就是把业务需求中具体逻辑实现和接口分开,对外只暴露接口,经过接口实现业务。而在业务需求变化时,仅须要修改实现类,而不须要变更现有的对接代码,下降对系统的影响。

而mybatis正是基于这样的思想,在namespace中指定该mapper对应的接口以后,不须要编写接口实现类,mybatis会经过该绑定自动帮你找到对应要执行的SQL语句。

如:在com.xxx.dao中建立一个XxxMapper.java的接口,须要编写一根据用户查询用户信息的方法。

package com.xxx.dao;
public interface XxxMapper  {
  //根据姓名查询一条用户信息
  Map selectUserByName(@Param("name") String name);
}

此时咱们就能够在mapper.xml中设置namespace对应到上面的接口来:

<?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="com.xxx.dao.XxxMapper">
 <select id="selectUserByName" parameterType="String" resultType="hashmap">
  select * from user where name = #{name}
</select>
</mapper>

而在具体的业务实现类中,则是这样使用的:

@Service
public class XxxServiceImpl implements CustomerInfoService {
    @Resource
    private  XxxMapper xxxMapper=null;
    @Override
    public Map getUser(String name) {
        return xxxMapper.selectUserByName(name);
    }
}

能够看出,从编写SQL语句到最终业务调用SQL语句的过程当中,咱们并无给XxxMapper接口编写任何的实现类,这就是基于接口编程的思想,mybatis已经把这些事情都处理好了,咱们只须要在namespace中把SQL映射文件和接口类对应起来,就可使用了。

知道根节点mapper怎么设置以后,接下来咱们须要学习如何在mapper节点里编写SQL语句,在mapper标签后,mybatis提供了不少语义化的标签以便于咱们编写SQL语句和配置映射文件,下面是几个很是经常使用子标签:

1. select:用于编写查询语句的标签
2. update:用于编写update语句的标签
3. insert:用于编写insert语句的标签
4. delete:用于编写delete语句的标签
5. sql:编写语句块的标签,可被其它语句引用
6. resultMap:定义数据库结果和实体属性的映射关系

这些标签都是咱们在编写SQL语句中的必备标签,下面一一描述他们的使用。

1. select标签

在一个项目中,大部分功能都涉及到查询,所以mybatis也为select元素配备了很是多的属性,一下仅列出最经常使用的几个属性以及做用解释:

<select
  #必填,惟一标识符,和mapper接口中的方法一一对应
  id="selectUser"
  #选填,默认值为 unset,用于传入参数的类型设置
  parameterType="String"
  #选填,语句查询结果返回的指望类型,resultType 和 resultMap不能同时使用
  resultType="HashMap"
  #选填,语句查询结果返回的数据集,能够对应实体类和和resultMap定义的ID。
  resultMap="com.xxx.entity.User"
  #是否清除缓存,为true时本地缓存和二级缓存都会被清除
  flushCache="false"
  #是否启用缓存,为true时查询结果会被放入二级缓存
  useCache="true"  >

 #SQL语句编写....

 </select>

2. update标签

<update
  #必填,惟一标识符,和mapper接口中的方法一一对应
  id="updateUser"
  #选填,默认值为 unset,用于传入参数的类型设置
  parameterType="com.xxx.entity.User"
  #是否清除缓存,为true时本地缓存和二级缓存都会被清除
  flushCache="true">

 #编写update的SQL语句...

</update>

3. insert标签

<insert
  #必填,惟一标识符,和mapper接口中的方法一一对应
  id="updateUser"
  #选填,默认值为 unset,用于传入参数的类型设置
  parameterType="com.xxx.entity.User"
  #是否清除缓存,为true时本地缓存和二级缓存都会被清除
  flushCache="true"
  #是否取出由数据库内部生成的主键,默认为false
   useGeneratedKeys="false"  
   #选填,设置了以后,会经过getGeneratedKeys的返回值或者经过 insert语句的selectKey子元素设置它的键值。
   keyProperty="id"
  >

 #编写insert的SQL语句...

</insert>

4. delete标签

<delete
  #必填,惟一标识符,和mapper接口中的方法一一对应
  id="updateUser"
  #选填,默认值为 unset,用于传入参数的类型设置
  parameterType="com.xxx.entity.User"
  #是否清除缓存,为true时本地缓存和二级缓存都会被清除
  flushCache="true">

 #编写delete的SQL语句...

</delete>

5. sql标签

SQL节点用来编写那些能够被重用的SQL代码段,当咱们用SQL编写好一个代码段以后,就能够在其余语句使用。

咱们都知道,在写满了SQL以后,若是要修改表名,是一件很痛苦的事情,由于表名都写到了SQL语句中了,可是在mybatis中,咱们能够利用sql标签来定义好表名,若是在全部的SQL中引入这个代码块便可:

<sql id="TABLE_NAME">user</sql>

#在语句中用include的方式把表名动态化
<select id="selectUserByName">
select * from 
<include refid="TABLE_NAME" />
 where name = #{name}
</select>

相似的用法还有很是多,好比把查询字段一致的能够用sql块统必定义,而后在须要的地方调用...须要咱们在实际使用过程,灵活运用这些标签来减轻SQL的代码量和下降复杂度。

6. resultMap标签

resultMap标签用于表示数据库查询结果和实体对象的映射关系,它是映射文件中中所复杂的一个标签,经常使用的属性有两个:

<resultMap 
  #定义这个resultMap的惟一标识
  id="XXXResult"
  #返回值的全限定类名,或类型别名 
  type="com.xxx.entity.User"> 
  
     #子节点....

  </resultMap>

而它的子节点则就很是多了:

<resultMap id="XXXResult" type="java.util.HashMap"> 
    #constructor:类在实例化时,用来注入结果到构造方法中
    <constructor>
      #idArg:ID参数;标记结果做为ID能够帮助提升总体效能
      <idArg/>
      #arg:注入到构造方法的一个普通结果
      <arg/>
    </constructor>
    #一个 ID 结果;标记出做为 ID 的结果能够帮助提升总体性能        
    <id/>
    #注入到字段或 JavaBean 属性的普通结果
    <result/>
    #一个复杂类型的关联;许多结果将包装成这种类型
    <association property=""/>
    #一个复杂类型的集合
    <collection property=""/>
    # 使用结果值来决定使用哪一个 resultMap
    <discriminator javaType="">
       #基于某些值的结果映射
       <case value=""></case>
    </discriminator>!
  </resultMap>

如查询要把查询结果的字段用驼峰的写法映射,能够定义一个resultMap,吧对象和实体属性一一对应起来:

<resultMap id="UserResultMap" type="java.util.HashMap">
        <id column="id" property="id"/>
        <result column="nick_name" property="nickName"/>
        <result column="gmt_created" property="gmtCreated"/>
        <result column="gmt_modified" property="gmtModified"/>
    </resultMap>

在SQL用就能够直接使用这个resultMap做为返回类型:

<select id="selectUserByName" resultMap="UserResultMap">
    select id,nick_name,gmt_created,gmt_modified from user where name =#{name}
</select>

上面的例子只用到resultMap中最经常使用的两个子标签: <id>、<result>。还有不少其它的标签能够写成高级的resultMap,因为篇幅较长,而文章旨在入门,所以在此暂不对每一个标签举例子解释,有兴趣的能够自行百度。

6. 运行原理和实操一波

看完一波语法以后,脑子处于似懂非懂的状态,好像都是在讲配置文件和mapper的使用。当咱们学会了编写这些mapper以后,究竟应该怎么使用它?
到这里咱们就不得不提一下mybatis的运行过程了,先了解几个mybatis提供的接口/类:

  1. SqlSessionFactoryBuilder : SqlSessionFactory的构造器,用于建立SqlSessionFactory,采用了Builder设计模式。
  2. SqlSessionFactory:SqlSession工厂类,以工厂形式建立SqlSession对象,采用了Factory工厂设计模式。
  3. SqlSession:执行SQL的接口

因为mybatis的运行原理很是复杂,远远不是30分钟能掌握的,所以在此只是归纳为最大的四个过程:

  1. 加载配置建立SqlSessionFacotry
  2. 经过sqlSessionFactory获取SqlSession
  3. SqlSession查找和转化Mapper
  4. SqlSession执行mapper中的SQL语句

知道了运行流程以后,咱们就能够实操一波了,虽然主流的开发框架都已经看不见这些东西了,但做者仍是决定抛弃一切框架,只用maven构建一个空白项目进行实操:

  1. 在idea上建立一个maven项目,而且在pom中引入mybatis和mysql依赖

这个简单,很少描述。
其中pom中的依赖为:

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.7</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
        </dependency>
    </dependencies>
  1. 在resources中建立一个名为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>
    <!--properties用于定义一些属性变量,以便在配置文件中调用-->
    <properties>
        <!--定义一个变量为driver的属性,在下面就能够用${driver}来得到其属性值-->
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://10.9.0.111/test"></property>
    </properties>
    <!--定义不一样环境下的配置,便于区分生产、测试等环节的配置-->
    <environments default="development">
       <!--定义一个环境下的配置-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="root"/>
                <property name="password" value="test100"/>
            </dataSource>
        </environment>
    </environments>
    <!--用于设置mapper文件的引入-->
    <mappers>
        <!--resource方式引入mapper文件-->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
  1. 建立表结构:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `gmt_created` varchar(255) DEFAULT NULL,
  `gmt_modified` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
-- 插入一条数
INSERT INTO `user` VALUES ('1', 'hello mybatis', null, null);
  1. 在java下建立User.java的实体类(注意:为了简化代码,getter和serter已经去掉,实操时自行补上):
public class User {
    private Integer id;
    private String name;
    private String gmtCreated;
    private String gmtModified;
   //getter 和 setter...
}
  1. 在java下建立UserMapper.java的映射类:
public interface UserMapper {
    User getUserByName(@Param("name") String name);
}
  1. 在resources下建立mapper文件夹,在mapper下建立UserMapper的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="UserMapper">
    <select id="getUserByName" resultType="User">
        select  * from  user where  name =#{name}
    </select>
</mapper>
  1. 启动mybatis执行SQL

根据上面的运行流程,就能够编写一个测试类:

public static  void main(String args[]){
        try {
            String resource = "mybatis-config.xml";
//           1. 获取配置文件的输入流
            InputStream inputStream = Resources.getResourceAsStream(resource);
//            2. 读取配置文件并用SqlSessionFactoryBuilder建立一个SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//            3. 从SqlSessionFactory中获取一个SqlSession
             SqlSession s=  sqlSessionFactory.openSession();
//             4. 查找映射SQL文件
             UserMapper mapper=s.getMapper(UserMapper.class);
//             5.执行CURD操做
            User user=mapper.getUserByName("hello mybatis");

            if(user!=null){
                System.out.print("查询成功,个人名次是:"+user.getName());
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }

查看输出:

查询成功,个人名次是:hello mybatis

大功告成!有兴趣的读者能够根据上面的过程,编写属于本身的原生态mybatis的测试项目,若是有问题或者须要源码请关注公众号留言或加微信:sisi-ceo,咱们一块儿来征服写代码这作大山~


以为本文对你有帮助?请分享给更多人
关注「编程无界」,提高装逼技能

相关文章
相关标签/搜索