mybatis_04---映射文件②insert、参数传递(封装)

insert

主键生成方式、获取主键值

主键生成方式:

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]}

参数封装map的过程

以命名参数为例:

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"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值