赞
踩
主键生成方式:
1、支持主键自增的mysql数据库
2、不支持主键自增的mysql数据库
获取主键值
1、若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。
useGenreatedKeys=“true”:使用自增主键获取主键值策略
keyProperty:指定对应的主键属性,也就是mybatis获取到主键值后,将这个值封装给javaBean的哪个属性
2、而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素: selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用
selectKey属性:
KeyProperty:查处的主键值封装给javaBean的哪个属性
resultType:查处数据的返回值类型
order:
BEFORE:当前sql语句在插入sql语句之前运行
运行顺序:
先运行selectKey查询的sql语句,查处的id值封装给javaBean的id属性
再运行插入的sql语句,取出id属性的值
AFTER:当前sql语句在插入sql语句运行之后运行
运行顺序:
先运行插入的sql语句(从序列中取出新值作为id)
在运行查询当前的id值的sql语句,查询的id值封装给javaBean的id属性
<insert id="insertEmployee"
parameterType="dao.Employee" databaseId="oracle">
<selectKey order="BEFORE" keyProperty="id"
resultType="integer"> select employee_seq.nextval from dual
</selectKey>
<insert id="insertEmployee"
parameterType="dao.Employee" databaseId="oracle">
<selectKey order="AFTER" keyProperty="id"
resultType="integer"> select employee_seq.currval from dual
</selectKey>
insert into orcl_employee(id,last_name,email,gender) values(employee_seq.nextval,#{lastName},#{email},#{gender})
</insert>
推荐使用BEFORE属性,当插入多条数据时,AFTER只能获取最后一个的序列
1、单个参数:
可以接受基本类型,对象类型。这种情况 MyBatis 可直接使用这个参数,不需要经过任何处理。
select * from tb_employee where id=#{id}
2、多个参数;
mybatis会做特殊处理,多个参数会被封装成一个map
key:param1...paramN,或者参数的索引
value:传入的参数值
#{}就是从map中获取指定key的值
select * from tb_employee where id=#{param1} and name=#{param2}
3、命名参数:
明确指定封装参数时map的key:@param("id")
多个参数会被封装成一个map
key:使用@param注解指定的值
value:参数值
#{指定的key}取出对应的参数值
public Employee getEmpByIdAndName(@param("id")integer id,@param("name")name)
select * from tb_employee where id=#{id} and name=#{name}
4、POJO
如果多个参数正好是业务逻辑的数据模型,可以直接传入pojo
#{属性名}:取出传入的pojo的属性值
5、Map
如果多个参数不是业务模型重的数据,没有对应pojo,不经常使用为了方便,可以直接传入map #{key} public Employee getEmpByMap(Map<String,Object> map); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String,Object> map = new HashMap<>(); map.put("id",1); map.put("name","tom"); Employee employee = mapper.getEmpByMap(map); System.out.println(employee); }finally{ openSession.close(); } <select id="getEmpByMap" resultType="dao.Employee"> select * from tb_employee where id=#{id} and name=#{name} </select>
6、TO
如果多个参数不是业务模型中的数据,但是经常使用,推荐编写一个TO(Transfer Object)的数据传输对象
Page{
int index;
int size;
}
例:
public Employee getEmp(@Param("id")integer id,String name);
id==>#{id/param1} name==>#{param2}
public Employee getEmp(integer id,Employee emp);
id==>#{param1} name==>#{param2.name}
注意:如果是Collection(List、Set)类型或者是数组,也会特殊处理
把传入的List或者数组封装在Map中
key:Collection(collection),
如果是List还可以使用key(list)
如果是数组还可以使用(array)
public Employee getEmpById(List<Integer> ids);
取值:取出第一个id的值#{list[0]}
以命名参数为例:
public Employee getEmployeeByIdAndLastName (@Param("id")Integer id, @Param("lastName")String lastName);
源码:
ParamNameResolve解析参数封装map
<!-- 1、name:{0=id,1=lastName} name的赋值在构造器的时候就确定好了。ParamNameResolve方法中给name赋值 确定流程: 1、获取每个标了param注解的参数的@Param的值,id、lastName:赋值给name; 2、每次解析一个参数给map中保存信息,(key:参数索引,value:name的值) name的值: 标注了param注解,注解的值 没有标注: 1、全局配置:useActualParamName,name=参数名 2、name=mao.size():相当于当前参数的索引 {0=id,1=lastName,2=2}//若有第三个参数值 --> //args【1,"tom","hello"】 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; //4、遍历name集合:{0=id,1=lastName,2=2} for (Map.Entry<Integer, String> entry : names.entrySet()) { //name集合的value作为map的key,name集合的key作为取值的参考索引:args[0]:args[1,"tom"] //eg:{id=args[0]:1,lastName=args[1]:tom,2=args[2]:hello} param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) //额外的将每一个惨回溯也保存到map中,使用新的key:param1...paramN //效果:有Param注解可以#{指定key},或者#{param1} 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; } }
总结:参数多时会封装map,为了不混乱,可以使用@Param来指定封装时使用的key:#{key}就可以取出map中对应的值
#{}、${}:都是可以获取map中的值或者POJO对象属性的值
区别:
#{}:是以预编译的形式,将参数设置到sql语句中,PreparedStatement;防止sql注入
${}:取出得知直接拼接在sql语句中;会有安全问题
大多数情况下,取参数的值都使用#{}
原生sql不支持占位符的地方就可以使用${}进行取值
如分表:按照年份分表拆分
select * from ${year}_salary where ×××;
select * from ${tableName} where id=#{id} and name=#{name};
javaType、jdbcType、mode(存储过程)、numericScale、resultMap、typeHandler、jdbcTypeName、 expression
jdbcType通常需要在某种特定的条件下被设置:
在数据为null时,有些数据库可能不能识别mybatis对null的默认处理方式。如Oracle数据库(报错)
JdbcType OTHER:无效类型。这是因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,Oracle不能正确处理
由于全局配置中,jdbcTypeForNull=OTHER,oracle不支持,两种方法如下:
1、#{email,jdbcType=NULL}(映射文件)
2、jdbcTypeForNull=NULL(全局配置)
<setting name="jdbcTypeForNull" value="NULL"/>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。