[MyBatis] MyBatis理论入门

  • 什么是MyBatis
  • iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
  • 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
  • MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

  • MyBatis特点
  • 简单易学,
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
  • 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

  • MyBatis执行流程
  • 加载配置(xml或注解)
    MyBatis将SQL的配置信息加载为一个个的MappedStatement对象(包括sqlId,sql语句,入参信息,返回值信息等),并将其存储在内存中

  • SQL解析
    当API接口层收到调用请求以后,会接收到传入的SQLId以及传入的入参对象(可以是任何类型),MyBatis根据SQL的Id找到对应的MappedStatement对象,然后根据传入参数对象对MappedStatement对象进行解析(将实际传入的参数来替换占位符参数,得到一条能够执行的sql语句)

  • SQL执行
    将解析得到的sql语句发送到数据库进行执行,得到数据库操作以后的结果

  • 结果集映射
    将数据库操作后得到的结果根据出参的配置进行自动转换,可以转换成任意类型,最后,将结果返回给调用方

  • MyBatis中的配置文件
    sqlMapConfig.xml(仅有一个),放在src目录下
  • <configuration></configuration>:包含配置信息
  • <environments default="environment"></environments>:默认的数据库连接环境,该节点中可包含多个<environments>标签
    • default:默认使用哪一个<environments>节点,值为<environments>中的id属性
  • <environments></environments>:数据库连接环境,可有多个
    <configuration>
        <!-- 数据库连接环境,default属性表示当前默认使用哪一个环境,值就是下面 environment子节点的id-->
        <environments default="environment">
            <!--environment节点可以有多个,表示不同的环境  -->
            <environment id="environment">
                <!-- transactionManager 必须写在最上面 -->
                <transactionManager type="JDBC" />
                <dataSource type="POOLED">
                    <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                    <property name="url" value="jdbc:oracle:thin:@192.168.3.5:1521:XE" />
                    <property name="username" value="SYSTEM" />
                    <property name="password" value="system" />
                </dataSource>
            </environment>
        </environments>
        <!-- 包含了映射文件的信息 -->
        <mappers>
            <mapper resource="com/niit/entity/Dept.xml"/>
            <mapper resource="com/niit/entity/Emp.xml"/>
        </mappers>
        
    </configuration>
  • MyBatis放置SQL语句的XML文件(映射文件)
  • <mapper></mapper>:定义需要执行的一些SQL语句的信息 
    • namespace属性:命名空间,可以用来指定sqlId所在的xml文件,每一个xml文件都有一个唯一的namespace

  • <insert></insert>:新增。  <update></update>:更新  <select></select>:搜索  <delete></delete>:删除
    • id:当前SQL语句的一个唯一标识,在同一个映射文件中id不能重复
    • paramType:入参的类名
    • #{ }:占位符参数
    • ${ }:占位符。在添加到SQL语句中的值不会自动添加 单引号( ‘ ’)

  • 动态SQL

    在一些组合查询页面,需要根据用户输入的查询条件不同生成不同的查询SQL语句,这个操作在JDBC或其他框架中都需要通过SQL的拼接来完成
    动态SQL是MyBatis中的重要特性,用来解决这一问题

    • 判断元素:if(简单的条件判断逻辑,当满足指定条件时追加if元素内的SQL语句)  / choose
    •                 <select>
                          固定SQL语句
                          <if test="条件表达式">
                              动态SQL语句
                          </if>
                          <if ...>
                              ...
                          </if>
                      </select>
    • choose
                      <select>
                          固定SQL语句
                          <choose>
                              <when test="条件表达式">
                                  动态SQL语句
                              </when?>
                              <when ...>
                                  ...
                              </when>
                              <otherwise>
                                  动态语句N(当前都不满足时追加的SQL)
                              </otherwise>
                          </choose>
                      </select>
  • 关键字元素
    • where:主要用于简化查询语句中where部分的条件判断,where元素可以在其出现的位置上输出一个where关键字,而且还可以将后面条件多余的and或or去掉
                      <select>
                          固定SQL语句
                          <where>
                              根据不同条件动态追加的SQL语句
                          </where>
                      </select>
    • set:用在更新操作时,主要功能和where元素类似,set元素所在的位置输出一个set关键字,而且还可以去掉内容结尾中无关的逗号。
                      <update>
                          update 表名
                          <set>
                              根据条件动态追加要更新的列
                              //可嵌套if
                          </set>
                      </update>
    • trim:在trim包含的内容之前加上某些前缀,也可以在其后面添加后缀
        prefix="":前缀
        suffix="":后缀
      可以把trim包含的内容前面的某些内容过滤,也可以把尾部的某些内容过滤
        prefixOverrides="":过滤前面内容
        suffixOverrides="":过滤后面内容
      <!-- trim元素的使用   模拟where元素的实现 -->
             <select id="getDeptsByNameAndLoc4"  resultType="com.niit.entity.Dept">
                      select * from dept 
                     <trim prefix="where" prefixOverrides="AND|OR">
                         <if test="dname!=null and dname!=''">
                          and dname=#{dname}
                      </if>
                      <if test="loc!=null and loc!=''">
                          and  loc=#{loc}
                      </if>
                     </trim>
             </select>
  • 循环元素
    • foreach

      collection="":要迭代的集合
      item="":迭代变量
      open="":打印集合元素时,以什么元素开始
      close="":打印集合元素时,以什么符号结尾
      separator="":每个集合元素打印时,其中的分隔符

      <!-- foreach -->
             <select id="getDeptByDeptNos" resultType="com.niit.entity.Dept">
                     select * from dept where deptno in 
                     <!-- 
                         collection:要迭代的集合
                         item:迭代变量
                         open:打印集合元素时,以什么符号开头
                         close:打印集合元素时,以什么符号结尾
                         separator:每个集合元素打印时中间的分隔符
                      -->
                     <foreach collection="deptnos" item="deptno" open="(" close=")" separator=",">
                         #{deptno}
                     </foreach>
             </select>

       

  • 如果语句中有小于号(<)会被解析为XML中的节点,使用CDATA语句块

    <![CDATA[  and age<19  ]]>

     

  • 主键映射
    • 使用MyBatis做插入操作时,可以由MyBatis负责主键的生成,主键字段的映射分为两种情况
      数据库支持自动递增:(MySQL、SqlServer)
      数据库不支持自动增长:(Oracle)

                  <insert>
                      <selectKey keyProperty="" resultType="" order="">
                          
                      </selectKey>
                  </insert>

      selectKey指定了入参对象中用来表示主键的属性名,在完成selectKey中语句的执行以后, 会自动将值set到入参对象中由keyProperty指定的属性中去
      keyProperty:入参中用来表示主键字段的属性名
      order:如果取值为BEFOR,表示先获取主键,再执行插入;对于之处自增长主键的数据库必须设置为AFTER才有效
      resultType:生成的主键对应的结果类型

  • 关联映射
    • (1)嵌套查询:通过执行另外一条SQL语句来返回关联数据的结果(至少要查两次)
    • (2)嵌套结果:执行一个表关联查询的SQL语句,然后将查询结果映射成关联的对象(只查一次)

      <!-- 关联映射  嵌套查询 -->
          <select id="getEmpByEmpNo" parameterType="int" resultMap="empMap1">
              select * from emp where empno=#{empno}
          </select>
          <select id="getDeptByDeptno" parameterType="int" resultType="com.niit.entity.Dept">
              select * from dept where deptno=#{deptno}    
          </select>
          <resultMap id="empMap1" type="com.niit.entity.Emp">
              <!-- association元素:用来配置JavaBean类型的关联对象
                   property:关联对象在当前类中的属性名
                   column:关联列的列名
                   javaType:关联对象的java类型
                   select:指定通过哪一条语句来查询关联对象
               -->
              <association property="dept" column="deptno" javaType="com.niit.entity.Dept" select="getDeptByDeptno">
                  
              </association>
          </resultMap>
          
          <!-- 嵌套结果 -->
          <select id="getEmpByEmpNo2" parameterType="int" resultMap="empMap2">
              select e.*,d.*
              from emp e,dept d 
              where e.deptno=d.deptno and e.empno=#{empno}
          </select>
          <resultMap  id="empMap2" type="com.niit.entity.Emp">
              <result column="empno" property="empno"/>
              <!-- 
                  Emp中其它字段映射关系的配置……    
               -->
              <association property="dept" column="deptno" javaType="com.niit.entity.Dept">
                  <id column="deptno" property="deptno"/>
                  <result column="dname" property="dname"/>
                  <result column="loc" property="loc"/>
              </association>
          </resultMap>
  • 集合映射 
    • 嵌套查询:(查询两次)
      <!-- 嵌套查询 -->
             <select id="getDeptInfoByDeptNo" parameterType="int" resultMap="deptMap1">
                     select * from dept where deptno=#{deptno}
             </select>
             <select id="findEmpsByDeptNo" parameterType="int" resultType="com.niit.entity.Emp">
                     select * from emp where deptno=#{deptno}
             </select>
             <resultMap id="deptMap1" type="com.niit.entity.Dept" >
                     <result property="deptno" column="deptno"/>
                     <!-- 返回Dept中关联的Emp列表 -->
                     <!-- 
                         collection:关联的集合对象
                         property:当前类中的集合对象对应的属性
                         column:当前表中的关联列,通过这个列的值再去查询另外一张表
                         javaType:返回的集合类型
                         ofType:返回的集合中元素的泛型
                         select:指定通过哪条SQL语句来查询关联的集合对象
                      -->
                     <collection property="emps" 
                     column="deptno" 
                     javaType="java.util.ArrayList" 
                     ofType="com.niit.entity.Emp" 
                     select="findEmpsByDeptNo"></collection>
                     
             </resultMap>
    • 嵌套结果:(查询一次)
      <!-- 嵌套结果 -->
             <select id="getDeptInfoByDeptNo2" parameterType="int" resultMap="deptMap2">
                     select e.*,d.*
                  from emp e,dept d
                  where e.deptno=d.deptno and d.deptno=#{deptno}
             </select>
             <resultMap  id="deptMap2" type="com.niit.entity.Dept">
                     <id column="deptno" property="deptno"/>
                     <result column="dname" property="dname"/>
                     <result column="loc" property="loc"/>
             
                     <collection property="emps" column="deptno" ofType="com.niit.entity.Emp" javaType="java.util.ArrayList">
                         <id column="empno" property="empno"/>
                         <result column="ename" property="ename"/>
                         <!-- Emp中的其它字段和属性的映射关系 -->
                     </collection>
             </resultMap>

      使用<collection>进行dept对象中的List<Emp> emps;的注入。只执行了一次SQL语句,返回一个 Dept 对象。该标签中的列名当前表中的关联列,通过这个列的值再去查询另外一张表
      <id />和<result />基本一致


      Dept.java

      private int                    deptno;
          private String                dname;
          private String                loc;
          private List<Emp>            emps;


      Emp.java

      private int                    empno;
          private String                ename;
          private String                job;
          private int                    mgr;
          private Date                hiredate;
          private double                sal;
          private double                comm;
          private int                    deptno;
          /** dept就是员工对应的部门对象 **/
          private Dept                dept;

       

       

posted @ 2018-03-07 20:56  1440min  阅读(194)  评论(0编辑  收藏  举报