编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
Maven版本:apache-maven-3.6.3
Mybatis版本:3.5.6
目录
一. Mybatis中参数传递问题
1.1 单个普通参数传递
对于单个普通参数而言,只要它的数据类型是Java基本数据类型,包装类型,字符串类型等。请放心大胆的使用它去传递,因为MyBatis可直接使用这个参数,不需要经过任何处理。且不受参数名称约束,即你可以任意命名,但一般遵循见名知意的原则。
示例代码如下:
<select id="selectUsers" resultType="User">
select id, username, password
from users
where id = #{id}
</select>
在上述代码中,"#{id}"中的id可以任意取名,并且在程序中传给id的参数,其数据类型只要是符合(Java基本数据类型,包装类型,字符串类型)其中之一,MyBatis可直接使用这个参数传入到sql语句中。
1.2 多个普通参数传递
对于任意多个参数而言,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,或arg0,arg1。相应的value是参数的值。
用法案例:根据员工姓名与薪资在数据库中查找相应的员工信息
①先在Mapper接口定义根据员工姓名与薪资查找相应的员工信息的方法
代码示例如下:
//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(String lastName,double salary);
②在映射文件中定义相关的sql
<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
where last_name=#{param1}
and
salary=#{param2}
</select>
③测试
@Test
public void test2(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.selectEmployeeByNameandSalary("李四", 9000);
System.out.println(employee);
} catch (IOException e) {
e.printStackTrace();
}
}
1.3 命名参数
语法:
@Param(value="参数名")
@Param("参数名")
位置:
在XXXMapper接口中方法的形参前面声明
注意:
- 它的底层封装的是Map结构
- 命名参数支持参数【param1,param2,…】,但不支持【arg0,arg1…】
示例代码:
①Mapper接口对应代码的书写
//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByName(@Param("lName") String lastName,@Param("salary") double salary);
②接口对应的映射文件中书写的sql
版本一(参数不使用param1,param2):
<select id="showEmpByName" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
//#{lName}里是Mapepr接口中对应方法形参中@Param("lName")里的值
where
last_name=#{lName}
and
salary=#{salary}
</select>
版本二(参数使用param1,param2):
<select id="showEmpByName" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
where
last_name=#{param1}
and
salary=#{param2}
</select>
版本三(参数使用arg0,arg1)
<select id="showEmpByName" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
where
last_name=#{arg0}
and
salary=#{arg1}
</select>
③测试
@Test
public void test4(){
try {
//从当前类下寻找并加载mybatis-config.xml(核心配置文件)
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession()获取sqlsession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlsession对象使用getMapper(),传入EmployeeMapper的反射对象以获取代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//使用其代理对象调用showEmpByName()通过员工姓名与薪资去查找相应的员工
List<Employee> jack = employeeMapper.showEmpByName("jack", 9000);
System.out.println(jack);
} catch (IOException e) {
e.printStackTrace();
}
}
1.4 POJO(java Bean)参数传递
Mybatis支持POJO [Java Bean】入参,参数key是POjO中的属性
用法案例:基于1.2小结中的用法案例,修改Mapper接口中该方法的形参为Employee类型,仅修改映射文件中相应的sql与测试代码
①修改Mapper接口中该方法的形参类型为Employee
代码示例如下:
//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(Employee employee);
②修改映射文件中相应的sql
<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
where
last_name=#{lastName}
and
salary=#{salary}
</select>
③测试
@Test
public void test3(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee=new Employee();
employee.setSalary(5600.0);
employee.setLastName("jack");
Employee jack = employeeMapper.selectEmployeeByNameandSalary(employee);
System.out.println(jack);
} catch (IOException e) {
e.printStackTrace();
}
}
1.5 Map参数传递
Mybatis支持Map集合类型的元素直接入参,map的key是参数的key
注意:
Mybatis不支持方法重载,因为在Mybatis中xxxMapper接口对应的映射文件中若存在相同方法的sql,则其id值不能保持唯一性,会发生冲突
用法案例:基于1.2节的案例,这次使用Map集合作为形参传入,在对应的映射文件中书写相应的sql并测试
代码示例如下:
①使用Map集合作为形参传入
//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByMap(Map<String,Object> map);
②在对应的映射文件中书写相应的sql
<select id="showEmpByMap" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
where last_name=#{lastName} and salary=#{salary}
</select>
③测试
@Test
public void test5() {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Map<String,Object> map=new HashMap<>();
map.put("lastName","jack");
map.put("salary",5600);
List<Employee> jack = employeeMapper.showEmpByMap(map);
System.out.println(jack);
} catch (IOException e) {
e.printStackTrace();
}
}
1.6 Collection ,List & Array等参数传递
当传入的参数数据类型为 Collection ,List 或Array等,在对应映射文件的相应sql部分可直接使用mybatis对应的内置自定义类型别名(collection、list、array)传入,亦可使用命名参数自定义名称。
用法案例:通过多个id获取员工的信息 【EmpIds:员工id的集合】
代码示例如下:
a.在EmployeeMapper接口定义相应的方法
/**
* 通过多个id获取员工的信息 【EmpIds:员工id的集合】
* @param EmpIds
* @return
*/
public List<Employee> selectEmpByIds(@Param("ids") List<Integer> EmpIds);
b.在EmployeeMapper接口对应的映射文件中定义相应的sql
<select id="selectEmpByIds" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
<where>
`id` in
(
<foreach collection="ids" item="id" separator=",">
#{id}
</foreach>
)
</where>
</select>
c.测试
@Test
public void test04(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = employeeMapper.selectEmpByOneOpr(1);
System.out.println(employees);
} catch (IOException e) {
e.printStackTrace();
}
}
二. Mybatis参数传递中#与$的使用问题
2.1 #与$的区别
#
:底层执行SQL语句的对象,使用PreparedStatementd,预编译SQL,防止SQL注入安全隐患,相对比较安全。$
:底层执行SQL语句的对象使用Statementi对象,未解决SQL注入安全隐患,相对不安全。
2.2 #与$的使用场景
以查询SQL为例:
select col,col2 from table1 where col=? and col2=?group by? order by?limit?,?
使用场景:
“#”
使用场景:在上述Sql中的占位符位置均可以使用#
“$”
使用场景:#
解决不了的参数传递问题,均可以交给$
处理【如form动态表格】
示例代码如下:
public List<Employee> selectEmpByDynamitTable(@Param("tblName")String tblName);
<select id="selectEmpByDynamitTable" resultType="employee">
SELECT
id,
last_name,
email,
salary
FROM
${tb1Name}
</select>
附注:
在 Mybatis 中,$ 符号也是用于访问各种参数、变量等的值和信息的符号,主要用于动态 SQL 的构建和参数传递等场景中,例如:
${variable}
:用于插入变量或者表名/列名等的动态语句部分#{parameter}
:用于占位符参数的预编译语句$方法名()
:用于调用 SQL 片段中定义的方法并返回结果
为什么说${variable}主要用于插入动态语句的部分?
解析不同:
-
${variable}
:它是将传入的参数值直接显示在原来的sql语句中,且不加任何引号例如slect * from users where id= v a r i a b l e ,传入 {variable},传入 variable,传入{1} => id=1
代码示例如下:
<select id="showEmpByMap" resultType="mybatis.pojo.Employee"> select id, last_name , email, salary from tbl_employee where last_name=${lastName} and salary=${salary} </select>
-
#{variable}
:是将传入的参数值当成一个字符串且加双引号显示例如slect * from users where id= v a r i a b l e ,传入 {variable},传入 variable,传入{1} => id=“1”
代码示例如下:
<select id="showEmpByMap" resultType="mybatis.pojo.Employee"> select id, last_name , email, salary from tbl_employee where last_name=#{lastName} and salary=#{salary} </select>