MyBatis 3 学习笔记

一、Mybatis 基础知识

1.MyBatis 3编写步骤:

  • 根据mybatis-config.xml配置文件创建一个SqlSessionFactory对象。
  • sql映射文件,配置了每一个sql,以及sql的封装规则
  • 将sql映射文件注册到全局配置文件mybatis-config.xml中
  • 写代码:
    • 根据全局配置文件得到SqlSessionFactory
    • 从SqlSessionFactory中获取SqlSession对象,使用它来做增删改查。一个SqlSession就代表和数据额 库的一次会话,用完要关闭
    • 使用sql标识来告诉mybatis执行那个sql。sql都是保存在SQL映射文件中的。
    mybatis-config.xml 文件
      <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
      <mappers>
          <mapper resource="EmployeeMapper.xml" />
      </mappers>
    </configuration>
    //1.通过配置文件创建一个sqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          //2.获取SqlSession实例,能直接执行已经映射的SQL语句
          SqlSession openSession = sqlSessionFactory.openSession();
          //3.参数一:statement唯一标识,参数二:传入sql变量
          try {
              Employee employee = openSession.selectOne("cn.guet.bean.EmployeeMapper.selectEmployee", 1);
              System.out.println(employee);
          }catch (Exception e){
              e.printStackTrace();
          }finally {
              openSession.close();
          }
    SQL映射文件:
    <mapper namespace="cn.guet.bean.EmployeeMapper">
      <!--
      namespace:名称空间;指定为接口的全类名
      id:唯一标识
      resultType:返回值类型
      #{id}:从传递过来的参数中取出id值
    
      public Employee getEmpById(Integer id);
       -->
      <select id="selectEmployee" resultType="cn.guet.bean.Employee">
          select id,last_name lastName,email,gender from tb1_employee where id = #{id}
      </select>
    </mapper>

2.MyBatis 3 接口式编程中,在进行接口和SQL的动态绑定时,SQL映射文件中的namespace指定为mapper接口的全限定名,映射文件中的id 指定为接口的中方法。动态绑定以后,不用再写mapper的实现类。mybatis会为我们自动创建一个代理对象,代理对象去执行增删改查的方法。

3.接口式编程: 原生 Dao ==> DaoImpl; mybatis: Mapper ==> xxxMapper.xml

4.Configuration,全局配置文件mybatis-config.xml 的标签 (p.s. 标签有顺序)

  • properties标签,用来引入 jdbc文件。
 <!--配置数据源信息-->
 <properties resource="jdbc.properties"></properties>
  • settings设置标签,用来设置各种信息。如下划线转驼峰标识。
<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
  • typeAliases别名标签。mybatis中的别名处理器。给Java type 一个短一点简单一点的别名,以后xml文件引用式直接用别名。
    <!--typeAliases别名处理器,可以为Java类型取别名-->
    <typeAliases>
        <!--typeAlias为某个Java类型取别名。默认别名是类名小写employee-->
        <!--<typeAlias type="cn.guet.bean.Employee" alias="emp"></typeAlias>-->
        <!--批量取别名-->
        <!--package为某个包下的所有类型批量起别名,name指定报名,为包以及包下面的所有类起默认别名(类名小写)-->
        <package name="cn.guet.bean"/>
    </typeAliases>
当使用批量起别名,且包里面有类名重复是,可以使用@Alias("xxx")指定别名
@Alias("emp")
public class Employee {
    private Integer id;
    private String lastName;
  • typeHandlers类型处理器标签。Java类型和数据库类型映射的桥梁。
  • plugins插件标签。插件可以拦截以下四大对象。
• Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
  • mappers标签。将sql映射注册到全局配置文件中。
 <!--
        mappers:注册一个sql映射文件,
        resource:引用类路径下的映射文件,
        url:引用磁盘路径下的映射文件,
        class:引用注册接口,
            1.有SQL文件,映射文件名必须和接口同名,并且放在与接口同一目录下。
            2.没有SQL文件,所有的SQL都是利用注解写在接口上。
            推荐:比较重要的,复杂的Dao接口写映射文件,不重要的、简单的可以写注解
     -->
    <mappers>
        <!--<mapper class="cn.guet.dao.EmployeeMapperAnnotation"/>-->
        <!--<mapper resource="EmployeeMapper.xml" />-->
        <!--  <mapper url="file:///var/mappers/AuthorMapper.xml"/>-->
        <!--批量注册-->
        <package name="cn.guet.dao"/>
    </mappers>
/**
 * 基于注解版的Mapper接口
 */
public interface EmployeeMapperAnnotation {
    @Select("select id,last_name ,email,gender from tb1_employee where id = #{id}")
    public Employee getEmployeeById(Integer id);
}
    <!--
    p.s. mybatis错误——java.io.IOException: Could not find resource com/xxx/xxxMapper.xml
    原因:IDEA是不会编译src的java目录的xml文件,所以在Mybatis的配置文件中找不到xml文件!(也有可能是Maven构建项目的问题,网上教程很多项目是普通的Java web项目,所以可以放到src下面也能读取到)
    在Maven的pom文件中,添加下面代码:
    -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

5.Mapper XML Files 中的 select、insert、update and delete 不做过多的赘述。

6.参数的处理

  • 单个参数:mybatis不会做特殊处理,#{参数名/任意名}:取出参数值。
  • 多个参数:mybatis会做特殊处理。多个参数会被封装成 一个map,key:param1...paramN,或者参数的索引也可以,value:传入的参数值,#{}就是从map中获取指定的key的值。
  • 异常:org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [1, 0, param1, param2]。操作:
    • 方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
    • 取值:#{id},#{lastName}
    • 命名参数:明确指定封装参数时map的key;@Param("id"),多个参数会被封装成 一个map。key:使用@Param注解指定的值,value:参数值。#{指定的key}取出对应的参数值。
  • POJO:如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;#{属性名}:取出传入的pojo的属性值。
  • Map:如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map,#{key}:取出map中对应的值。
  • 总结:参数多时会封装map,为了不混乱,我们可以使用@Param来指定封装时使用的key;#{key}就可以取出map中的值。
/*mybatis处理参数源代码 */
org.apache.ibatis.reflection.ParamNameResolver

7.${xxx} 与 #{xxx} 区别:
#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入。${}:取出的值直接拼装在sql语句中;会有安全问题;大多情况下,我们去参数的值都应该去使用#{}。原生jdbc不支持占位符的地方我们就可以使用${}进行取值。比如分表、排序;按照年份分表拆分select * from ${year}_salary where xxx。select * from tbl_employee order by ${f_name} ${order}

8.select 查询返回一个list时,resultType=pojo类型。

    <select id="findEmployeeByLastName" resultType="cn.guet.bean.Employee">
        select *from tb1_employee where last_name like #{lastName}
    </select>

9.Dynamic SQL

  • if 条件判断,条件成立时,则拼接SQL。
   <select id="getEmpsByConditionIf" resultType="cn.guet.bean.Employee">
        select *from tb1_employee
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                and last_name like #{lastName}
            </if>
        </where>
    </select>
  • choose (when, otherwise) 当条件成立,则拼接SQL,只会拼接一个SQL。
<select id="getEmpsByConditionChoose" resultType="cn.guet.bean.Employee">
         select *from tb1_employee
        <where>
            <!--如果带了id,就用id查。如果带了lastname就用lastname查询-->
            <choose>
                <when test="id!=mull">
                    id = #{id}
                </when>
                <when test="lastName!=null">
                    last_name like #{lastName}
                </when>
                <otherwise>
                    gender = "1"
                </otherwise>
            </choose>
        </where>
    </select>
  • trim (where, set) 可以实现部分数据更新
 <update id="updateEmployee">
        update tb1_employee
        <trim prefix="SET" suffixOverrides=",">
                <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">last_name=#{lastName},</if>
                <if test="email!= null">email=#{email},</if>
                <if test="gender!= null">gender=#{gender},</if>
        </trim>
        where id=#{id}
    </update>
  • foreach 个人感觉意义不大,略。

10.SQL片段抽取

  <sql id="select_column">
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                and last_name like #{lastName}
            </if>
        </where>
    </sql>

 <select id="getEmpsByConditionIf" resultType="cn.guet.bean.Employee">
        select *from tb1_employee
      <include refid="select_column"></include>
    </select>

二、Mybatis 缓存机制 (未完、、、)

1.mybatis提供两级缓存

  • 一级缓存(本地缓存):sqlSession级别的缓存,一直开启,无法关闭。就是与数据库一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。一级缓存就是sqlSession级别的一个map,一级缓存失效的情况(失效了即要重新查询):

    • sqlSession不同。
    • sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
    • sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
    • sqlSession相同,手动清除了一级缓存(缓存清空)
  • 二级缓存(全局缓存):是namespace级别的缓存,一个namespace对应一个二级缓存。
    • 工作机制:

      • 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
      • 如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
      • sqlSession===EmployeeMapper==>Employee;DepartmentMapper===>Department。不同namespace查出的数据会放在自己对应的缓存中(map)。查出的数据都会被默认先放在一级缓存中。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中

三、Mybatis 和 Spring整合

1.创建maven创建web-app工程,然后添加依赖。需要添加的依赖有 spring (4.0.9)、springmvc、mybatis(1.3.0)、mybatis-spring、mysql-connector-java、c3p0、taglibs、log4j。pom文件中注意以后下代码:

 <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
        <resource>
            <directory>${basedir}/src/main/resources</directory>
        </resource>
    </resources>

2.配置web.xml


  <!--Spring配置: needed for ContextLoaderListener -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- SpringMVC配置 -->
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

3.配置SpringMVC,springmvc默认会加载WEB-INF/spring-servlet.xml文件,配置如下:

    <!--SpringMVC只是控制网站跳转逻辑  -->
    <!-- 只扫描控制器 -->
    <context:component-scan base-package="cn.guet.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>
    <mvc:default-servlet-handler/>

4.到这里springmvc 应该是可以工作了,应该写一个controller,测试springmvc是否正常。
5.配置mybatis。mybatis中的配置都会交给spring,所以很多配置都是在springContext.xml 里面去配置。

<configuration>
    <!--开启下划线转驼峰标识-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

6.JDBC.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true
jdbc.username=root
jdbc.password=root

7.Spring 配置

<!--spring希望管理所有的业务主键-->
    <context:component-scan base-package="cn.guet">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 引入数据库的配置文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!-- Spring用来控制业务逻辑。数据源、事务控制、aop -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!-- spring事务管理 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启基于注解的事务 -->
    <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
    <!--
整合mybatis 目的:1、spring管理所有组件。mapper的实现类。service==>Dao   @Autowired:自动注入mapper;
                 2、spring用来管理事务,spring声明式事务-->
    <!--创建出SqlSessionFactory对象  -->
    <!--让spring的IOC一启动就代替我们去创建sqlSessionFactory对象-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!-- configLocation指定全局配置文件的位置 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!--mapperLocations: 指定mapper文件的位置-->
        <!--<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>-->
    </bean>
    <!--配置一个可以进行批量执行的sqlSession  -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
        <constructor-arg name="executorType" value="BATCH"></constructor-arg>
    </bean>
    <!-- 扫描所有的mapper接口的实现,让这些mapper能够自动注入;
    base-package:指定mapper接口的包名
     -->
    <mybatis-spring:scan base-package="cn.guet.dao"></mybatis-spring:scan>
    <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.atguigu.mybatis.dao"></property>
    </bean> -->

注:如果你的web. xml 是如下版本,默认是禁用 el 表达式的,需要手动开启

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<%--开启EL表达式--%>
<%@ page isELIgnored="false" %>

三、Mybatis 运行原理

四、Mybatis 插件开发

MyBatis 3的更多相关文章

  1. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

  2. Java MyBatis 插入数据库返回主键

    最近在搞一个电商系统中由于业务需求,需要在插入一条产品信息后返回产品Id,刚开始遇到一些坑,这里做下笔记,以防今后忘记. 类似下面这段代码一样获取插入后的主键 User user = new User ...

  3. [原创]mybatis中整合ehcache缓存框架的使用

    mybatis整合ehcache缓存框架的使用 mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓 ...

  4. 【SSM框架】Spring + Springmvc + Mybatis 基本框架搭建集成教程

    本文将讲解SSM框架的基本搭建集成,并有一个简单demo案例 说明:1.本文暂未使用maven集成,jar包需要手动导入. 2.本文为基础教程,大神切勿见笑. 3.如果对您学习有帮助,欢迎各种转载,注 ...

  5. mybatis plugins实现项目【全局】读写分离

    在之前的文章中讲述过数据库主从同步和通过注解来为部分方法切换数据源实现读写分离 注解实现读写分离: http://www.cnblogs.com/xiaochangwei/p/4961807.html ...

  6. MyBatis基础入门--知识点总结

    对原生态jdbc程序的问题总结 下面是一个传统的jdbc连接oracle数据库的标准代码: public static void main(String[] args) throws Exceptio ...

  7. Mybatis XML配置

    Mybatis常用带有禁用缓存的XML配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  8. MyBatis源码分析(一)开篇

    源码学习的好处不用多说,Mybatis源码量少.逻辑简单,将写个系列文章来学习. SqlSession Mybatis的使用入口位于org.apache.ibatis.session包中的SqlSes ...

  9. (整理)MyBatis入门教程(一)

    本文转载: http://www.cnblogs.com/hellokitty1/p/5216025.html#3591383 本人文笔不行,根据上面博客内容引导,自己整理了一些东西 首先给大家推荐几 ...

  10. MyBatis6:MyBatis集成Spring事物管理(下篇)

    前言 前一篇文章<MyBatis5:MyBatis集成Spring事物管理(上篇)>复习了MyBatis的基本使用以及使用Spring管理MyBatis的事物的做法,本文的目的是在这个的基 ...

随机推荐

  1. 系列文章|OKR与敏捷(二):实现全栈敏捷

    OKR与敏捷开发的原理有着相似之处,但已经使用敏捷的团队再用OKR感觉会显得多余.这种误解的根源就在于对这两种模式不够了解,运用得当的情况下,OKR和敏捷可以形成强强联合的效果,他们可以创造出以价值为 ...

  2. RDIFramework.NET代码生成器全新V3.5版本发布-重大升级

    发布说明 RDIFramework.NET代码生成器V3.5版本全新震撼推出,相比上次版本,本次发布新增与修改的内容如下: 1.全新增加了WinForm界面代码的生成,可直接生成常用的主界面(集新增. ...

  3. 解决Spring MVC前台传参中文乱码问题

    在web.xml文件中配置字符编码过滤器: <filter> <filter-name>CharacterEncoding</filter-name> <fi ...

  4. Activity、Window、View三者之间的联系

    Activity类:Android四大组件之一,是开发者最常用的一个组件 Window类:是一个抽象类,具有窗口管理的功能,实现类为PhoneWindow View类:提供对View的操作,包括绘制测 ...

  5. Android Studio Error:Execution failed for task ':app:preDebugAndroidTestBuild'.彻底解决的方法以及修改AScompileSDKVersion

    Error Error:Execution failed for task ':app:preDebugAndroidTestBuild'. > Conflict with dependency ...

  6. linux下mysql区分大小写的内容

    1.数据库名严格区分大小写2.表名严格区分大小写的3.表的别名严格区分大小写4.变量名严格区分大小写5.列名在所有的情况下均忽略大小写6.列的别名在所有的情况下均忽略大小写

  7. 好代码是管出来的——.Net中的代码规范工具及使用

    上一篇文章介绍了编码标准中一些常用的工具,本篇就具体来介绍如何使用它们来完成代码管理. 本文主要内容有: Roslyn简介 开发基于Roslyn的代码分析器 常用的基于Roslyn的代码分析器 在.N ...

  8. vue和angular的区别:

    相同: 1.数据绑定:vue和angular绑定都可以用{{}} 2.都支持内置指令和自定义指令 3.都支持内置过滤器和自定义过滤器. 区别: 1.学习成本和API 设计:vue相比于angular来 ...

  9. iBatis第五章:事务管理

    ---------------------------- 1.什么是事务 ------------------------------ 什么是事务? 需要注意的是,事务的概念不是针对某个特定的数据库的 ...

  10. DIY手机锂电池万能充

    今天翻出来一个诺基亚的旧手机,试了一下,无法开机,应该了电池亏电了.可惜手头没有充电器,无法给手机充电. 活人岂能让尿憋死?回想了一下以前用过的手机万能充的样式(这里暴露年龄了) 根据家中现成的材料, ...