• MyBatis


    MyBatis优秀的持久层框架,用于简化JDBC开发

    MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

     官网:https://mybatis.org/mybatis-3/zh/index.html

    一些持久层框架

    持久层:

    • 负责将数据保存到数据库,操作数据库数据的那一层代码
    • javaee三成架构 :表现层,业务层,持久层

    框架

    • 框架是一个半成品软件,一套可重用的,通用的,软件基础代码模型
    • 在框架的基础之上构建软件编写更加高效,规范,通用,可扩展

    官网 mybatis-spring –

    JDBC 的缺点

    JDBC代码

     

    • 硬编码
      • 一些语句的改动不方便等等
      • 注册驱动,获取连接,SQL语句处的硬编码
    • 操作繁琐
      • 手动操作参数
      • 手动封装结果集 等等

    MyBatis 入门

    入门操构建一个查询所有的MyBatis模块

    1创建数据库表单

    2 安装

    要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。

     

    如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>x.x.x</version>
    </dependency>

    3 编写MyBatis核心配置文件→替换连接信息解决硬编码问题

    →→→→→→→→→→→→ 

     

    <--指定sql映射配置文件的历经-->  
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>

    4编写SQL映射文件→统一管理sql语句,解决硬编码问题

    <?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">
    <!--
        namespace:名称空间
        配合要执行的sql语句标签中的id使用
    id是sql语句的唯一标识,resultType是返回值类型
    --> <mapper namespace="com.yang.mapper.UserMapper"> <select id="selectAll" resultType="com.yang.Pojo.User"> SELECT * FROM tb_user </select> </mapper>

    5编码

    • 设计pojo javabean封装类
    • 加载核心配置文件,获取SqlSessionFactory对象
    • 获得SqlSession对象,执行Sql语句
    • 释放资源
      //加载核心配置文件,获取SqlsessionFactory工厂对象
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //获取sqlSession对象
            SqlSession sqlSession = build.openSession();
            //执行sql语句,并接受结果集
            List<User> list = sqlSession.selectList("com.yang.mapper.UserMapper.selectAll");//mapper的名称空间.select的id属性值
            sqlSession.close();
            for (User user : list) {
                System.out.println(user);
            }
    sql语句爆红是没有连接数据库
    6 了解了原生的开发,只是为了让我们更好的了解Mybatis的原理,上面代码仍然存在硬编码问题

    在我们传递sql语句映射地址的时候仍然有硬编码问题所以我们又要使用Mapper代理开发

     我们只需要增加一个对应封装类的Mapper接口,如User的UserMapper接口,保证mapper的命名空间namespce为mapper接口的全类名。只需保证接口中的抽象方法返回值能接受你sql语句的返回值方法名保持sql的唯一标识相同即可,这样我们的MyBatis即可利用反射原理,替我们完成老本版方法的连接,这样能让你的代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。但我们需要定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。(编译后和对应皆苦的Class文件在同一地址下就可以)

      我们使用UserMapper.class对象能够得到该接口的全限定名,又因为SQL映射配置文件也是这个地址,我们执行该接口的方法,改方法和SQL id一致,我们便可以执行SQL语句,且该方法的返回值,也是和之前sqlSession直接执行SQL语句一样的,所以者样我们使用Mapper代理便实现了旧版本的升级。

    使用了Mapper代理后,我们可以使用包扫描的方法完成sql映射文件的加载

    <mappers>
            <!--加载映射配置文件-->
            <!--<mapper resource="UserMapper.xml"/>-->
            <!-- 更换为包扫描-->
            <package name="com.yang.mapper"/>
        </mappers>

     这样我们的项目结构就变成了这样   

     

    public static void main(String[] args) throws IOException {
            //加载核心配置文件,获取SqlsessionFactory工厂对象
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //获取sqlSession对象
            SqlSession sqlSession = build.openSession();
            //执行sql语句,并接受结果集
           //List<User> list = sqlSession.selectList("test.selectAll");//名称空间.id属性值
            //使用mapper代理 获得UserMapper接口的代理对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = mapper.selectAll();
            sqlSession.close();
            //for遍历集合,处理结果
            for (User user : users) {
                System.out.println(user);
            }
    
        }

    7Mapper核心配置文件内容

     官网很详细(配置遵守顺序就可以)

     8注意

    当数据库字段名,与实体类属性名称对应不上时,数据便不能自动封装,这会导致我们查询到结果为空
    如 brand_name 与brandName
    • sql映射文件中的sql语句利用as关键字起别名 brand_name as brandName
          <select id="selectAll" resultType="Brand">
              select brand_name as brandName from tb_brand;
          </select>
    • 当很多sql语句需要起别名时,我们可以抽取sql片段 缺点不灵活
      <sql id="brand_cloum">
          brand_name as brandName
      </sql>
          <select id="selectAll" resultType="Brand>
              select <include refid="brand_cloum"/> from tb_brand;
          </select>
    • 使用resultMap映射
        <!--方案三:resultMap-->
        <!--
            resultMap标签:手动配置数据表字段和实体类的映射关系
            id属性:唯一标识
            type属性:映射的实体类类型,支持别名
        -->
    <resultMap id="brand_mapper" type="Brand">
        <result column="brand_name" property="brandName"/>
    </resultMap>
    
    //resultType换为resultMap 值设为 resultMap映射ID
        <select id="selectAll" resultMap="brand_mapper">
            select * from tb_brand;
        </select>

    9参数占位符和xml中sql语句的特殊字符

    <!--
            1.参数占位符
                #{}:使用预编译,将参数替换为 ? 占位符。防止sql注入,安全!
                ${}:直接拼接sql语句,存在sql注入,不安全!
                使用场景:
                    #{}:实际参数传递时使用
                    ${}:表名或字段名不固定时使用
            2.参数类型:parameterType属性(可以省略不写)这里parameterType的属性设置为 int
            3.特殊字符处理:< > <>等等
                转义字符替换:SELECT * FROM tb_brand WHERE id &lt; #{id}
                CDATA区:
                    SELECT * FROM tb_brand WHERE id
                     <![CDATA[
                        <
                     ]]>
                     #{id}
        -->
    <select id="selectById" parameterType="int" resultMap="brandResultMap">
         SELECT * FROM tb_brand WHERE id = #{id}
    </select>
    <select id="selectById" resultMap="brand_mapper">
    select * from tb_brand where id <![CDATA[
    <
    ]]>#{num};
    </select>
     

    10 Mapper 映射接口中的sql方法多参数接收

     为保证我们sql映射文件中的sql语句的#{}里面的参数占位符,能与我们在Mapper接口中对应方法的形参对应起来我们可以使用三种方法

       <select id="selectByCodition" resultMap="brand_mapper">
            select * from tb_brand
            <where>
                <if test="status !=null">
                    and status=#{status}
                </if>
                <if test="companyName !=null and companyName != ''">
                    and company_name like #{companyName}
                </if>
                <if test="brandName !=null and brandName != ''">
                    and brand_name like #{brandName}
                </if>
            </where>
        </select>
    
    •   散装参数使用Param注解 @Param("sql语句的参数占位符名称")
     List<Brand> selectByCodition(@Param("status") int status, @Param("brandName") String brandName,@Param("companyName") String companyName);
    •      实体类封装参数 要求sql语句的参数占位符与实体类的属性名一致就可以了,其他无需改动
      List<Brand> selectByCodition(Brand brand);
    • Map集合封装参数 sql语句占位符与Map 的 key保持一致
      List<Brand> selectByCondition(Map map);

    11 动态多条件查询

              当我们需要多条件查询时我们会编写这样的sql语句

     <select id="selectByCodition" resultMap="brand_mapper">
            select * from tb_brand
            where
             status=#{status} and company_name like #{companyName}and brand_name like #{brandName}
        </select>

    但是当用户只给一个company_name的值查询时,程序会报错

    因为 会产生 where and sql语句的语法错误 可以在where后加恒等式 或者使用<where>标签 会帮我们去掉多余的and关键字

    这时我们需要一个动态SQL语句,使得sql语句随着用户的输入或外部条件的变化而变化 。MyBatis为我们提供了很多sql标签来帮助我们完成动态SQL

     <select id="selectByCodition" resultMap="brand_mapper">
            select * from tb_brand
            <where>
                <if test="status !=null">
                    and status=#{status}
                </if>
                <if test="companyName !=null and companyName != ''">
                    and company_name like #{companyName}
                </if>
                <if test="brandName !=null and brandName != ''">
                    and brand_name like #{brandName}
                </if>
            </where>
        </select>

    12 动态单条件查询

    Mabatis为我们提供了 <choose><when></when><when></when><otherwise></otherwise>动态单条件查询标签

    choose相当于switch when相当于 case otherwise相当于 default

     <select id="selectByConnditionSingle" resultType="com.yang.pojo.Brand">
            select * from tb_brand
            <where>
                <choose>
                    <when test="status!=null">
                        status=#{status}
                    </when>
                    <when test="brandName!=null and brandName!=''">
                        brand_name like #{brandName}
                    </when>
                    <when test="companyName!=null and companyName!=''">
                        company_name like #{companyName}
                    </when>
                </choose>
            </where>
        </select>

    13 提交事务

    MaBatis事务:

    • openSession(): 默认开启事务,进行增删改查操作后需要使用sqlSession.commit();手动提交事务
    • openSession(true): 可以设置为自动提交事务(关闭事务)
    //进行增删改 操作需要对事务进行设置   

    try { brandMapper.add(brand); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); }finally { sqlSession.close(); }

    14 获取主键id

    编写映射文件的sql
    • useGeneratedKeys属性:是否使用生成的主键

    • keyProperty属性:主键名称

    <!--添加数据后、可以返回自增数据的主键-->
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
            INSERT INTO tb_brand (brand_name,company_name,ordered,description,status)
            VALUES (#{brandName},#{companyName},#{ordered},#{description},#{status})
    </insert>

    15 动态修改字段

    添加<if></if>标签判断(防止其他字段被修改为null),sql中的,会出现错误,我们需要使用<set>标签

    <!--
            动态修改数据
                <set>标签:替换set关键字
        -->
    <update id="update">
            UPDATE tb_brand
                <set>
                    <if test="brandName != null and brandName != ''">
                        brand_name = #{brandName},
                    </if>
                    <if test="companyName != null and companyName != ''">
                        company_name = #{companyName},
                    </if>
                    <if test="ordered != null">
                        ordered = #{ordered},
                    </if>
                    <if test="description != null and description != ''">
                        description = #{description},
                    </if>
                    <if test="status != null">
                        status = #{status}
                    </if>
                </set>
            WHERE
                id = #{id}
    </update>

     16批量删除

       <!--

            批量删除
    mybatis会将数组参数,封装为一个一个Map集合:
    *默认 array=数组
    *或者使用Param注解来改变Map集合的默认名称 <foreach>标签:循环 collection属性:获取容器的名称,数组默认是array,可以通过@Param()指定名称 item属性:接收每个元素的变量名 separator属性:连接符 open属性:开始符号 close属性:结束符号
    --> <!--collection 数组或者集合名 item 数组元素 separater item之间的连接符 open 开始符号 close 结束符号--> <delete id="deleteByIds"> delete from tb_brand where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach>
          ;
    </delete>

    17 MyBatis 参数传递

    1.MyBatis参数封装原理

    • MyBatis接口方法中的形参可以是多种类型的,MyBatis底层会对这些参数自动进行不同的封装

    • 通过 ParamNameResolver 类进行封装参数

    2.单个参数情况

    • POJO类型:直接使用,属性名 和 参数占位符名称 一致

    • Map集合:直接使用,键名 和 参数占位符名称 一致

    • Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

      • map.put("arg0",collection集合);

      • map.put("collection",collection集合);

    • List:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

      • map.put("arg0",list集合);

      • map.put("collection",list集合);

      • map.put("list",list集合);

    • Array:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

      • map.put("arg0",数组);

      • map.put("array",数组);

    • 其他类型:直接使用

    3.多个零散参数情况

    • 封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

    • 未使用@Param注解

      • map.put("arg0",参数值1)

      • map.put("param1",参数值1)

      • map.put("param2",参数值2)

      • map.put("agr1",参数值2)

    • 使用@Param注解

      • map.put("username",参数值1)

      • map.put("param1",参数值1)

      • map.put("param2",参数值2)

      • map.put("agr1",参数值2)

    4.建议

    • 以后都使用@Param()注解来修改指定的键名替换arg名(param键名不会被替换),方便记忆参数和提高可读性

     18 使用注解完成增删改查

    1.注解开发介绍

    • 在接口方法上,通过不同的注解,将SQL语句直接给定,可以省去映射配置文件的编写!

    • 例如

    @Select(value = "SELECT * FROM tb_brand WHERE id = #{id}")
    public Brand select(int id);

     

     

     

  • 相关阅读:
    格式化dataGridview里数据
    XtraGrid gridview基本用法
    winForm中如何控制listView的滚动条高手请进
    WinForm 和 Windows Service 通信 消息队列
    抽象工厂模式
    C#之访问控制修饰符
    JavaScript之变量
    Android之传感器(二)持续更新
    备忘录模式
    JavaScript之构造函数初了解
  • 原文地址:https://www.cnblogs.com/yang-qiu/p/15507571.html
Copyright © 2020-2023  润新知