MyBatis(中)

目录

1、动态sql:

1、if标签:

2、where标签:

3、 trim标签:

4、set标签:

5、choose when otherwise:

6、模糊查询的写法:

 7、foreach标签:

(1)批量删除:

(2)批量插入:

8、include标签:

2、MyBatis的高级映射:

1、多对一:

(1)级联属性映射:

(2)association:

(3)分步:

 2、一对多:

(1)collection标签:

(2)分步:


1、动态sql:

1、if标签:

mapper接口:

//if 标签  多条件查询
    List<Car> selectByMultiConditional(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

mapper映射文件:

 <select id="selectByMultiConditional" resultType="Car">
        select *
        from t_car
        where 1=1
        <!-- if标签中的test的属性是必须的
             if标签中的test的属性值是true或者是false
             如果是ture 拼接if标签里面的sql语句

             test属性中可以使用的数据:
             如果使用啦Param的注解  那么只能只用Param的注解里面的参数
             如果没有使用Param的注解的话,那么使用的是可以是Param1 param2... 或者arg0 arg1...

             如果传递的不是某一个属性值而是对象,那么可以使用的数据只能是对象里面的字段

        -->
        <if test="brand !=null and brand!=''">
           and brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice !=null and guidePrice!=''">
            and guide_price > #{guidePrice}
        </if>
        <if test="carType !=null and carType!=''">
            and car_type =#{carType}
        </if>
    </select>

 测试类:

/**
     * 使用if标签多条件查询
     */
    @Test
    public void test1(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> carList = mapper.selectByMultiConditional(null,null,null);//什么参数也没有
        carList.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("--------------");
        List<Car> carList1 = mapper.selectByMultiConditional("保时捷", 100.0, null);//两个参数
        carList1.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("--------------");
        List<Car> carList2 = mapper.selectByMultiConditional("比亚迪", 25.0, "混动");
        carList2.forEach(car -> {
            System.out.println(car);
        });

2、where标签:

where标签的作用:让where子句更加动态智能。

  • 所有条件都为空时,where标签保证不会生成where子句。
  • 自动去除某些条件前面多余的and或or。

 mapper接口:

//if 和 where标签一起使用
    List<Car> selectByMultiConditionalWithWhere(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

mapper映射文件:

 <select id="selectByMultiConditionalWithWhere" resultType="Car">
        select *
        from t_car
        <!--
            where 标签的使用可以使where的语句更加灵活
            如果所有的条件都不成立,那么就不会有where语句
            真好 也不用拼1=1 啦
        -->
        <where>
            <if test="brand !=null and brand!=''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice !=null and guidePrice!=''">
                and guide_price > #{guidePrice}
            </if>
            <if test="carType !=null and carType!=''">
                and car_type =#{carType}
            </if>
        </where>
 </select>

 测试类:

 /**
     * 使用if 和 where 标签多条件查询
     */
    @Test
    public void test2(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> carList = mapper.selectByMultiConditionalWithWhere(null,null,null);//什么参数也没有
        carList.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("--------------");
        List<Car> carList1 = mapper.selectByMultiConditionalWithWhere("保时捷", 100.0, null);//两个参数
        carList1.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("--------------");
        List<Car> carList2 = mapper.selectByMultiConditionalWithWhere("比亚迪", 25.0, "混动");
        carList2.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("--------------");
        List<Car> carList3 = mapper.selectByMultiConditionalWithWhere(null, 100.0, null);
        carList3.forEach(car -> {
            System.out.println(car);
        });
    }

总结:

        使用where的标签的话可以去where语句的前面的and或者or,但是不可去除条件语句的后面的and或者or 

3、 trim标签:

trim标签的属性:

  • prefix:在trim标签中的语句前添加内容
  • suffix:在trim标签中的语句后添加内容
  • prefixOverrides:前缀覆盖掉(去掉)
  • suffixOverrides:后缀覆盖掉(去掉)

mapper接口:

 <select id="selectByMultiConditionalWithTrim" resultType="Car">
        select *
        from t_car
        <!--
            prefix: 在trim标签的内容的前面加上 前缀
            suffix: 在trim标签的内容的后面加上 后缀
            prefixOverrides: 将删除trim标签 指定的前缀
            suffixOverrides: 删除trim标签 指定的后缀
        -->
        <trim prefix="where" suffixOverrides="or|and">
            <if test="brand !=null and brand!=''">
                 brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice !=null and guidePrice!=''">
                guide_price > #{guidePrice} and
            </if>
            <if test="carType !=null and carType!=''">
                car_type =#{carType}
            </if>
        </trim>
    </select>

测试和接大差不差,就不复制粘贴啦,主要是看Trim标签怎么使用的! 

4、set标签:

主要使用在update语句当中,用来生成set关键字,同时去掉最后多余的“,”

比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。

 mapper接口:

//set 标签  通常用于更新操作
    int updateCarWithSetById(Car car);

mapper映射文件:

<update id="updateCarWithSetById">
        update t_car
        <set>
            <if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
            <if test="brand != null and brand != ''">brand = #{brand},</if>
            <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
            <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
            <if test="carType != null and carType != ''">car_type = #{carType},</if>
        </set>
        where
        id =#{id}
    </update>

测试方法:

//测试 set标签
    @Test
    public  void test5(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int count = mapper.updateCarWithSetById(new Car(169L, "凯迪拉克", null, 12.5, null, "燃油"));
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

5、choose when otherwise:

语法格式:

<choose>
  <when></when>
  <when></when>
  <when></when>
  <otherwise></otherwise>
</choose>

相当于java中的if-else  只有一个分支会被执行!!

需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。

mapper接口:

//choose when otherwise
    /*需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。*/
    List<Car> selectByChoose (@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("produceTime") String produceTime);

mapper映射文件:

<select id="selectByChoose" resultType="Car">
        select *
        from t_car
        <where>
            <choose>
                <when test="brand != null and brand != ''">brand = #{brand}</when>
                <when test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice}</when>
                <otherwise>produce_time = #{produceTime}</otherwise>
            </choose>
        </where>
    </select>

 测试类:

//测试 choose when otherwise
    @Test
    public void test6(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> carList = mapper.selectByChoose("比亚迪汉", null, "2000-01-02");
        carList.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("-------------------");
        List<Car> carList1 = mapper.selectByChoose(null, 120.0, "2000-01-02");
        carList1.forEach(car -> {
            System.out.println(car);
        });
        System.out.println("-------------------");
        List<Car> carList2 = mapper.selectByChoose(null, null, "2000-01-02");
        carList2.forEach(car -> {
            System.out.println(car);
        });
    }

测试结果:

        这里的sql语句可以很直观的看出来,这个choose的特点就是只有一个条件会被执行,即使其传递的参数也符合要求。

6、模糊查询的写法:

方法一:
brand like '%${brand}%'
方法二:
brand like concat('%',#{brand},'%')
方式三:
brand like "%"#{brand}"%"

经常使用方式三!

 7、foreach标签:

(1)批量删除:

mapper接口:

 //foreach 通过ids来批量删除
    int deleteByIdsUseForeach(@Param("ids") Long[] ids);

 mapper映射文件:

<delete id="deleteByIdsUseForeach">
        delete
        from t_car
        <!--
            foreach 标签的属性 :
            collection 用来指定是数组还是集合
            item  代表数组或者集合中的元素
            separtor  循环之间的分割符

        -->
        where id in (
            <foreach collection="ids" item="id" separator="," >
                #{id}
            </foreach>
            )
    </delete>

小括号也可以不写 就是 in(....)

<delete id="deleteByIdsUseForeach">
        delete
        from t_car
        <!--
            foreach 标签的属性 :
            collection 用来指定是数组还是集合
            item  代表数组或者集合中的元素
            separtor  循环之间的分割符
            open:foreach标签中所有内容的开始
            close:foreach标签中所有内容的结束

        -->
        where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

 上面是使用in的方式来实现的批量删除的操作,那么如果是实现的是or的关键字的话,那么sql的语句可以这样写:

<delete id="deleteBatchByForeach2">
  delete from t_car where
  <foreach collection="ids" item="id" separator="or">
    id = #{id}
  </foreach>
</delete>

测试类:

//测试批量删除
    @Test
    public void test7(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long[] ids ={198L,199L,200L};
        int count = mapper.deleteByIdsUseForeach(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }
(2)批量插入:

mapper接口:

//foreach 实现批量插入
    int insertBatchByForeach(@Param("carList") List<Car> carList);

mapper映射文件:

<insert id="insertBatchByForeach">
        insert into t_car values
        <foreach collection="carList" item="car" separator=",">
            (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
        </foreach>
    </insert>

测试类:

//批量插入
    @Test
    public void test8() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car1=new Car(null,"雷克萨斯","1334",56.0,"2015-7-25","燃油");
        Car car2=new Car(null,"阿斯顿·马丁DBS","6989",400.5,"2022-7-1","混动");
        Car car3=new Car(null,"迈凯伦GT","7997",123.2,"2019-10-25","燃油");
        List<Car> carList=new ArrayList<>();
        Collections.addAll(carList,car1,car2,car3);
        int count = mapper.insertBatchByForeach(carList);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

8、include标签:

sql标签用来声明sql片段

include标签用来将声明的sql片段包含到某个sql语句当中

作用:代码复用。易维护。

<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType</sql>

<select id="selectAllRetMap" resultType="map">
  select <include refid="carCols"/> from t_car
</select>

<select id="selectAllRetListMap" resultType="map">
  select <include refid="carCols"/> carType from t_car
</select>

<select id="selectByIdRetMap" resultType="map">
  select <include refid="carCols"/> from t_car where id = #{id}
</select>

2、MyBatis的高级映射:

1、多对一:

(1)级联属性映射:

mapper接口:

//根据sid获取去学生对象,同时获取学生关联的班级信息
    Student selectBySid(Integer sid);

mapper映射文件:

<!--级联属性映射  多对一 -->
    <resultMap id="studentResultMap" type="Student">
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <result property="clazz.cid" column="cid"></result>
        <result property="clazz.cname" column="cname"></result>
    </resultMap>

    <select id="selectBySid" resultMap="studentResultMap">
        select s.sid, s.sname, c.cid, c.cname
        from t_stu as s
                 left join t_clazz as c on s.cid = c.cid
        where s.sid = #{sid}
    </select>

测试:

//多对一 级联属性映射
    @Test
    public void test1(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectBySid(100);
        System.out.println(student);
    }
(2)association:

 mapper接口:

//association标签
    Student selectBySidAssociation(Integer sid);

mapper映射文件:

 <resultMap id="studentResultMapAssociation" type="Student">
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <association property="clazz" javaType="Clazz">
            <id property="cid" column="cid"></id>
            <result property="cname" column="cname"></result>
        </association>
        <!--
            association: 一个是student关联一个clazz对象
            property: 提供要映射的pojo类的属性名
            javaType: 用来指定要映射的java类型
        -->
    </resultMap>
    <select id="selectBySidAssociation" resultMap="studentResultMapAssociation">
        select s.sid, s.sname, c.cid, c.cname
        from t_stu as s
                 left join t_clazz as c on s.cid = c.cid
        where s.sid = #{sid}
    </select>

测试:

//多对一 使用association标签
    @Test
    public void test2(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectBySidAssociation(100);
        System.out.println(student);
    }
(3)分步:

mapper接口   第一步  查cid

//分步查询的第一步  通过sid查出来学生信息
    Student selectBySidOne(Integer sid);

 mapper映射文件:

<resultMap id="selectByIdOne" type="student">
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <!--select 用来指定另外一个select语句的id-->
        <association property="clazz"  select="com.songzhishu.mybatis.mapper.ClazzMapper.selectByCidTwo" column="cid">
        </association>
    </resultMap>
    <select id="selectBySidOne" resultMap="selectByIdOne">
        select sid,sname,cid
        from t_stu
        where sid = #{sid}
    </select>

mapper接口:  第二步 查信息

//分步查询 根据班级id查询班级信息
   Clazz  selectByCidTwo(Integer cid);

mapper映射问价:

<select id="selectByCidTwo" resultType="Clazz">
        select *
        from t_clazz
        where cid = #{cid}
    </select>

 测试:

//多对一 分步查询
    @Test
    public void test3(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectBySidOne(101);
        System.out.println(student);
    }

        首先说一下,就是复用性好是什么意思,这里讲的是我现在的需求是根据学生的sid来出查询出来学生的班级信息,然后就编写了两个sql语句,一个是根据sid查学生的信息,然后另外一个是根据cid查询出来班级的信息,这是两个sql语句,分别摘开都可以使用的,这就是可以复用。

        然后就是我们现在的需求是有限定的条件,通过sid确定学生,然后根据学生确定班级,但是我不是每一次都要想查询班级的信息呀,那怎么办,这就要提出来延迟加载。

        他的核心就是用的时候使用select语句,不用的时候不使用,这样可以减少查询的条件提高性能!开启延迟加载的方式也很简单 ,再Assoication标签内部的属性中加上,fetchType属性,在默认的情况先,懒加载是关闭的

<association property="clazz"  select="com.songzhishu.mybatis.mapper.ClazzMapper.selectByCidTwo" column="cid"
        fetchType="lazy">

测试:

@Test
    public void test3(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectBySidOne(101);
        System.out.println(student.getSname());//只要名字  //只执行一条sql
        System.out.println(student); //要全部的信息  //执行两个
    }

 这里我将测试的语句都写出来啦,测试后的时候可以注释掉其中一个!

上面的只是针对这个一个Association标签内部的分步开启延迟加载,如果想在全局开启的话,可以在核心配置文件中设置一下字段:

<!--开启全局的懒加载 默认是false -->
        <setting name="lazyLoadingEnabled" value="true"/>

        这样全局的分步都可以使用延迟加载的方式,需要的时候才使用分步,不需要的时候就采用延迟加载从而达到性能的优化,如果配置后针对某一部分的分部的操作不需要使用延迟加载的话,也就可以在Association字段中设置:

fetchType="eager"

 2、一对多:

(1)collection标签:

mapper接口 Clazz


   //根据班级编号查询班级信息
    Clazz selectByCid(Integer cid);

 mapper映射文件:

<resultMap id="selectByCidMap" type="Clazz">
        <id property="cid" column="cid"></id>
        <result property="cname" column="canme"></result>
        <!--
            一对多 collection
            ofType="student" 用来指定集合中元素的类型
        -->
        <collection property="studentList" ofType="student">
            <id property="sid" column="sid"></id>
            <result property="sname" column="sname"></result>
        </collection>
    </resultMap>

    <select id="selectByCid" resultMap="selectByCidMap">
        select c.cid,c.cname,s.sid, s.sname
        from t_clazz as c
                 left join t_stu as s on c.cid = s.cid
        where c.cid = #{cid}
    </select>

测试:

//一对多
    @Test
    public void test4(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);
        Clazz clazz = mapper.selectByCid(1000);
        System.out.println(clazz);
    }
(2)分步:

mapper接口:  cLazz 第一步

  //分步查询 跟据编号获取班级信息
    Clazz selectByCidOne(Integer cid);

mapper映射文件:  一对多

<resultMap id="selectByCidOneMap" type="clazz">
        <id property="cid" column="cid"></id>
        <result property="cname" column="cname"></result>
        <collection property="studentList" ofType="student" select="com.songzhishu.mybatis.mapper.StudentMapper.selectByCidTwo" column="cid">
        </collection>
    </resultMap>

    <select id="selectByCidOne" resultMap="selectByCidOneMap">
        select cid,cname
        from t_clazz
        where cid = #{cid}
    </select>

mapper接口 student

//一对多  第二步 根据cid查询 学生信息
   List<Student> selectByCidTwo(Integer cid);

mapper映射文件:

 <select id="selectByCidTwo" resultType="Student">
        select *
        from t_stu
        where cid=#{cid}
    </select>

测试类

 //一对多 分步
    @Test
    public void test5(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);
        Clazz clazz = mapper.selectByCidOne(1001);
        System.out.println(clazz);
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值