mybatis动态Sql

Mybatis 动态sql

一.准备工作

mybatisX插件下载

mybatis代理开发(mapper接口和xml的对应)

在这里插入图片描述

二.xml增删改查

1.所有代码基本思路(接口方法–>xml–>测试)

mapper接口方法: 返回值 参数

xml中的statement : sql语句

测试:test测试代码

2. 查(重点!!!)

(略)查询所有(resultMap标签)和查询详情(#和$占位符,特殊符号处理)
查询所有:在一个界面中,显示一整张表(从数据库中查询所有信息)
  1. 基本语句:
<select id="selectAll" resultType="brand">
    select *
    from tb_brand;
</select>
  1. 问题:数据库中是company_name ,属性字段中是companyName,会发现这个数据查出来是null

  2. 解决(resultMap出现啦):

    1. (略)as命名(麻烦)
    <select id="selectAll" resultType="brand">
        select id,brand_name as brandName,company_name as companyName,order,description,status
        from tb_brand;
    </select>
    
    1. (略)include标签导入sql片段(当你要查询几个特定属性时,也麻烦)
    <sql id="brand_column">
        id,brand_name as brandName,company_name as companyName,order,description,status
    </sql>//sql片段设置
    <select id="selectAll2" resultType="brand">
        select <include refid="brand_column"/> //include标签导入sql片段
        from tb_brand;
    </select>
    
    1. (重点)resultMap-result解决:
    <resultMap id="brandMapper" type="brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap> 
        //将pojo类和数据库中不同名的在这里一次性设置好 
        // resultMap的type属性对应设置的pojo类名(因为在mybatis核心配置文件中用了 typeAliases 别名标签,所以可以忽略大小写,即brand和Brand均可)
        // column    对应数据库中的列名
        // property  对应pojo类中的属性名
    
    <select id="selectAll" resultMap="brandMapper">
        //这里的属性是 resultMap 而非 resultType 了!!!(直接整个导入)
        select *
        from tb_brand;
    </select>
    

    所以,后续创建一个xml时,第一件事就是来一个resultMap标签,将数据库和类名匹配,之后需要用到就直接用 resultMap

查询详情:点击该表中某个对象的查询按钮,跳转到另一个界面,显示该对象所有信息
  1. 基本语句

    <select id="selectById" resultMap="brandMapper">
        select *
        from tb_brand
        where id = #{id};//这里我们用#占位符,而非$,可以防止sql注入
    </select>
    
  2. 小小拓展

    当你要查询的条件是id<6的所有数据,要用到"<"号,但这是标签符号,所以,对于这种特殊符号,处理方式:

    (1)用转义字符

    <select id="selectMulById" resultType="com.kikky.pojo.Brand">
        select *
        from tb_brand
        where id  &lt; #{id};  //看这里的“<”的特殊字符!但是此方法不适用于有很多特殊字符的时候哦
    </select>
    

    ​ (2)用CDATA区(设置一个区, 写个CD,就会有提示)

    <select id="selectMulById" resultType="com.kikky.pojo.Brand">
        select *
        from tb_brand
        where id <![CDATA[
        <=
        ]]>#{id};  //这里只要打个CD,就会有提示,把字符放里面即可,当作纯文本处理
    </select>
    

    总结:

在这里插入图片描述

(重点)条件查询
基础语句(多参数的三种解决办法)
  1. 情景:

    用户输入很多条件,要根据id、companyName等查询对象,这时,我们又遇到了方法中形参和xml中占位符怎么对应的问题

举例:接口方法中,写的是:

Brand selectByConditions(String cName, String bName);
<select id="selectByConditions" resultMap="brandMapper">
    select *
    from tb_brand
    where company_name = #{companyName}//计算机并不知道这个companyName是谁,所以,我们要将方法中的形参和#中的占位符绑定,让sql语句可以识别并拿到用户输入的条件
          and
          brand_name = #{brandName}
</select>
  1. 三种解决方式:

    • 接口和对应的测试代码

    ​ 1. 散装,用@Param注解(注解名 要和statement中占位符名一致

//mapper接口方法示例:对每一个参数设置注解,让其可以在statement中被识别
List<Brand> selectByCondition(@Param("status")int status, @Param("companyName") String company_name, @Param("brandName") String brand_name);
//测试代码示例:注意模糊查询的通配符使用
int status = 1;
String company_name = "华为";
String brand_name = "华为";
company_name ="%"+company_name+"%";
brand_name ="%"+brand_name+"%";
//注意sql语句用到了like,参数要有 通配符 %  !(模糊查询)
List<Brand> brands = mapper.selectByCondition(status,company_name,brand_name);

	    	2. 封装成对象 (**对象的属性名  要和xml中占位符一致** )
//mapper接口方法示例:形参是一个Brand对象
//这里就要注意Brand类中的属性名和 对应statement中的占位符 一样!!!
List<Brand> selectByCondition( Brand brand);
//测试代码示例:
Brand brand = new Brand();
brand.setStatus(status);
brand.setBrandName(brand_name);
brand.setCompanyName(company_name);//Brand类的属性名要与占位符一致
List<Brand> brands = mapper.selectByCondition(brand);
  		3. 封装成map集合(**集合的键名  要和statement中占位符名一致**)
//mapper接口方法示例:形参是一个map集合
List<Brand> selectByCondition(Map map);
//测试代码示例:
Map map =new HashMap();
map.put("status",status);
map.put("brandName",brand_name);
map.put("companyName",company_name);//键名要与占位符一致
List<Brand> brands = mapper.selectByCondition(map);
  • ​ xml中的statement
  <select id="selectByConditions" resultMap="brandMapper">
        select *
        from tb_brand
        where status = #{status}
        and company_name  like #{companyName}
        and brand_name like #{brandName};
-- 多条件查询有个问题就是,sql语句中的占位符到底对应mapper方法中哪一个参数,重点学习和掌握!!!
-- 注意这里sql语句左侧是数据库中列名,右侧占位符一般写成 类的属性名,(与BrandMapper方法中不同的参数,散装、对象、map集合对应)
    </select>

总结:

在这里插入图片描述

多条件动态查询( where if 标签)
  1. 情景:用户只输入了 status 和 company_name就点击了查询,其他条件为null!

  2. 解决:if判读呀–>if标签

    <select id="selectByCondition" resultMap="brandMapper">
        select *
        from tb_brand
        where
            <if test="status !=null"> //这里根据参数封装情况不同,也可以写成status!=0
                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>
    </select>
    
  3. 新问题:and 必须根据情况 决定 有没有–>where标签

    当我只输入了company_name时,语句变成了

    select * from tb_brand where and company_name like ? ;//要报错啊
    

    有恒等式和标签方法,这里重点介绍mybatis提供的标签(mybatis:我都帮你弄好了~~)

    • 恒等式:

      那怎么办,我们在status语句前也写上and ,然后在where 后面直接加一个 1=1 !

       <select id="selectByCondition" resultMap="brandMapper">
              select *
              from tb_brand
      //动态sql
              where 1=1
              <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>
      // 注意这里sql语句左侧是数据库中列名,右侧占位符一般写成 类的属性名,(与BrandMapper方法中不同的参数,散装、对象、map集合对应)
          </select>
      
    • 标签

      看官网给where标签(元素)的定义:

      where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除

      所以,当where标签会自动智能地决定 where关键字和and的去留,你只管写就好了(但别忘了要加and)

      <select id="selectByCondition" resultMap="brandMapper">
          select *
          from tb_brand
         <where>  //智能的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>
      
单条件动态查询(choose-when-otherwise )
  1. 情景:用户只选择一个条件进行查询,比如,在第一个文本框中选择 公司名,在第二个文本框中输入 华为 ,我们事先并不知道他要选哪个条件(你可能会想,这不是用上面的就能实现嘛,但是标签设计的用途不一样嘛,就像你可以用if-else if-else 也可以用switch-case-default一样)

  2. 示例:

    类比:choose-when-otherwise 相当于 switch-case-default

    <select id="selectBySingleCondition" resultMap="brandMapper">
            select *
            from tb_brand
            where
                <choose>  //相当于 switch ,最后只会有一个条件成立
                  <when test=" status !=null">  //相当于 case
                       status = #{status}
                  </when>
                  <when test="companyName !=null and companyName !=''">
                       company_name like #{companyName}
                  </when>
                  <when test="brandName !=null and brandName !=''">
                        brand_name like #{brandName}
                  </when>
                  <otherwise>  // 相当于default
                      1 = 1
                  </otherwise>
                </choose>
        </select>
    

3. 增(Mybatis的事务问题、主键返回)

增就没什么标签了,我们老老实实地用对象封装参数

<insert id="add" >
    insert into tb_brand (brand_name,company_name,ordered,description,status)
    values (#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>
sqlSession自动提交

但是,在按照正常流程写完代码后,你发现运行都正常,但是在数据库中就是没有新添加的结果,为什么呢,因为mybatis的事务问题,看日志会发现,添加成功后它没有提交,所以又回滚了;

那么我们可以手动用sqlSession设置开启事务,或者是在创建sqlSession的时候就设置自动开启

//自动开启事务 
SqlSession sqlSession = sqlSessionFactory.openSession(true);
int status = 1;
String company_name = "当当";
int ordered = 50;
String brand_name = "挡挡";
String description = "致力于";
Brand brand = new Brand(company_name,brand_name,ordered,description,status);
mapper.add(brand);

//最后手动开启事务
sqlSession.commit();
sqlSession.close();
主键返回

我们想得到新添加的对象的id,于是有以下代码:

mapper.add(brand);
System.out.println(brand.getId());//获取这个对象的id,但是结果是0(没有设置时的默认值)

实际上在insert语句执行的时候就已经有Id了,只是还没有与对象绑定,我们只要在insert标签中设置这useGeneratedKeys ** 和keyProperty** 两个属性即可:

//添加的statement
//设置useGeneratedKeys为true,设置keyProperty为对象中的id字段(所以用对象封装参数!!!)
<insert id="add" keyProperty="id" useGeneratedKeys="true">
    insert into tb_brand (brand_name,company_name,ordered,description,status)
    values (#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>   

这样一来,就可以查询到新添加的对象id了

4. 改(set 标签 )

  1. 修改全部字段

    简单的sql语句:

    <update id="updateById">
        update tb_brand
        set 
         status =#{status},
         company_name = #{companyName},
         brand_name = #{brandName},
         ordered = #{ordered},
         description = #{description}, //封装成对象或者map集合都可
        where
            id = #{id}
    </update>
    
  2. 修改动态字段

    有时不是要修改所有,所以还是和查一样,我们用 if标签 判断,用set标签 解决多余的逗号和set关键字问题

    <update id="updateById" >
        update tb_brand
        <set>
         <if test="status !=0">
             status = #{status},
         </if>
        <if test="companyName!=null and companyName!=''">
            company_name = #{companyName},
        </if>
        <if test="brandName!=null and brandName!=''">
            brand_name = #{brandName},
        </if>
        <if test="ordered!=0">
            ordered = #{ordered},
        </if>
        <if test="description!=null and description!=''">
            description = #{description},
        </if>
        </set>
        where
            id = #{id}
    </update>
    

5.删

删除一个(基础语句)
<delete id="deleteById">
    delete
    from tb_brand
    where
        id = #{id}
</delete>
批量删除(for each标签 )

当用户选择了很多商品需要删除时

我们将ids封装成一个数组,或是list集合均可,下面代码是封装成集合的代码:

  1. mapper接口方法:
int deleteByMulId(List<Integer> ids);  
  1. 对应statement:
<delete id="deleteByMulId">
    delete
    from tb_brand
    where id in
     <foreach collection="list" separator="," item="id" open="(" close=")">
          #{id}
     </foreach>
</delete>
  • 对于for each标签中的属性:
  1. collection属性:

根据mapper中形参的不同,分别对应:

array 当形参为数组时

list 当形参为list集合时 (比如我这个例子)

或者是arg0(和后面mybatis封装参数的底层原理)

或者是你对形参进行@params注解的参数名称!如下:

int deleteByMulId(@Param("ids") List<Integer> ids);

于是,我们才可以在collection属性中用 “ids”,否则会报错!!!

<foreach collection="ids" separator="," item="id" open="(" close=")">
    #{id}
</foreach>
  1. item属性:很简单,就是给每一个元素的名字
  2. seperator属性:分隔符,因为在sql语句中, in 后面要加的一系列值是用逗号分隔开的
  3. open和close属性:表示此语句分别以open和close中的字符开始和结束(这样左右括号就不用打在外面了)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值