第二章Mybatis的SQL映射文件和ResultMap
2018-01-25 21:49
489 查看
一、SQL映射文件
1.CRUD
Mybatis允许定义以下类型的返回值:Integer、Long、Boolean、void
//mybatis引入将Integer、Long、Boolean、void作为方法的返回值
public Integer updateEmployee(Employee employee);
2.返回值类型
①:返回 List集合对象类型,只需要指定返回值类型为集合中泛型的类型即可
<!-- public List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.nengjie.mybatis.bean.Employee"
select * from tbl_employee
</select>
②:查询单条记录封装为Map,此时,返回值类型只需要使用 Map类型即可;
<!-- public Map<String, Employee> selectEmployeeMapById(Integer id); -->
<select id="selectEmployeeMapById" resultType="map"
select * from tbl_employee where id = #{id}
</select>
③:查询多条记录封装为Map,如我们返回Map<String,Employee>类型的Map,使用 resultType指定value的类型;
使用@MapKey注解来指定POJO的哪个属性作为key
@MapKey("id")
public Map<String, Employee> selectEmployeeMapById(Integer id);
<select id="selectEmployeeMapById" resultType="map">
select * from tbl_employee where id > #{id}
</select>
3.获取自增主键的值:
mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
(JDBC中使用 Statement的getGeneratedKeys()方法来获取自增主键)
useGeneratedKeys="true";使用自增主键获取主键值策略
keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
<!-- public void addEmployee(Employee employee); -->
<insert id="addEmployee" useGeneratedKeys="true" keyProperty="id">
insert
into tbl_employee(last_name,gender,email) values(#{lastName},#{gender},#{email})
</insert>
4.获取非自增主键的值:
Oracle不支持自增;Oracle使用序列来模拟自增;
每次插入的数据的主键是从序列中拿到的值;
5.参数处理:
单个参数:当传入单个参数时,mybatis不会做特殊的处理因为只有一个参数,此时对参数名不会进行严格的检查:
#{参数名/任意名}:取出参数值。
return args[names.firstKey()];
多个参数:mybatis会做特殊处理。多个参数会被封装成
一个map
key:param1...paramN,或者参数的索引0,1......也可以
value:传入的参数值
#{}就是从map中获取指定的key的值;
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name = #{param1} and id = #{param2}
</select>
异常:
org.apache.ibatis.binding.BindingException:
Parameter 'id' not found.
Available parameters are [1, 0, param1, param2]
解决方法:使用#{index}或者#{paramN}
缺点:当有多个参数时,可读性差
为了解决上述问题,使用【命名参数】:明确指定封装参数时map的key;@Param("id")
多个参数会被封装成 一个map,
key:使用@Param注解指定的值
value:参数值
#{指定的key}取出对应的参数值
public Employee selectEmployeeByNameAndId(@Param("lastName")String name, @Param("id")Integer id);
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee
where last_name = #{last_name} and id = #{id}
</select>
mybatis的对参数的处理的源码分析:
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
//1、参数为null直接返回
if (args == null || paramCount == 0) {
return null;
//2、如果只有一个元素,并且没有Param注解;args[0]:单个参数直接返回
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
//3、多个元素或者有Param标注
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
10cd3
//4、遍历names集合;{0=id, 1=lastName,2=2}
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//names集合的value作为key; names集合的key又作为取值的参考args[0]:args【1,"Tom"】:
//eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]}
param.put(entry.getValue(), args[entry.getKey()]);
//额外的将每一个参数也保存到map中,使用新的key:param1...paramN
//效果:有Param注解可以#{指定的key},或者#{param1}
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
}
POJO:
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
#{属性名}:取出传入的pojo的属性值
public Employee selectEmployeeByNameAndId(Employee employee);
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name = #{lastName} and id = #{id}
</select>
测试方法:
Employee employee = new Employee(2, "Jack1", null, null);
employee = mapper.selectEmployeeByNameAndId(employee);
Map:
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
#{key}:取出map中对应的值
public Employee
getEmployeeByMap(Map<String, Object> map);
<select id="getEmployeeByMap" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name
= #{lastName} and id = #{id}
</select>
Map<String, Object> map = new HashMap<String,
Object>();
map.put("lastName", "Jack1");
map.put("id", 2);
Employee employee = mapper.getEmployeeByMap(map);
TO:
如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象
Page{
int index;
int size;
}
Collection:
当需要从 Collection 中获取参数时,可以使用 #{collection[index]}来获取指定 index位置的参数值
注意:
如果是 List 集合,还可以使用 #{list[index]}来获取指定 index位置的参数值
如果是数组类型,可以使用 #{array[index]} 来获取指定 index位置的参数值
public Employee getEmployeeByList(Collection<String> name);
<select id="getEmployeeByList" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee
where last_name = #{collection[0]}
</select>
List<String> name = new ArrayList<String>();
name.add("jack1");
Employee employee = mapper.getEmployeeByList(name);
#{}与${}
相同点:都可以获取map中的值或者pojo对象属性的值;
区别:
#{}:是以预编译的形式,使用PreparedStatement将参数设置到sql语句中,可以防止sql注入
${}:取出的值直接拼装在sql语句中,会有sql注入的安全问题;
大多情况下,我们取参数的值都应该去使用#{};
${}的使用场景:
原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序。。。;按照年份分表拆分
#{}对null值的处使用 PageInfo 对结果进行封装理:我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);使用 PageInfo 对结果进行封装
二、ResultMap
1.CRUD
Mybatis允许定义以下类型的返回值:Integer、Long、Boolean、void
//mybatis引入将Integer、Long、Boolean、void作为方法的返回值
public Integer updateEmployee(Employee employee);
2.返回值类型
①:返回 List集合对象类型,只需要指定返回值类型为集合中泛型的类型即可
<!-- public List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.nengjie.mybatis.bean.Employee"
select * from tbl_employee
</select>
②:查询单条记录封装为Map,此时,返回值类型只需要使用 Map类型即可;
<!-- public Map<String, Employee> selectEmployeeMapById(Integer id); -->
<select id="selectEmployeeMapById" resultType="map"
select * from tbl_employee where id = #{id}
</select>
③:查询多条记录封装为Map,如我们返回Map<String,Employee>类型的Map,使用 resultType指定value的类型;
使用@MapKey注解来指定POJO的哪个属性作为key
@MapKey("id")
public Map<String, Employee> selectEmployeeMapById(Integer id);
<select id="selectEmployeeMapById" resultType="map">
select * from tbl_employee where id > #{id}
</select>
3.获取自增主键的值:
mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
(JDBC中使用 Statement的getGeneratedKeys()方法来获取自增主键)
useGeneratedKeys="true";使用自增主键获取主键值策略
keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
<!-- public void addEmployee(Employee employee); -->
<insert id="addEmployee" useGeneratedKeys="true" keyProperty="id">
insert
into tbl_employee(last_name,gender,email) values(#{lastName},#{gender},#{email})
</insert>
4.获取非自增主键的值:
Oracle不支持自增;Oracle使用序列来模拟自增;
每次插入的数据的主键是从序列中拿到的值;
5.参数处理:
单个参数:当传入单个参数时,mybatis不会做特殊的处理因为只有一个参数,此时对参数名不会进行严格的检查:
#{参数名/任意名}:取出参数值。
return args[names.firstKey()];
多个参数:mybatis会做特殊处理。多个参数会被封装成
一个map
key:param1...paramN,或者参数的索引0,1......也可以
value:传入的参数值
#{}就是从map中获取指定的key的值;
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name = #{param1} and id = #{param2}
</select>
异常:
org.apache.ibatis.binding.BindingException:
Parameter 'id' not found.
Available parameters are [1, 0, param1, param2]
解决方法:使用#{index}或者#{paramN}
缺点:当有多个参数时,可读性差
为了解决上述问题,使用【命名参数】:明确指定封装参数时map的key;@Param("id")
多个参数会被封装成 一个map,
key:使用@Param注解指定的值
value:参数值
#{指定的key}取出对应的参数值
public Employee selectEmployeeByNameAndId(@Param("lastName")String name, @Param("id")Integer id);
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee
where last_name = #{last_name} and id = #{id}
</select>
mybatis的对参数的处理的源码分析:
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
//1、参数为null直接返回
if (args == null || paramCount == 0) {
return null;
//2、如果只有一个元素,并且没有Param注解;args[0]:单个参数直接返回
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
//3、多个元素或者有Param标注
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
10cd3
//4、遍历names集合;{0=id, 1=lastName,2=2}
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//names集合的value作为key; names集合的key又作为取值的参考args[0]:args【1,"Tom"】:
//eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]}
param.put(entry.getValue(), args[entry.getKey()]);
//额外的将每一个参数也保存到map中,使用新的key:param1...paramN
//效果:有Param注解可以#{指定的key},或者#{param1}
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
}
POJO:
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
#{属性名}:取出传入的pojo的属性值
public Employee selectEmployeeByNameAndId(Employee employee);
<select id="selectEmployeeByNameAndId" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name = #{lastName} and id = #{id}
</select>
测试方法:
Employee employee = new Employee(2, "Jack1", null, null);
employee = mapper.selectEmployeeByNameAndId(employee);
Map:
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
#{key}:取出map中对应的值
public Employee
getEmployeeByMap(Map<String, Object> map);
<select id="getEmployeeByMap" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee where last_name
= #{lastName} and id = #{id}
</select>
Map<String, Object> map = new HashMap<String,
Object>();
map.put("lastName", "Jack1");
map.put("id", 2);
Employee employee = mapper.getEmployeeByMap(map);
TO:
如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象
Page{
int index;
int size;
}
Collection:
当需要从 Collection 中获取参数时,可以使用 #{collection[index]}来获取指定 index位置的参数值
注意:
如果是 List 集合,还可以使用 #{list[index]}来获取指定 index位置的参数值
如果是数组类型,可以使用 #{array[index]} 来获取指定 index位置的参数值
public Employee getEmployeeByList(Collection<String> name);
<select id="getEmployeeByList" resultType="com.nengjie.mybatis.bean.Employee">
select * from tbl_employee
where last_name = #{collection[0]}
</select>
List<String> name = new ArrayList<String>();
name.add("jack1");
Employee employee = mapper.getEmployeeByList(name);
#{}与${}
相同点:都可以获取map中的值或者pojo对象属性的值;
区别:
#{}:是以预编译的形式,使用PreparedStatement将参数设置到sql语句中,可以防止sql注入
${}:取出的值直接拼装在sql语句中,会有sql注入的安全问题;
大多情况下,我们取参数的值都应该去使用#{};
${}的使用场景:
原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序。。。;按照年份分表拆分
#{}对null值的处使用 PageInfo 对结果进行封装理:我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);使用 PageInfo 对结果进行封装
二、ResultMap
相关文章推荐
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- mybatis学习(二)SQL语句映射文件resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习(二) - SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习-SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件-resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- mybatis 学习二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件 resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap