动态SQL,模糊查询,关联查询

一.#{}和${}的区别

  • 相同点:这两个都是占位符,用来指定传入sql的参数
  • 不同点:
    • #{}这个是预编译的,不会发生sql注入,如果需要使用拼接的话可以使用sql的内置函数contact()
    • ${}这个是将其中的变量通过字符串拼接的方式插入到sql语句中的,容易发生sql注入,尽量避免使用

二.参数

1.多个参数

当我涉及到多个参数传参的时候,这个时候,我们直接使用变量名会发现控制台有错误提示
 Parameter ‘XXX’ not found. Available parameters are [arg1, arg0, param1, param2]
这一行报错的意思是XXX变量没有生命,我们可以用的变量名为arg1,arg0,param1,param2
当我们有多个变量的时候,我们就需要通过arg0,arg1来获取对应的变量了

// 接口方法
int updateNickname( int id,String nickname);
<update id="updateNickname">
  # 读取第二个变量nickname和第一个变量id
  update t_user set nickname = #{arg1} where id = #{arg0}
</update>

这种方式不是特别直观,当我们调整顺序之后,相应的xml里的顺序也需要调整,故我们一般会通过第二种方式来解决这个问题。通过注解的方式

// 接口方法
 int updateNickname( @Param("id") int id,@Param("nickname")String nickname);
    <update id="updateNickname">
        update t_user set nickname = #{nickname} where id = #{id}
    </update>

2.包装类型单个参数

java有八个基本数据类型,我们在使用这些基本数据类型,可以直接取到对应的value,比如我们上次课程中涉及到的int类型。
但是当我们的参数是包装类型时,比如String或者是User的实体类,这时mybatis就或读取包装类型中的属性,比如我们在使用User实体类时,直接使用实体类中的#{id}属性。但是String类型并没有对应的属性,我们希望的是直接获取String中的值,那么我们在取值的时候,就会出现这个错误。
 There is no getter for property named ‘xxx’ in ‘class java.lang.String’
这个报错的意思就是从String类型中获取不到xxx属性
这个使用我们也需要通过@Param的注解来解决这个问题

// 接口方法
List<User> selectList(@Param("orderBy") String orderBy);
<select id="selectList" parameterType="String" resultType="User">
    select * from t_user ${orderBy}
</select>

3.实体类参数与基本类型参数混用

直接看例子就明白了

// 接口方法
List<User> selectList(@Param("orderBy") String orderBy,@Param("user") User user);
<select id="selectList" resultType="User">
    select * from t_user where username = #{user.username} ${orderBy} 
</select>

三.paramerterType , resultType , resultMap

1.paramerterType

参数的类型

单个基本类型可以不写
参数有多种类型的时候不写
实体类必须写

2.resultType

返回值类型
除了查询,其他的都可以不写,因为其他的返回值都是int(默认影响的行数)

3.resultMap

返回值map
使用场景:
实体类与数据库表字段不一致,例如表中的字段是user_id,实体中的是userId,那么就需要进行一下映射,方法如下

<resultMap id = "mapName" type="User" autoMapping="ture">
<result column="user_id" property="userId">
</resultMap>

type映射实体的类型,比如user表映射的是User实体类
autoMapping="true"会自动的将同名的字段映射
result标签中的column对应的数据表的字段名,property对应的是实体类中的属性

四.动态SQL

直接上代码

1.StudentMapper接口

package com.tl.mybatis02.mapper;

import com.tl.mybatis02.model.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @author Antg
 * @date 2021/8/39:59
 */
public interface StudentMapper {

    /***************************** 动态sql ***********************************/
    //使用if语句
    public List<Student> find(Student student);

    //使用choose when otherwise
    public List<Student> useChoose(Student student);

    //where
    public List<Student> useWhere(Student student);

    //set
    public int useSet(Student student);

    //foreach 循环插入
    public int useForEach01(@Param("list01") List<Student> studentList);

    //foreach 循环in
    public List<Student> useForEach02(@Param("idList") Integer[] idList);

    //根据id查询
    public Student findStuById(@Param("id") Integer id);

    
}

2.StudentMapper.xml

<?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">
<mapper namespace="com.tl.mybatis02.mapper.StudentMapper">

    <resultMap id="stuResult" type="Student">
        <id column="id" property="id"/>
        <result column="username" property="username"></result>
        <result column="nickname" property="nickname"></result>
    </resultMap>

    <!-- ############################### 动态sql #################################  -->

    <!--动态sql 使用if-->
    <select id="find" parameterType="Student" resultMap="stuResult">
        select * from student_info where true
        <if test="username != null and username != ''">
            and username =
            #{username}
        </if>
        <if test="nickname != null and nickname != ''">
            and nickname like concat('%',
            #{nickname},
            '%'
            )
        </if>
    </select>

    <!--动态sql 使用choose-->
    <select id="useChoose" parameterType="Student" resultType="Student">
        select * from student_info where 1=1
        <choose>
            <when test="id != null">
                and id = #{id}
            </when>
            <when test="username != null and username != ''">
                and username = #{username}
            </when>
            <otherwise>
                and nickname = #{nickname}
            </otherwise>
        </choose>

    </select>

    <!--动态sql 使用where-->
    <select id="useWhere" parameterType="Student" resultMap="stuResult">
        select * from student_info
        <where>
            <if test="username != null and username != ''">
                and username =
                #{username}
            </if>
            <if test="nickname != null and nickname != ''">
                and nickname like concat('%',
                #{nickname},
                '%'
                )
            </if>
        </where>
    </select>

    <!--动态sql 使用set-->
    <update id="useSet">
        update student_info
        <set>
            <if test="username != null and username != ''">
                username =
                #{username},
            </if>
            <if test="nickname != null and nickname != ''">
                nickname =
                #{nickname},
            </if>
        </set>
        where id = #{id}
    </update>

    <!--动态sql 使用forEach循环插入-->
    <insert id="useForEach01">
        insert into student_info(username, password, nickname, age, birthday) values
        <foreach collection="list01" item="item" separator=",">
            (#{item.username}, #{item.password}, #{item.nickname}, #{item.age}, #{item.birthday})
        </foreach>
    </insert>

    <!--动态sql 使用forEach in查询-->
    <select id="useForEach02" resultType="Student">
        select * from student_info where id in
        <foreach collection="idList" item="item" separator="," open="(" close=")">
            #{item}
        </foreach>
    </select>


</mapper>

五.联查

1.一对一

接口

package com.tl.mybatis02.mapper;

import com.tl.mybatis02.model.Address;

public interface AddressMapper {
    /***************************** 一对一 ***********************************/
    public Address findAddressById(Integer id);

    public Address findAddressById2(Integer id);

    public Address findAddressById3(Integer id);

    /***************************** 一对多 ***********************************/
    public Address findById(Integer id);

}

xml

<?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">
<mapper namespace="com.tl.mybatis02.mapper.AddressMapper">

    <!-- ############################### 联查之一对一 #################################  -->

    <!-- 方法一: 使用select引入其他mapper中的方法-->
    <resultMap id="addressMap" type="Address" autoMapping="true">
        <!--        &lt;!&ndash;因为实体类和数据库中的字段不一样,所以要在这里映射一下&ndash;&gt;-->
        <result column="stu_id" property="stuId"></result>
        <association property="student" column="stu_id" javaType="Student"
                     select="com.tl.mybatis02.mapper.StudentMapper.findStuById"></association>
    </resultMap>
    <!--这里一定要写resultMap,切记不要写成resultType了,否则就不会找到上面写的Map-->
    <select id="findAddressById" parameterType="Integer" resultMap="addressMap">
        select *
        from address
        where id = #{id}
    </select>

    <!--方法二:直接进行联查-->
    <!--  可以使用resultMap配置映射字段,即数据库和javaBean中的对应字段,需要转换的字符可以在association中进行配置  -->
    <!-- 这里设置autoMapping可以进行自动封装-->
    <resultMap id="addressMap2" type="Address" autoMapping="true">
        <result column="id" property="id"/>
        <association property="student" column="stu_id" javaType="Student" autoMapping="true">
            <id column="stu_id" property="id"></id>
            <!-- 这里的id必须加,因为在进行联查的时候将Student的id是stu_id,而在实体类中是id,所以得进行一下转换,否则就将address中的id映射到了student中了 -->
        </association>
    </resultMap>
    <select id="findAddressById2" resultMap="addressMap2">
        select *
        from address a
                 inner join student_info s on a.stu_id = s.id
        where a.id = #{id}
    </select>

    <!--方法三:嵌套的resultType-->
    <resultMap id="addressMap3" type="Address" autoMapping="true">
        <association property="student" column="stu_id" resultMap="stuMap"></association>
    </resultMap>
    <resultMap id="stuMap" type="Student" autoMapping="true">
        <id column="stu_id" property="id"></id>
    </resultMap>
    <select id="findAddressById3" parameterType="Integer" resultMap="addressMap3">
        select a.id,
               stu_id,
               address,
               phone,
               consignee,
               username,
               password,
               nickname,
               age,
               birthday,
               del_state,
               create_time,
               update_time
        from address a
                 inner join student_info s on a.stu_id = s.id
        where a.id = #{id}
    </select>

</mapper>

2.一对多

接口

package com.tl.mybatis02.mapper;

import com.tl.mybatis02.model.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @author Antg
 * @date 2021/8/39:59
 */
public interface StudentMapper {

    /***************************** 一对多联查 ***********************************/
    //方法一:调用别的mapper中的方法
    public Student findoneToMany1(Integer id);

    //方法二:直接进行联查,在association中进行转换
    public Student findoneToMany2(Integer id);

    //方法三:嵌套resultMap
    public Student findoneToMany3(Integer id);
    
}

xml

<?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">
<mapper namespace="com.tl.mybatis02.mapper.StudentMapper">

    <!-- ############################### 一对多联查#################################  -->

    <!--  方法一:调用别的mapper中的方法  -->
    <resultMap id="studentMap1" type="Student" autoMapping="true">
        <id column="id" property="id"></id><!--这里的id有合并的作用,去掉后会查询出多条记录,就不对了-->
        <collection property="addressList" column="id" autoMapping="true"
                    select="com.tl.mybatis02.mapper.AddressMapper.findById"></collection>
    </resultMap>
    <select id="findoneToMany1" parameterType="Integer" resultMap="studentMap1">
        select *
        from student_info
        where id = #{id}
    </select>

    <!--  方法二:直接进行联查,在collection中进行转换  -->
    <resultMap id="studentMap2" type="Student" autoMapping="true">
        <id column="id" property="id"></id><!--这里的id有合并的作用,去掉后会查询出多条记录,就不对了-->
        <collection property="addressList" ofType="Address" autoMapping="true">
            <id column="address_id" property="id"></id>
        </collection>
    </resultMap>
    <select id="findoneToMany2" parameterType="Integer" resultMap="studentMap2">
        select s.id as id,
               username,
               password,
               nickname,
               age,
               birthday,
               a.id as address_id,
               stu_id,
               address,
               phone,
               consignee
        from student_info s
                 left join address a
                           on s.id = a.stu_id
        where s.id = #{id}
    </select>
    <resultMap id="findoneToMany3" type="Student" autoMapping="true">
        <id column="id" property="id"></id><!--这里的id有合并的作用,去掉后会查询出多条记录,就不对了-->
        <collection property="addressList" column="id" ofType="Address" resultMap="addressMap3"></collection>
    </resultMap>
    <resultMap id="addressMap3" type="Address">
        <id column="address_id" property="id"></id>
    </resultMap>
    <!--  方法三:嵌套resultMap  -->
    <select id="findoneToMany3" parameterType="Integer" resultMap="findoneToMany3">
        select s.id as id,
               username,
               password,
               nickname,
               age,
               birthday,
               a.id as address_id,
               stu_id,
               address,
               phone,
               consignee
        from student_info s
                 left join address a
                           on s.id = a.stu_id
        where s.id = #{id}
    </select>
</mapper>


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mizui_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值