2022-03-31 西安 mybatis(2) #{}和${}、5种查询功能、特殊sql

一、获取mapper接口方法里的参数

#{}的本质就是占位符赋值 ; ${}的本质就是字符串拼接

#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;

Mybatis在处理${}时,就是把${}替换成变量的值

1.参数为单个字面量类型

User getUserByname(String username);

注意的是:单个参数下#{}这里写啥名称不重要,任意名称都可以

<!--    User getUserByname(String username);-->
        <select id="getUserByname"  resultType="user">
<!--       select * from t_user where username=#{aaa}  单个参数,这样写也行,只是推荐用下面这种方式见名知意-->
           select * from t_user where username=#{username} 
        </select>

如果要是用${},该怎么写呢。用${},要记得加单引号

        <select id="getUserByname"  resultType="user">
<!--        select * from t_user where username='${aaa}'  单个参数,这样写也行,只是推荐用下面这种方式见名知意-->
           select * from t_user where username='${username}'
        </select>

2.参数有多个时

User checkLogin(String username,String password);

先来个错误但是很容易犯的写法

mapper接口方法有多个参数的时候的错误写法
<!--    User checkLogin(String username,String password);-->
        <select id="checkLogin"  resultType="user">
           select * from t_user where username=#{username} and password= #{password}
        </select>

多个参数的情况下,mybatis会自动把我们的多个参数封装为map。以俩种方式存储

  1. 以arg0,arg1...为键,以参数为值
  2. 以param1,param2...为键,以参数为值

mapper映射文件写sql取参数值的时候,需要通过#{键}的方式就可以拿到map集合的值了,如下:

mapper接口方法有多个参数的时候的正确的写法是
<!--    User checkLogin(String username,String password);-->
        <select id="checkLogin"  resultType="user">
<!--           select * from t_user where username=#{param1} and password= #{param2}-->
           select * from t_user where username=#{arg0} and password= #{arg1}
        </select>

多个参数也可以使用${},注意单引号的使用,但是不推荐${}

<!--    User checkLogin(String username,String password);-->
        <select id="checkLogin"  resultType="user">
           select * from t_user where username='${param1}' and password= '${param2}'
        </select>

3.定义一个map参数

当mapper接口的方法有多个参数的时候,可以手动定义一个map参数。(取代mybatis自定义的map)

User checkLoginbyMap(Map<String,Object> map);

在代码里这样去自定义这个map

        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("username","admin");
        map.put("password","123456");
        //调用mapper接口的方法
        User user = userMapper.checkLoginbyMap(map);

在mapper映射文件里就可以直接使用#{username}获取到值了。

<!--    User checkLoginbyMap(Map<String,Object> map);-->
        <select id="checkLoginbyMap"  resultType="user">
<!--       从自定义map集合中根据key获取值-->
           select * from t_user where username=#{username} and password= #{password}
        </select>

4.参数是实体类类型

int insertUser(User user);

什么叫属性,属性和成员变量关系并不大,属性主要是看get和set方法

只需要通过#{}和${}以属性的方式访问属性值即可,注意${}的单引号问题

<!--        int insertUser(User user);-->
        <insert id="insertUser">
<!--        #{属性名}来获取属性值,实际开发用的最多的-->
        insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
        </insert>

5.使用@Param注解命名参数

@Param整合了方法1/2/3。

User checkLoginByparam(@Param("username")String username,@Param("password") String password);

此时mybatis,会有俩种方式封装map

  1. 以@Param注解的值为键,以参数为值
  2. 以param1,param2...为键,以参数为值

    只需要通过#{}和${}以键的方式访问值即可,注意${}的单引号问题

<!--        User checkLoginByparam(@Param("username")String username,@Param("password") String password);-->
        <select id="checkLoginByparam"  resultType="user">
<!--       从自定义map集合中根据key获取值-->
           select * from t_user where username=#{username} and password= #{password}
        </select>

二、mybatis5种重要的查询功能

1.查询一个实体类对象

根据用户id查询用户信息

User getUserById(@Param("id") int id);

2.查询一个list集合

 查询所有用户信息,mapper接口如下:

List<User> getUserList();

mapper映射文件如下,要注意的是,尽管方法的返回值是List集合,但是resultType的值是一个user,不能是List

<select id="getUserList" resultType="com.atguigu.mybatis.pojo.User">
	select * from t_user
</select>

3.查询单个数据

怎么查呢?不分组的聚合函数。mapper接口内容如下:

int getCount();

mapper映射文件内容如下:

<!--int getCount();-->
<select id="getCount" resultType="_integer">
	select count(*) from t_user
</select>

控制台打印如下:

mybatis定义好的类型别名(不区分大小写)

-->右边是左边类型的别名

  •  例如: java.lang.Integer-->int|integer
  •  例如: int-->_int|_integer
  •  例如: Map-->map,List-->list String-->string

4.查询一条数据为map集合

 根据用户id查询用户信息为map集合

Map<String, Object> getUserToMap(@Param("id") int id);

mapper映射文件如下,注意此时的resultType的值是map,用了别名。我们把一行记录封为了一个map

<select id="getUserToMap" resultType="map">
	select * from t_user where id = #{id}
</select>

测试程序如下:

Map<String, Object> map = userMapper.getUserToMap(5);
map.forEach((k,v)->{
    System.out.println(k+" = "+v);
});

运行结果:要注意的是,此种方法只会把结果不为null的给封装到map里


5.查询多条数据为List<map>集合

查询所有用户信息为map集合

方式一:List<Map<String, Object>>

将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取

List<Map<String, Object>> getAllUserToMap();

mapper映射文件中:要注意虽然返回值是List<Map>,但是resultType写的是map

<select id="getAllUserToMap" resultType="map">
    select * from t_user
</select>

遍历list,结果如下:


6.查询多条数据为一个map

@MapKey()

将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的 map集合

mapper接口中:

@MapKey("id")
Map<Integer, Object> getAllUserToMap();

mapper映射文件中:

<select id="getAllUserToMap" resultType="map">
	select * from t_user
</select>

测试程序:

       Map<Integer, Object> map= userMapper.getAllUserToMap();
        map.forEach((k,v)->{
            System.out.println(k+" = "+v);
        });

结果:


三、 特殊的sql,用${}

1.模糊查询

模糊查询的话因为不知道查出来几条,所以用List<User>接收,mapper接口中如下:

    List<User> getUserListByLike( @Param("keywords") String keywords);

mapper映射文件中如下:

    <select id="getUserListByLike" resultType="com.atguigu.mybatis.pojo.User">
    	select * from t_user where username like '%#{keywords}%'
    </select>

like '%#{keywords}%'  会报错:意思是给占位符赋值了,但是找到0个占位符


解决方案1: like '%${keywords}%'  
解决方案2:    like concat('%',#{keywords},'%') 
解决方案3:    like "%"#{keywords}"%" 用的最多,推荐

    <select id="getUserListByLike" resultType="com.atguigu.mybatis.pojo.User">
    	select * from t_user where username like "%"#{keywords}"%"
    </select>

这时候运行结果如下:达到了模糊查询的效果


2.批量删除

mapper接口内容如下

    int deleteUser(@Param("ids") String ids);

 mapper映射文件如下:

    <delete id="deleteUser">
       delete from t_user where id in (#{ids})
    </delete>

运行结果,当然是报错了 ,因为#{}会自动加单引号,就会报错

改成下面这样${ids},就对了,达到了批量删除的效果

    <delete id="deleteUser">
       delete from t_user where id in (${ids}) 
    </delete>


3.动态设置表名

表名作为参数传过去,应用场景:比如普通用户表和vip表;比如表里数据太多时分库分表.mapper接口和mapper映射文件内容分别如下:

   List<User> getAllUser(@Param("tableName") String tableName);
    <select id="getAllUser" resultType="User">
	  select * from #{tableName}
    </select>

#{} 因为会给表名加单引号,会报错不可取,如下:

sql语句中表名一定不能用单引号,则需要修改为${tableName}

    <select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
	  select * from ${tableName}
    </select>  

运行结果:


4.添加功能获取自增的主键

需求:添加班级的时候,顺便为班级分配学生。(所谓分配就是将某学生的班级id修改为新添加的班级的id )

在mapper接口中:

    int insertUser(User user);

在mapper映射文件中:

<insert>中使用useGeneratedKeys和 keyProperty两个属性来获取自动生成的主键值。

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values(null,#{username},#{password},#{age})
    </insert>

useGeneratedKeys:设置使用自增的主键
keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中

运行结果:会把自增后的id放回到参数user对象的id属性中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值