目录
2、动态SQL标签if、choose、where、set、foreach
2.3 choose标签:分支选择(多选一,遇到成立的条件即停止)
2.7 set标签:update语句中,添加set关键字,会将动态sql最后多余的逗号去除
2.9 foreach标签:遍历集合或者数组,拼接成字符串用于sql中in关键字
一、MyBatis参数
SqlSessiong工具类
public class SessionFactoryUtils {
//声明一个工厂对象
private static SqlSessionFactory factory;
//在静态代码块中创建会话工厂
static {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//得到输入流
try(InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
factory = builder.build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
静态方法得到会话工厂
*/
public static SqlSessionFactory getSessionFactory() {
return factory;
}
/**
得到会话对象
*/
public static SqlSession getSession() {
return factory.openSession();//使用的是默认事务:手动提交
}
}
1、映射文件配置-入参
1.1 parameterType入参
CRUD标签都有属性parameterType,底层的statement通过它指定接收的参数类型。入参数据有以下几种类型:HashMap,基本数据类型(包装类),实体类;
在mybatis中入参的数据类型分为2大类:
-
基本数据类型:int,string,long,Date等;
-
复杂数据类型:类(pojo)和Map;
说明:如果传递参数是数组或者集合,底层都会封装到Map集合中。
1.2 单个入参,变量名任意定义:
mapper.java
根据id查询用户信息,入参是单个参数:用户id
User queryById(Integer id); //接口方法传入一个参数
mapper.xml配置:
<!--根据id查询用户信息-->
<!--返回值类型User,入参类型int,单个入参#{变量随便写}-->
<select id="queryById" resultType="User" parameterType="int">
select * from user where id = #{ii}
</select>
在xml中通过#{ 任意变量名}可接收到参数,若接口传入单个参数,可在xml中使用任意变量名接收。
1.3 多个入参,解决方案:
mapper.java
多个入参,根据用户名和性别查询用户信息
User queryByNameAndSex(String name ,String sex);
错误演示:
<!--返回值类型User,未定义入参类型-->
<select id="queryByNameAndSex" resultType="User">
select * from user where name = #{name} and sex = #{sex}
</select>
报参数绑定异常!
需使用参数索引(arg0,arg1)、参数位置(param1,param2)、或在接口处明确指定传入参数名。
方式1:使用参数索引获取:arg0,arg1 (了解即可)
<select id="queryByNameAndSex" resultType="user">
select * from user where user_name=#{arg0} and sex=#{arg1}
</select>
方式2:使用参数位置获取:param1,param2 (了解即可)
<select id="queryByNameAndSex" resultType="user">
select * from user where user_name=#{param1} and sex=#{param2}
</select>
掌握:命名参数获取,在接口处明确指定传入参数名称。
mapper.java接口
List<User> queryByNameAndSex(@Param("name") String name,@Param("sex") String sex);
mapper.xml,变量名与接口中明确的@Param("name")参数名相同,接收参数时通过指定的名称获取参数值。
<!--根据用户名和性别查询用户信息-->
<select id="queryByNameAndSex" resultType="User">
select * from user where user_name = #{name} and sex = #{sex}
</select>
1.4 pojo类入参:
mapper.java接口
保存用户,pojo对象作为入参
int saveUser (User user);
mapper.xml,#{变量},变量名与User类中属性名对应
<!--#{变量},变量名为User类中属性名,要一一对应-->
<insert id="saveUser">
insert into user values (null ,#{username},#{birthday},#{sex},#{address})
</insert>
1.5 Map入参:
mapper.java接口
以map为参数插入用户信息
int saveUser2 (Map map);
SqlSession sqlSession = SessionFactoryUtils.getSession();
//获取接口代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("username","鞋垫老板");
map.put("sex","男");
map.put("address","鞋店");
mapper.saveUser2(map);
sqlSession.commit();
sqlSession.close();
mapper.xml
<!--#{变量},变量名与Map中key一一对应-->
<insert id="saveUser2" parameterType="map">
insert into user values (null ,#{username},null,#{sex},#{address})
</insert>
1.6 自增主键回填
1)使用insert标签的子标签selectKey+last_insert_id()函数实现实现
<!-- selectKey:表示查询主键字段的标签
keyColumn:表示表中字段名称,一般指主键名称
keyProperty="id":表示pojo类中对应主键的属性名称
order="AFTER":表示在操作之前或者之后获取主键值-->
<insert id="addUserAndGetFkId">
insert into user values(null,#{username},#{birthday},#{sex},#{address})
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
2)使用insert标签的属性useGeneratedKeys,keyProperty,keyColumn实现
说明:直接在insert标签中增加属性的方式,只适合于支持自动增长主键类型的数据库。
<!--useGeneratedKeys="true"表示开启获取主键id的功能
keyColumn="id":表示指定表中主键字段名称
keyProperty="id":表示指定pojo类中主键对应的属性名称-->
<insert id="addUserAndGetFkId2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into user values(null,#{username},#{birthday},#{sex},#{address})
</insert>
2、参数值的获取
2.1 获取参数的方式
在mybatis中获取传入参数值的方式有两种:#{} 和 ${}
#{}: 使用#{}的sql是进行预编译的,防止sql注入。
${}:参数与sql直接拼接,有sql注入的风险。${id} 获取id值时,接口必须使用命名参数取值@param,若取单个值,也可使用${value}获取。
mapper.java接口
User findById2(@Param("id") Integer id);
mapper.xml
<select id="findById2" resultType="user" parameterType="int">
select * from user where id=${id}
</select>
2.2 ${}取值的应用场景
如果需要设置到SQL中的不是查询的条件,只能使用${}拼接;
SELECT COUNT(*) FROM ${tableName}
例:传入参数:没有指定参数名称
User selectUserById(Integer id);
获取参数通过${value}获取
<select id="selectUserById" resultType="user">
select * from user where id = ${value}
</select>
3、结果集映射
mybatis框架提供了resultType和resultMap来对结果集进行封装; 只要一个方法有返回值需要处理,那么 resultType和resultMap必须有一个;
3.1 简单结果映射resultType
从sql语句中返回的期望类型的类的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。 可以使用 resultType 或 resultMap,但不能同时使用。
① 返回值是基本类型
1)基本类型 int short double ... 别名: _基本类型名称
2)包装类 类 String ArrayList .... 别名: 类名首字母小写
3)自定义类 扫包取别名 类首字母小写(大写也可以)
② 返回值为一个pojo(User)对象时
1)表中列明要与pojo中属性名称一致
2)若表中列名与pojo中属性名称不一致,可使用as取别名使其一致即可
3)如果满足驼峰映射,也可以开启驼峰映射设置
③返回值为一个List<User>时
当返回值为List集合时,resultType需要设置成集合中存储的具体的pojo数据类型
3.2 resultType测例
1)返回一条数据,封装到map中
接口:
Map<String,Object> findMapById(@Param("id") Integer id);
xml:
<select id="findMapById" resultType="map">
select id,user_name as userName,address from user where id=#{id}
</select>
2)返回多条数据,封装到map中
获取所有用户,value为user对象:@MapKey("id"),指定key为id值
接口:
@MapKey("id")
Map<Integer,User> findAllToMap();
xml:
<select id="findAllToMap" resultType="map">
select id,user_name as name,birthday,sex,address from user
</select>
3.3 结果映射resultMap
正常开发中,数据库字段名称与Pojo类属性名称不一致时,一般通过驼峰映射或者AS关键字取别名可以搞定,但是对于复杂的orm映射,上述的2种方式就不能适用了。
resultMap是mybatis中最重要最强大的元素,使用ResultMap可以解决ORM复杂映射问题: 1. POJO属性名和表结构字段名不一致的问题(字段名:user_name,属性名:name) 2. 完成高级查询,比如说,一对一、一对多、多对多
3.3 resultMap测例
之前使用驼峰匹配,方便封装用户。现取消驼峰映射,使用ResultMap。
<settings>
<!--作用:表:user_name 类:userName/username 自动映射-->
<!--关闭驼峰映射,测试resultMap-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>
resultMap标签自定义结果集,自行设置结果集的封装方式。
id属性:resultMap标签的唯一标识,不能重复,一般是用来被引用的
type属性:结果集的封装类型
autoMapping属性:操作单表时,不配置默认为true,如果pojo对象中的属性名称和表中字段名称相同,则自动映射。
<!--type="user" 表示结果集的封装类型是user-->
<resultMap id="userMap" type="User" autoMapping="true">
<!--配置主键映射关系-->
<id column="id" property="id"></id>
<!--配置用户名的映射关系 column 表示数据表列 property表示pojo的属性-->
<result column="user_name" property="username"></result>
</resultMap>
<select id="findUserById" resultMap="userMap">
select id,user_name from user where id = #{id}
</select>
SqlSession sqlSession = SessionFactoryUtils.getSession();
//获取接口代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用方法根据id查询单个数据
User user = mapper.findUserById(2);
System.out.println("user = " + user);
sqlSession.close();
注意:若xml中sql只查询数据库部分字段,需在pojo