一、参数传入问题
1.一个简单参数
Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方法的参数名无关。
接口方法
Student selectById(Integer id);
mapper 文件
<select id="selectById" resultType="com.aiit.domain.Student">
select * from student where id=#{id}
</select>
#{id} , id 是自定义的变量名称,和方法参数名无关
测试方法
@Test
public void testSelectById(){
//一个参数
Student student = studentDao.selectById(1001);
System.out.println("查询 id 是 1001 的学生:"+student);
}
2.多个参数
方式一:使用@Param
当 Dao 接口方法多个参数,需要通过名称使用参数。
在方法形参前面加入@Param(“自定义参数名”)
接口方法
/*
* 多个参数:命名参数,在形参定义的前面加入@param("自定义参数名称")
* */
List<Student> selectMulitParam(@Param("myname") String name,@Param("myage") Integer age);
mapper文件
<select id="selectMulitParam" resultType="com.aiit.domain.Student">
select * from student where name=#{myname} or age=#{myage};
</select>
测试方法:
@Test
public void testSelectMultParam(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> students = studentDao.selectMulitParam("宋进锋", 20);
students.forEach(student -> System.out.println(student));
sqlSession.close(); }
}
方式二:使用JAVA对象
我们可以书写一个装饰类,里面存放的是我们需要传入的属性
public class QueryParam {
private String paramName;
private Integer paramAge;
}
接口方法
/*
* 多个参数.使用jave对象作为接口中的方法参数
* */
List<Student> selectMultiObject(QueryParam queryParam);
mapper.xml文件
以下由两种写法
多个参数:使用java对象的属性值,作为参数实际值
使用对象方法,#{属性名} javaType=类型名称,jdbcType=数据类型
javaType:指java中属性数据类型
jdbcType:在数据库中的数据类型
例如:#{paramName,javaType="java.lang.String",jdbcType=VARCHAR}
我们使用简化方式:#{属性名} javaType jdbcType的值mybatis反射能获取。不用提供
<select id="selectMultiObject" resultType="com.aiit.domain.Student">
select * from student where name=#{paramName,javaType="java.lang.String",jdbcType=VARCHAR}
or #{paramAge,javaType="java.lang.Integer",jdbcType=INTEGER};
</select>
<select id="selectMultiObject" resultType="com.aiit.domain.Student">
select * from student where name=#{paramName}
or #{paramAge};
</select>
测试方法
@Test
public void testSelectMultObject(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
QueryParam param = new QueryParam();
param.setParamName("张三");
param.setParamAge(22);
List<Student> students = studentDao.selectMultiObject(param);
students.forEach(student -> System.out.println(student));
sqlSession.close(); }
该处一定要学会灵活运行,我们传入的对象可以是一个Student类,然而他们参数可以是Student类里面的name和age属性
方式三:按照位置传入参数(不推荐)
接口方法
/*
* 多个参数-简单类型,按照位置传入参数
* mybatis 3.4之前,使用#{0} ,#{1}
* mybatis 3.4之后,使用#{arg0} ,#{arg1}
* */
List<Student> selectMultiPosition(String name,Integer age);
mapper.xml文件
<select id="selectMultiPosition" resultType="com.aiit.domain.Student">
select * from student where name=#{arg0}
or #{arg1};
</select>
方式四:使用map集合传入参数(不推荐)
接口方法
/*
* 多个参数,使用Map存放多个值
* */
List<Student> selectMulitByMap(Map<String, Object>map);
测试方法
@Test
public void testSelectMultiByMap(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Map<String, Object> data = new HashMap<>();
data.put("myname","张三");
data.put("myage",28);
List<Student> students = studentDao.selectMulitByMap(data);
students.forEach(student -> System.out.println(student));
sqlSession.close(); }
}
mapper.xml配置文件
<select id="selectMultiPosition" resultType="com.aiit.domain.Student">
select * from student where name=#{myname}
or #{myage};
</select>
3.# 和 $
1.使用#,可以替换成?
select id,name, email,age from student where id=#{id}
#的结果: select id,name, email,age from student where id=?
2.使用$,可以替换成字符串拼接
select id,name, email,age from student where id=${studentId}
$ 的结果:select id,name, email,age from student where id=1001
也可以写成如下:
String sql="select id,name, email,age from student where id=" + "1001";
# 和 $区别
-
#使用 ?在sql语句中占位的, 使用PreparedStatement执行sql,效率高
-
#能够避免sql注入,更安全。
-
$不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
-
$有sql注入的风险,缺乏安全性。
-
$:可以替换表名或者列名(
select * from user order by name
)这里的name可以进行值得更改
举例SQL注入问题
如果我们参数传过来的值为:
List<Student> students = dao.selectUser("'李四';drop table student");
因为$是一种字符串的拼接方式,那么当我们传入这种参数的时候,会发生两个语句
select * from student where name ='李四';drop table student;
此时会导致我们的数据库里面删除,用户在输入这些语句的时候,会造成我们的数据库的隐患。
二、结果返回问题
1、resultType结果类型
-
指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
-
resultType结果类型的它值
- 类型的全限定名称
- 类型的别名, 例如 java.lang.Integer别名是int
- 当我们返回值是集合,只要返回的值是< T >当中的泛型即可
案例
接口文件
List<Student> selectMultiParam(@Param("myname") String name,@Param("myage") Integer age);
Integer queryCountStudent();
Mapper.xml文件
<select id="selectMultiParam" resultType="com.aiit.domain.Student">
select * from student;
</select>
<select id="queryCountStudent" resultType="int">
select count(*) from student;
</select>
2、 定义自定义类型的别名
在mybatis主配置文件中定义,使<typeAlias>
定义别名
- 可以在resultType中使用自定义别名
- 也可以使用package标签
主配置文件
<typeAliases>
<!--方式一-->
<typeAlias type="com.aiit.domain.Student" alias="Student"></typeAlias>
<!--方式二-->
<package name="com.aiit.domain"/>
</typeAliases>
mapper文件
<select id="selectStudentById" resultType="Student">
select * from student where id=#{id};
</select>
推荐使用全包名的方式,不适用取别名的方式,因为如果我们使用了相同类名的属性,会进行报错
三、ResultMap
概念:其为结果映射,指定列名和java对象的属性对应关系
功能:
1.自定义列值赋值给哪个属性
2.当列名和属性值不一样,一定要使用ResultMap
接口方法
/*
* 使用resultMap定义映射关系
* */
List<Student> selectAllStudents();
mapper.xml文件
<resultMap id="studentMap" type="com.aiit.domain.Student">
<!--列名和java属性的关系-->
<!--主键列,使用id标签
column:列名
property:java类型的属性名
-->
<id column="id" property="id"/>
<!--非主键列,使用result-->
<result column="name" property="name"/>
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select * from student;
</select>
注意
-
resultMap标签中
id
与<select>
中的resultMap属性的值必须保持一致 -
resultMap中的主键列使用id属性,
-
column:列名
-
property:java类型的属性名
-
除id之外的属性,使用result标签
四、实体之间的关系
一对一
一对多
五、模糊查询
接口方法
/*
* 模糊查询
* 在java代码指定,like的内容
* */
List<Student> selectLikeOne (String name);
mapper.xml文件
<!--第一种like方式-->
<select id="selectLikeOne" resultType="com.aiit.domain.Student">
select * from student where name like #{name}
</select>
测试方法
@Test
public void testSelectLikeOne(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
String name="%张%";
List<Student> students = studentDao.selectLikeOne(name);
students.forEach(student -> System.out.println(student));
sqlSession.close();
}
六、动态sql
动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。
动态sql的实现,使用的是mybatis提供的标签, <if>
,<where>
,<foreach>
< if > 标签
1.语法
<if test="判断java对象的属性值">
部分sql语句
</if>
2.案例
接口方法
List<Student> selectStudentIf(Student student);
mapper.xml文件
<!--if-->
<!--<if:test "判断java对象的属性值 语法:属性=XXX值"-->
<select id="selectStudentIf" resultType="com.aiit.domain.Student">
select * from student
where
<if test="name !=null and name !=''">
name =#{name}
</if>
<if test="age > 0">
and age >#{age}
</if>
</select>
测试方法:
@Test
public void testSelectStudentIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("李四");
student.setAge(20);
List<Student> students = dao.selectStudentIf(student);
students.forEach(s -> System.out.println(s));
sqlSession.close();
}
< where >标签
1.概述
<where>
用来包含 多个<if>
的, 当多个if有一个成立的, <where>
会自动增加一个where关键字,并去掉 if中多余的 and ,or等
2.案例
接口方法
List<Student> selectStudentWhere(Student student);
mapper.xml文件
<!--where标签-->
<select id="selectStudentWhere" resultType="com.aiit.domain.Student">
select * from student
<where>
<if test="name !=null and name !=''">
name =#{name}
</if>
<if test="age > 0">
and age >#{age}
</if>
</where>
</select>
where标签可以自动过滤一些有误的sql语句
< foreach>标签
1.概述
<foreach>
循环java中的数组,list集合的。 主要用在sql的in语句中
2.案例
七、代码片段
<sql/>
标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用<include/>
子标签。该标签可以定义 SQL 语句中的任何部分,所以<include/>
子标签可以放在动态 SQL的任何位置
案例
<mapper namespace="com.aiit.dao.StudentDao">
<!--定义sql片段-->
<sql id="studentsql">
select * from student
</sql>
<!--if-->
<!--<if:test "判断java对象的属性值 语法:属性=XXX值"-->
<select id="selectStudentIf" resultType="com.aiit.domain.Student">
<include refid="studentsql"></include>
where
<if test="name !=null and name !=''">
name =#{name}
</if>
<if test="age > 0">
and age >#{age}
</if>
</select>
</mapper>
八、PageHelper
基于 PageHelper 分页:
(1) maven 坐标
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
(2)PageHelper 对象
查询语句之前调用 PageHelper.startPage 静态方法。
除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。
需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个 MyBatis 查询方法会被进行分页。
@Test
public void testSelect() throws IOException {
//获取第 1 页,3 条内容
PageHelper.startPage(1,3);
List<Student> studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
}