MyBatis 映射文件 参数处理

本文详细介绍了MyBatis映射文件中参数处理的方法,包括增删改操作、主键生成策略(如MySQL自增和Oracle序列)、多种参数处理方式(如单个参数、多个参数、命名参数、POJO、Map和TO)以及#与$取值的区别。重点讲解了如何在主键生成中使用useGeneratedKeys和selectKey,并提供了示例代码。
摘要由CSDN通过智能技术生成

1、简介

映射文件指导着MyBatis如何进行数据库增删改查,有着非常重要的意义

2、演示 增删改

去com.atguigu.mybatis.dao下面去写增删改查方法(定义好即可)

package com.atguigu.mybatis.dao;

public interface EmployeeMapper {
	
	//多条记录封装一个map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
	//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key
	@MapKey("lastName")
	public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
	
	//返回一条记录的map;key就是列名,值就是对应的值
	public Map<String, Object> getEmpByIdReturnMap(Integer id);
	
	public List<Employee> getEmpsByLastNameLike(String lastName);
	
	public Employee getEmpByMap(Map<String, Object> map);
	
	public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);
	
	public Employee getEmpById(Integer id);

	public Long addEmp(Employee employee);

	public boolean updateEmp(Employee employee);

	public void deleteEmpById(Integer id);
	
}

映射文件中,为上面定义的方法添加内容

工程路径\conf\com\atguigu\mybatis\dao  EmployeeMapper.xml中写增删改

<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">

	<insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee"
		useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
		insert into tbl_employee(last_name,email,gender) 
		values(#{lastName},#{email},#{gender})
	</insert>
	
	
	<!-- public void updateEmp(Employee employee);  -->
	<update id="updateEmp">
		update tbl_employee 
		set last_name=#{lastName},email=#{email},gender=#{gender}
		where id=#{id}
	</update>
	
	<!-- public void deleteEmpById(Integer id); -->
	<delete id="deleteEmpById">
		delete from tbl_employee where id=#{id}
	</delete>
	
	
</mapper>

进入测试类 test03, 测试增删改

(1)mybatis允许增删改直接定义以下类型返回值
     *         Integer、Long、Boolean、void、void
(2)我们需要手动提交数据
     *         sqlSessionFactory.openSession();===》手动提交
     *         sqlSessionFactory.openSession(true);===》自动提交

将下面的注解部分一个一个打开,即可完成测试

package com.atguigu.mybatis.test;

public class MyBatisTest {
	@Test
	public void test03() throws IOException{
		
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		//1、获取到的SqlSession不会自动提交数据
		SqlSession openSession = sqlSessionFactory.openSession();
		
		try{
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			//测试添加
			Employee employee = new Employee(null, "jerry4",null, "1");
			mapper.addEmp(employee);
			System.out.println(employee.getId());
			
			//测试修改
			//Employee employee = new Employee(1, "Tom", "jerry@atguigu.com", "0");
			//boolean updateEmp = mapper.updateEmp(employee);
			//System.out.println(updateEmp);
			//测试删除
			//mapper.deleteEmpById(2);
			//2、手动提交数据
			openSession.commit();
		}finally{
			openSession.close();
		}
		
	}
}

最终效果:

3、主键生成方式

3.1 mysql自增方式(自动生成主键)

    若数据库支持自动生成主键的字段(比如MySQL 和SQL Server),则可以设置useGeneratedKeys=”true”,然后再把keyProperty设置到目标属性上。mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();

     useGeneratedKeys="true";使用自增主键获取主键值策略
     keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性

<!-- public void addEmp(Employee employee); -->
	<!-- parameterType:参数类型,可以省略, 
	获取自增主键的值:
		mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
		useGeneratedKeys="true";使用自增主键获取主键值策略
		keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
	-->
	<insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee"
		useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
		insert into tbl_employee(last_name,email,gender) 
		values(#{lastName},#{email},#{gender})
	</insert>

测试类中测试效果

package com.atguigu.mybatis.test;

public class MyBatisTest {
	@Test
	public void test03() throws IOException{
		
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		//1、获取到的SqlSession不会自动提交数据
		SqlSession openSession = sqlSessionFactory.openSession();
		
		try{
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			//测试添加
			Employee employee = new Employee(null, "jerry4",null, "1");
			mapper.addEmp(employee);
			System.out.println(employee.getId());
			
			//2、手动提交数据
			openSession.commit();
		}finally{
			openSession.close();
		}
		
	}
}

由于开启了自增主键,因此,就算new Employee(null, "jerry4",null, "1");,那个id值就算你写了null,也没得用,也会自增。如果没有开启自增,id值就是null

 

3.2 Orcal获取主键方式(非自增型数据库)

而对于不支持自增型主键的数据库(例如Oracle),Oracle使用序列来模拟自增;每次插入的数据的主键是从序列中拿到的值;重点是如何获取到这个值;

则可以使用selectKey子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用

说明:keyProperty属性的“id”,就是后面sql语句中#{id}用的id

keyProperty:查出的主键值封装给javaBean的哪个属性
        order="BEFORE":当前sql在插入sql之前运行
               AFTER:当前sql在插入sql之后运行
        resultType:查出的数据的返回值类型
        
        BEFORE运行顺序:
            先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
            在运行插入的sql;就可以取出id属性对应的值
        AFTER运行顺序:
            先运行插入的sql(从序列中取出新值作为id);
            再运行selectKey查询id的sql;

演示1:两种方式

id就是查询主键sql语句的返回值别名

进入映射文件(Before和Afer都写了,用Afer多的时候注掉Before)

<insert id="addEmp" databaseId="oracle">
		<!-- 
		keyProperty:查出的主键值封装给javaBean的哪个属性
		order="BEFORE":当前sql在插入sql之前运行
			   AFTER:当前sql在插入sql之后运行
		resultType:查出的数据的返回值类型
		
		BEFORE运行顺序:
			先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
			在运行插入的sql;就可以取出id属性对应的值
		AFTER运行顺序:
			先运行插入的sql(从序列中取出新值作为id);
			再运行selectKey查询id的sql;
		 -->
		<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
			<!-- 编写查询主键的sql语句 -->
			<!-- BEFORE-->
			select EMPLOYEES_SEQ.nextval from dual 
			<!-- AFTER:
			 select EMPLOYEES_SEQ.currval from dual -->
		</selectKey>
		
		<!-- 插入时的主键是从序列中拿到的 -->
		<!-- BEFORE:-->
		insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
		values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) 
		<!-- AFTER:
		insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
		values(employees_seq.nextval,#{lastName},#{email}) -->
</insert>

测试文件中 id为null,测试前,记得取全局配置文件把 环境标签改成<environments default="dev_oracle"

代码和上例一样,

没给id(id写null),也能获取到主键224

4、MyBatis参数处理(数据库操作方法的入参)

(1)单个参数

可以接受基本类型,对象类型,集合类型的值。这种情况MyBatis可直接使用这个参数,不需要经过任何处理。可直接取值

取值方法:

#{参数名}:取出参数值

(2)多个参数
任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,0,1…,值就是参数的值。

Key:param1...paramN

value:传入的参数值

取值方法:

#{}:就是从map中指定的key取值(param1...paramN)

注意:如果还是用单个参数的方式取值,比如:

方法: public Employee getEmpByIdAndLastName (Integer id,string lastName)//该方法两个参数

取值还是依然:#{id),#{1astName},此时就会报异常

异常:org. apache.ibatis.binding. BindingException: Parameter 'id' not found.Available parameters are [1, e, param1, param2]

(3)命名参数:

     如果不使用命名参数,默认map,key都是param1,param2,根本不认识想表达哪个值。

     因此,我们可以为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是我们自己指定的名字

比如,通过明确指定封装参数时map的key; @Param ("id")多个参数会被封装成一个map,

key:使用@Param注解指定的值

value:参数值

取值方法:

#{指定的key}:取出对应的参数值

exp(命名参数):

package com.atguigu.mybatis.dao;


public interface EmployeeMapper {
	
	public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);
	
}

映射配置文件:

即可用id,lastName完成取值

<select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from tbl_employee where id = #{id} and last_name=#{lastName}
</select>

(4)POJO(真正常用且简单快捷)

 如果多个参数正好是我们业务逻辑的数据模型(就是bean中对应的属性),我们就可以直接传入pojo

#{属性名}:取出传入的pojo的属性值

(5)传入Map,(本身就是传入Map,不如我自己传)  

Map:如果多个参数不是业务模型中的数据,没有对应的pojo,为了方便,我们也可以传入map#{key}:取出map中对应的值

说明:不经常使用的数据,比如只用一次的情况,就封装进Map

包com.atguigu.mybatis.dao  的EmployeeMapper接口中

package com.atguigu.mybatis.dao;

public interface EmployeeMapper {
	
	
	public Employee getEmpByMap(Map<String, Object> map);
}

映射配置文件中

getEmpByMap(Map<String,Object> map)

<!-- public Employee getEmpByMap(Map<String, Object> map); -->
 	<select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from ${tableName} where id=${id} and last_name=#{lastName}
 	</select>

进入测试文件,进行测试

package com.atguigu.mybatis.test;

public class MyBatisTest {    
    @Test
	public void test04() throws IOException{
		
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		//1、获取到的SqlSession不会自动提交数据
		SqlSession openSession = sqlSessionFactory.openSession();
		
		try{
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			//Employee employee = mapper.getEmpByIdAndLastName(1, "tom");
			Map<String, Object> map = new HashMap<>();
			map.put("id", 2);
			map.put("lastName", "Tom");
			map.put("tableName", "tbl_employee");
			Employee employee = mapper.getEmpByMap(map);
			
			System.out.println(employee);
			
			/*List<Employee> like = mapper.getEmpsByLastNameLike("%e%");
			for (Employee employee : like) {
				System.out.println(employee);
			}*/
			
			/*Map<String, Object> map = mapper.getEmpByIdReturnMap(1);
			System.out.println(map);*/
			/*Map<String, Employee> map = mapper.getEmpByLastNameLikeReturnMap("%r%");
			System.out.println(map);*/
			
		}finally{
			openSession.close();
		}
	}
}

(6)TO(Transfer Object)

如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO (Transfer object)数据传输对象

Page{

 int index;

int size;}

总结:

(1)public Employee getEmp (@Param("id")Integer id,string lastName);

取值: id==>#{id/param1}    lastName==>#{param2}

(2)public Employee getEmp (Integer id,@Param ("e")Employee emp);

取值: id==>#{param1)    lastName===>#{param2. lastName/e.lastName)

(3)##特别注意:如果是Collection (List. Set)类型或者是数组也会特殊处理。也是把传入的list或者数组封装在map中

key: Collection (collection) ,如果是List还可以使用这个key(即list),数组使用array

public Employee getEmpById(List<Integer> ids)

取值:取出第一个id的值: #{list [0]}

5、参数处理   

5.1 #与$取值的区别

#{}:可以获取map中的值或者pojo对象属性的值

${}:可以获取map中的值或者pojo对象属性的值

             select * from tbl_employee where id=${id} and last_name=#{lastName)

相当于: select * from tbl_employee where id=2 and last_name=?(占位符)

区别:

#{}:是以预编译的形式,将参数设置到sql语句中; Preparedstatement;防止sql注入(因此常用)

${}:取出的值直接拼装在sql语句中;会有安全问题;

总结:

① 大多情况下,我们去参数的值都应该去使用#{},

② 但是当使用原生jdbc,不支持占位符的地方我们就可以使用$进行取值比如分表;

比如分表、排序。。。;按照年份分表拆分

select * from $(year}_salary where xxx;

select * from tbl_employee order by ${f_name} $(order)

5.2 #{}进阶使用

#{}:更丰富的用法:规定参数的一些规则:

javaType. jdbcType, mode (存储过程) 、numericScale.resultMap, typeHandler. jdbcTypeName, expression (未来准备支持的功能) ;

Exp:jdbcType规定 演示

jdbcType通常需要在某种特定的条件下被设置:在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle (报错) ;

说明:mybatis默认对所有null值的处理,都是映射为原生Jdbc的OTHER类型(源码jdbcTypeForNull=OTHER),Mysql认识OTHER类型,但是Oracle不认识,要手动让OTHER类型转为NULL

两种解决办法

办法一:映射文件sql语句的Email字段加入参数限制规则

去全局配置文件mybatis.xml,将environments标签的default属性切换成oracle

<environments default="dev_mysql">

然后,在测试文件中,对email字段写入null值,oracle就会报错(JdbcType OTHER无效类型异常)

Employee employee= new Employee(null,"jerry3",null,"1");

解决办法,制定参数规则。在映射文件EmployeeMapper.xml的sql语句中写上 #{email ,jdbcType=NULL },规定当email为空时,指定email的jdbcType是NULL值

<insert id="addEmp" databaseId="oracle">
        insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
        values(#{id},#{lastName},#{email ,jdbcType=NULL }) 
        <!-- AFTER:
        insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
        values(employees_seq.nextval,#{lastName},#{email}) -->
    </insert>

办法二:将全局配置文件中的jdbcTypeForNull=OTHER 改为jdbcTypeForNull=NULL

<settings>
		<setting name="jdbcTypeForNull" value="NULL"/>
</settings>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值