一、获取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。以俩种方式存储
- 以arg0,arg1...为键,以参数为值
- 以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
- 以@Param注解的值为键,以参数为值
- 以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属性中