1、获取参数的方式
(1).#{} ==> jdbc String sql="select id,username from emp where id = ?"
(1)会经过JDBC当中PreparedStatement的预编译,会根据不同数据类型来编译成数据库所对应的数据
id=1
username='xxx'
(2)能够有效的防止sql注入(推荐使用)
特殊用法:
自带了很多内置参数的属性,通常不会使用
javaType、jdbcType、mode、numericScale、resultMap、typeHandler
比如,id可能为null,默认会设置为OTHER(NULL==>OTHER ),但oracle没有other,
这时,可以写为#{id,javaType=null},想要保留小数点后两位:#{price,numericScale=2}
(2).${} ==> jdbc String sql="select id,username from emp where id =" + id
(1)不会进行预编译,直接将传进来的数据拼接在sql中
(2)存在sql注入风险,不推荐使用。
特殊用法:
1.调试情况下可以暂时使用
2.可以实现一些特殊功能(前提:一定保证数据的安全性):
比如,动态表、动态列、动态SQL
根据用户选择的列排序
2、参数传递的处理
1.单个参数:selectEmp(Integer id);
获取方式:
mybatis不会有什么强制的要求,#{可以输入任何字符来获取参数}
2.多个参数:Emp selectEmp(Integer id, String username);
mybatis会将传进来的参数封装成map
一个参数对应map中两组key和value:
id ==> {key:arg0,value:id的值},{key:param1,value:id的值}
username ==> {key:arg1,value:username的值},{key:param2,value:username的值}
获取方式:
不使用@Param注解时,可以使用:
id =====> #{arg0} 或者 #{param1}
username =====> #{arg1} 或者 #{param2}
除了这种方式(参数名无意义),还有其他方式
可以使用@Param注解,但是使用注解后arg*的方式就会失效,但是可以使用param*的方式
id =====> #{id} 或者 #{param1}
username =====> #{username} 或者 #{param2}
3.javaBean参数
单个参数:Emp selectEmp(Emp emp);
获取方式:
emp.id=====> #{id}
emp.username=====> #{username }
多个参数:selectEmp(Integer num, Emp emp);
获取方式:
不使用@Param注解时,可以使用:
num=====> #{arg0}或#{param1}
emp.id=====> #{arg1.id}或#{param2.id}
emp.username=====> #{arg1.username}或#{param2.username}
使用@Param注解时:
num=====> #{@Param}或#{param1}
emp.id =====> #{@Param.id} 或者 #{param2.id}
emp.username =====> #{@Param.username} 或者 #{param2.username}
4.集合或者数组参数:selectEmp(List<String> usernames);
如果是list,mybatis会自动封装成为map:
获取方式:username = #{list[0]} or username = #{list[1]}
{key:"list",value:usernames}
不使用@Param注解时,要获得:usernames.get(0) =====> #{arg0[0]}
usernames.get(0) =====> #{list[0]}
使用@Param("usernames")注解时,要获得:usernames.get(0) =====> #{usernames[0]}
usernames.get(0) =====> #{param1[0]}
如果是数组,mybatis会自动封装成为map:
获取方式:username = #{array[0]} or username = #{array[1]}
{key:"array",value:usernames}
不使用@Param注解时,要获得:usernames.get(0) =====> #{arg0[0]}
usernames.get(0) =====> #{array[0]}
使用@Param("usernames")注解时,要获得:usernames.get(0) =====> #{usernames[0]}
usernames.get(0) =====> #{param1[0]}
4.map参数:和javaBean的参数传递是一样。
一般情况下:插入或者修改这种参数和pojo属性是全对应的情况,就用javaBean
请求进来的参数,没有和pojo对应,就用map
请求进来的参数,没有和pojo对应,但是用频率很高,就用TO(Transfer Object),DTO
(即单独为这些参数创建一个对应的javaBean出来,是参数传递更规范)
3、返回类型设置
返回类型设置:
如果返回一行数据,就可以使用pojo或map接收
如果返回多行数据,就可以使用List<pojo>或List<map>接收,resultType指定list中的泛型类型*****就可以
基础类型或者包装类型,就直接指定别名就行了
4、自定义结果集
resultType 与 resultMap(Mybatis最强大的特性)不能同时使用
1.声明resultMap自定义结果集(体现出ORM[Object Relational Mapping]淋漓尽致)
id 唯一标识,需要<select 上的resultMap进行对应
type 需要映射的pojo对象,可以设设置别名(前提是配置了别名<TypeAlias>)
autoMapping 自动映射(默认值为true),只要数据库字段与JavaBean属性名遵循映射规则就可以自动映射
但是不建议,哪怕属性名与字段名字一致,也要显式的写入
extends 如果多个resultMap有重复的映射,可以声明父resultMap,将公共映射提取出来,可以减少子resultMap映射的冗余
主键用<id>元素,其他字段都用<result>元素
2.
<resultMap id="common_map" type="emp">
<!--主键必须使用<id ,对底层的存储有性能作用
column 映射的数据库字段名
property 映射的pojo属性名
-->
<id column="id" property="id" />
<result column="username" property="username" />
</resultMap>
<resultMap id="emp_map1" type="emp" extends="common_emp">
<result column="createdate" property="date" />
</resultMap>
5、Select 元素的属性
属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType 可选 STATEMENT,PREPARED 或 CALLABLE(存储过程)。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultSets 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
6.1、EmpMapper.java
package cn.qqa.mapper;
import cn.qqa.pojo.Emp;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 注意
* xxxMapper.xml文件中,同一个命名空间只能有一个唯一的id,
* 所以在接口中也只能有唯一一个方法名,虽然java中可以函数重载,但是mybatis不支持
*/
public interface EmpMapper {
/*
单个参数,#{随便输入}
//查询
Emp selectEmp(Integer id);
*/
/*
多个参数
不使用@Param注解时,可以使用:
id =====> #{arg0} 或者 #{param1}
username =====> #{arg1} 或者 #{param2}
使用@Param注解,但是使用注解后arg*的方式就会失效,但是可以使用param*的方式
id =====> #{id} 或者 #{param1}
username =====> #{username} 或者 #{param2}
Emp selectEmp(@Param("id") Integer id,@Param("username") String username);
*/
/*
3.javaBean参数
单个参数:Emp selectEmp(Emp emp);
获取方式:
emp.id=====> #{id}
emp.username=====> #{username }
多个参数:selectEmp(Integer num, Emp emp);
获取方式:
不使用@Param注解时,可以使用:
num=====> #{arg0}或#{param1}
emp.id=====> #{arg1.id}或#{param2.id}
emp.username=====> #{arg1.username}或#{param2.username}
使用@Param注解时:
num=====> #{@Param}或#{param1}
emp.id =====> #{@Param.id} 或者 #{param2.id}
emp.username =====> #{@Param.username} 或者 #{param2.username}
Emp selectEmp(Integer num, Emp emp);*/
/*
如果是list,mybatis会自动封装成为map:
获取方式:username = #{list[0]} or username = #{list[1]}
{key:"list",value:usernames}
要获得usernames.get(0) =====> #{list[0]}
List<Emp> selectEmp(List<String> usernames);
*/
Emp selectEmp(Integer id);
/*
Integer select1(String username,@Param("id") Integer id);
Integer select2(@Param("beginDate") String beginDate, String endDate,
Emp emp);
Integer select3(List<Integer> ids,String [] usernames,
@Param("beginDate") String beginDate, String endDate);
*/
}
6.2、EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.qqa.mapper.EmpMapper">
<!--
获取参数的方式
1.#{} ==> jdbc String sql="select id,username from emp where id = ?"
(1)会经过JDBC当中PreparedStatement的预编译,会根据不同数据类型来编译成数据库所对应的数据
id=1
username='xxx'
(2)能够有效的防止sql注入(推荐使用)
特殊用法:
自带了很多内置参数的属性,通常不会使用
javaType、jdbcType、mode、numericScale、resultMap、typeHandler
比如,id可能为null,默认会设置为OTHER(NULL==>OTHER ),但oracle没有other,
这时,可以写为#{id,javaType=null},想要保留小数点后两位:#{price,numericScale=2}
2.${} ==> jdbc String sql="select id,username from emp where id =" + id
(1)不会进行预编译,直接将传进来的数据拼接在sql中
(2)存在sql注入风险,不推荐使用。
特殊用法:
1.调试情况下可以暂时使用
2.可以实现一些特殊功能(前提:一定保证数据的安全性):
比如,动态表、动态列、动态SQL
根据用户选择的列排序
-->
<!--
参数传递的处理
1.单个参数:selectEmp(Integer id);
获取方式:
mybatis不会有什么强制的要求,#{可以输入任何字符来获取参数}
2.多个参数:Emp selectEmp(Integer id, String username);
mybatis会将传进来的参数封装成map
一个参数对应map中两组key和value:
id ==> {key:arg0,value:id的值},{key:param1,value:id的值}
username ==> {key:arg1,value:username的值},{key:param2,value:username的值}
获取方式:
不使用@Param注解时,可以使用:
id =====> #{arg0} 或者 #{param1}
username =====> #{arg1} 或者 #{param2}
除了这种方式(参数名无意义),还有其他方式
可以使用@Param注解,但是使用注解后arg*的方式就会失效,但是可以使用param*的方式
id =====> #{id} 或者 #{param1}
username =====> #{username} 或者 #{param2}
3.javaBean参数
单个参数:Emp selectEmp(Emp emp);
获取方式:
emp.id=====> #{id}
emp.username=====> #{username }
多个参数:selectEmp(Integer num, Emp emp);
获取方式:
不使用@Param注解时,可以使用:
num=====> #{arg0}或#{param1}
emp.id=====> #{arg1.id}或#{param2.id}
emp.username=====> #{arg1.username}或#{param2.username}
使用@Param注解时:
num=====> #{@Param}或#{param1}
emp.id =====> #{@Param.id} 或者 #{param2.id}
emp.username =====> #{@Param.username} 或者 #{param2.username}
4.集合或者数组参数:selectEmp(List<String> usernames);
如果是list,mybatis会自动封装成为map:
获取方式:username = #{list[0]} or username = #{list[1]}
{key:"list",value:usernames}
不使用@Param注解时,要获得:usernames.get(0) =====> #{arg0[0]}
usernames.get(0) =====> #{list[0]}
使用@Param("usernames")注解时,要获得:usernames.get(0) =====> #{usernames[0]}
usernames.get(0) =====> #{param1[0]}
如果是数组,mybatis会自动封装成为map:
获取方式:username = #{array[0]} or username = #{array[1]}
{key:"array",value:usernames}
不使用@Param注解时,要获得:usernames.get(0) =====> #{arg0[0]}
usernames.get(0) =====> #{array[0]}
使用@Param("usernames")注解时,要获得:usernames.get(0) =====> #{usernames[0]}
usernames.get(0) =====> #{param1[0]}
4.map参数:和javaBean的参数传递是一样。
一般情况下:插入或者修改这种参数和pojo属性是全对应的情况,就用javaBean
请求进来的参数,没有和pojo对应,就用map
请求进来的参数,没有和pojo对应,但是用频率很高,就用TO(Transfer Object),DTO
(即单独为这些参数创建一个对应的javaBean出来,是参数传递更规范)
-->
<!--select1(String username,@Param("id") Integer id);-->
<!-- <select id="select1" resultType="int">
SELECT id,username FROM EMP WHERE username = #{param1} and id = #{id}
</select>-->
<!--
Integer select2(@Param("beginDate") String beginDate, String endDate,
Emp emp);
-->
<!-- <select id="select2" resultType="int">
SELECT id,username FROM EMP WHERE createdate = #{beginDate} and endDate = #{param2}
and id = #{param3.id} and username = #{param3.username}
</select>-->
<!--
Integer select3(List<Integer> ids,String [] usernames,
@Param("beginDate") String beginDate, String endDate);
-->
<select id="select3" resultType="int">
SELECT count(*) FROM EMP WHERE id = #{param1[0]} or id = #{param1[1]}
or username = #{param2[0]} or username = #{param2[1]}
or createdate = #{beginDate} or endDate = #{param4}
</select>
<!--
返回类型设置:
如果返回一行数据,就可以使用pojo或map接收
如果返回多行数据,就可以使用List<pojo>或List<map>接收,resultType指定list中的泛型类型*****就可以
基础类型或者包装类型,就直接指定别名就行了
-->
<!--
resultType 与 resultMap(Mybatis最强大的特性)不能同时使用
1.声明resultMap自定义结果集(体现出ORM[Object Relation Mapping]淋漓尽致)
id 唯一标识,需要<select 上的resultMap进行对应
type 需要映射的pojo对象,可以设设置别名(前提是配置了别名)
autoMapping 自动映射(默认值为true),只要数据库字段与JavaBean属性名遵循映射规则就可以自动映射
但是不建议,哪怕属性名与字段名字一致,也要显式的写入
extends 如果多个resultMap有重复的映射,可以声明父resultMap,将公共映射提取出来,可以减少子resultMap映射的冗余
主键用<id>元素,其他字段都用<result>元素
-->
<resultMap id="common_map" type="emp">
<!--主键必须使用<id ,对底层的存储有性能作用
column 映射的数据库字段名
property 映射的pojo属性名
-->
<id column="id" property="id" />
<result column="username" property="username" />
</resultMap>
<resultMap id="emp_map1" type="emp" extends="common_emp">
<result column="createdate" property="date" />
</resultMap>
<resultMap id="emp_map" type="emp">
<id column="id" property="id" />
<result column="username" property="username" />
<result column="createdate" property="date" />
</resultMap>
<!--使用resultMap关联自定义结果集的id-->
<!--根据id查询Emp对应实体(数据库字段)-->
<select id="selectEmp" resultMap="emp_map">
SELECT id,username,createdate FROM EMP WHERE id = #{id}
</select>
<!--
Select 元素的属性
属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
resultType 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType 可选 STATEMENT,PREPARED 或 CALLABLE(存储过程)。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultSets 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
-->
</mapper>
6.3、MybatisHomeworkTest.java
package cn.qqa.tests;
import cn.qqa.mapper.EmpMapper;
import cn.qqa.pojo.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
/**
* 日志配置
* 1.导入pom依赖
* 2.添加logback配置文件
* 3.在某个类下加入声明
*/
public class MybatisHomeworkTest {
Logger logger = LoggerFactory.getLogger(this.getClass());
SqlSessionFactory sqlSessionFactory;
@Before
public void before(){
//从XML中构建SqlSeesionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
/* @Test
public void test01() throws IOException, SQLException {
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
try{
String[] usernames =new String[]{"秦清澳","汪星源"};
List<Emp> emps = mapper.selectEmp(usernames);
System.out.println(emps);
}catch (Exception ex){
System.out.println("查询失败!");
}
sqlSession.commit();
sqlSession.close();
}*/
/**
*select1(String username,@Param("id") Integer id);
*/
/* @Test
public void test02() throws IOException, SQLException {
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
try{
String[] usernames =new String[]{"秦清澳","汪星源"};
Integer res= mapper.select1("qqa",1);
System.out.println(res);
}catch (Exception ex){
ex.printStackTrace();
System.out.println("查询失败!");
}
sqlSession.commit();
sqlSession.close();
}*/
/**
Integer select2(@Param("beginDate") String beginDate, String endDate,
Emp emp);
*/
/* @Test
public void test03() throws IOException, SQLException {
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
try{
String[] usernames =new String[]{"秦清澳","汪星源"};
Emp emp = new Emp(1, "qqa");
Integer res= mapper.select2("11:01","12:01",emp);
System.out.println(res);
}catch (Exception ex){
ex.printStackTrace();
System.out.println("查询失败!");
}
sqlSession.commit();
sqlSession.close();
}*/
/* Integer select3(List<Integer> ids, String [] usernames,
@Param("beginDate") String beginDate, String endDate);*/
/* @Test
public void test04() throws IOException, SQLException {
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
try{
List<Integer> ids = Arrays.asList(1,5);
String[] usernames =new String[]{"秦清澳","汪星源"};
Emp emp = new Emp(1, "qqa");
Integer res= mapper.select3(ids, usernames,"11:01","12:01");
System.out.println(res);
}catch (Exception ex){
ex.printStackTrace();
System.out.println("查询失败!");
}
sqlSession.commit();
sqlSession.close();
}*/
}