目录
6.深入理解参数
把数据传入到mapper文件的sql语句中。
6.1 parameterType
parameterType:接口中方法参数的类型,值是java数据类型的完全限定名或者是mybatis定义的别名。这个属性是可选的,因为Mybatis可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从java代码转入到mapper文件的sql语句。
parameterType不是强制的,mybatis可以通过反射机制能够发现接口参数的数据类型。
public interface StudentDao {
public Student selectStudentById(Integer id);
}
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{id}
</select>
public class TestMyBatis {
@Test
public void testSelectStudentById(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = dao.selectStudentById(1002);
System.out.println(student);
}
}
6.2 传入一个简单参数
mybatis把java的基本数据类型及其包装类和String类型叫做简单类型。
在mapper文件获取简单类型的一个参数的值,使用#{任意字符}。
使用#{}之后,mybatis执行sql是使用的jdbc中的PreparedStatement对象。由mybatis执行下面的代码:
①mybatis创建Connection、PreparedStatement对象;
String sql = "select id,name,email,age from studeng where id=?";
PreparedStatement ps = conn.preparedStatement(sql);
ps.setInt(1,1001);
②执行sql封装为"com.bjpowernode.domain.Student"这个类的对象;
ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next()){
//从数据库取表的一行数据,存到一个java对象属性中
student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getInt("name"));
student.setEmail(rs.getInt("email"));
student.setAge(rs.getInt("age"));
}
return student;//给了dao方法调用的返回值
6.3 多个参数---使用@Param
使用@Param("自定义参数名称"),放在形参的前面。
public interface StudentDao {
/**
* 多个参数:命名参数,在形参的前面加入@Param("自定义参数名称")
*/
List<Student> selectMultiParam(@Param("myname") String name,@Param("myage") Integer age);
}
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{myname} or age=#{myage}
</select>
public class TestMyBatis {
@Test
public void testSelectMulitParam(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectMultiParam("李四",20);
for(Student student : students){
System.out.println(student);
}
sqlSession.close();
}
}
6.4 多个参数---使用对象
使用java对象传递参数,java的属性值就是sql需要的参数值,每一个属性就是一个参数。
语法格式:#{属性名,javaType=类型名称,jdbcType=数据类型}
javaType:指java中的属性数据类型
jdbcType:指数据库中的数据类型
这种语法格式很少使用。
我们使用简化方式:#{属性名},javaType、jdbcType的值mybatis可以通过反射获取,不用自己手动提供。
package com.bjpowernode.vo;
public class QueryParam {
private String paramName;
private Integer paramAge;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public Integer getParamAge() {
return paramAge;
}
public void setParamAge(Integer paramAge) {
this.paramAge = paramAge;
}
@Override
public String toString() {
return "QueryParam{" +
"paramName='" + paramName + '\'' +
", paramAge=" + paramAge +
'}';
}
}
public interface StudentDao {
/**
* 多个参数,使用java对象作为接口中方法的参数
*/
List<Student> selectMultiObject(QueryParam param);
List<Student> selectMultiStudent(Student student);
}
<!--
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{paramName,javaType=java.lang.String,jdbc=VARCHAR}} or
age=#{paramAge,javaType=java.lang.Integer,jdbc=INTEGER}}
</select>
-->
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{paramName} or age=#{paramAge}
</select>
<select id="selectMultiStudent" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{name} or age=#{age}
</select>
public class TestMyBatis {
@Test
public void testSelectMulitObject(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
QueryParam queryParam = new QueryParam();
queryParam.setParamName("李四");
queryParam.setParamAge(20);
List<Student> students = dao.selectMultiObject(queryParam);
for(Student student : students){
System.out.println(student);
}
sqlSession.close();
}
@Test
public void testSelectMulitStudent(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("李四");
student.setAge(20);
List<Student> students = dao.selectMultiStudent(student);
for(Student stu : students){
System.out.println(stu);
}
sqlSession.close();
}
}
6.5 多个参数---按位置
public interface StudentDao {
/**
* 多个参数-简单类型的,按位置传值
* mybatis.3.4之前,使用#{0},#{1}
* mybatis.3.4之后,使用#{arg0},#{arg1}
*/
List<Student> selectMultiPosition(String name,Integer age);
}
<!--多个参数使用位置-->
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{arg0} or age=#{arg1}
</select>
public class TestMyBatis {
@Test
public void testSelectMulitPosition(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectMultiPosition("李四",20);
for(Student stu : students){
System.out.println(stu);
}
sqlSession.close();
}
}
6.6 多个参数---使用Map
public interface StudentDao {
/**
* 多个参数,使用Map存放多个值
*/
List<Student> selectMultiMap(Map<String,Object> map);
}
<!--多个参数,使用Map,使用语法#{map的key}-->
<select id="selectMultiMap" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{myName} or age=#{myAge}
</select>
public class TestMyBatis {
@Test
public void testSelectMulitMap(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<String,Object> data = new HashMap<>();
data.put("myName","李四");
data.put("myAge",20);
List<Student> students = dao.selectMultiMap(data);
for(Student stu : students){
System.out.println(stu);
}
sqlSession.close();
}
}
6.7 #和$
#:占位符。告诉mybatis使用实际的参数值代替,并且使用PreparedStatement对象执行sql语句,#{...}代替了sql语句的"?"。这样做可以避免sql注入现象,更安全,更迅速,通常也是首选做法。
$:字符串替换。告诉mybatis使用$包含的"字符串"替换所在位置。使用Statement对象把sql语句和${}的内容连接起来。可能存在sql注入现象。主要用在替换表名、列名、不同列排序等操作。
<!-- $替换列名 --> <select id="selectUse$Order" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student order by ${colName} </select>
#和$的区别:
①#使用?在sql语句中做占位的,使用PreparedStatement对象执行sql,效率高
②#能够避免sql注入,更安全
③$不使用占位符,而是字符串连接方式,使用Statement对象执行sql,效率低
④$有sql注入的风险,缺乏安全性
⑤$可以替换表名或者列名
7.封装MyBatis输出结果
7.1 resultType的使用
resultType:执行sql得到ResultSet转换的类型,这个类型是任意的,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。注意resultType和resultMap不能同时使用。
1.返回简单类型:可以返回mybatis定义的类型的别名,或者返回类的全限定名称。建议使用全限定名称。
int countStudent();
<!--返回简单类型,mybatis定义的类型的别名或全限定名称都可以-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
select count(*) from student
</select>
@Test
public void testRetunInt(){
int count = studentDao.countStudent();
System.out.println("学生总人数:"+ count);
}
2.返回对象类型。
public Student selectStudentById(Integer id);
<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{id}
</select>
@Test
public void testSelectStudentById(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = dao.selectStudentById(1002);
System.out.println(student);
}
执行过程:
①mybatis执行sql语句,然后mybatis调用类的无参构造方法,创建对象;
②mybatis把ResultSet中的列值赋给同名的对象属性。
可以定义自定义类型的别名:
①在mybatis主配置文件中定义,使用<typeAlias>定义别名;
②可以在resultType中使用自定义的别名。
比如自定义了一个类ViewStudent。最好还是使用全限定名称,最准确。
<!--自定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆)
<typeAlias type="com.bjpowernode.domain.Student" alias="stu"></typeAlias>
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu"></typeAlias>
-->
<!--
第二种方式:
<package> name是包名,这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
<!--selectStudentReturnViewStudent-->
<!--<select id="selectStudentReturnViewStudent" resultType="vstu">-->
<select id="selectStudentReturnViewStudent" resultType="viewstudent">
select id,name,email,age from student where id=#{sid}
</select>
3.返回Map。sql的查询结果作为Map的key和value。推荐使用Map<Object,Object>。注意:Map作为接口返回值,sql语句的查询结果最多只能有一条记录,大于一条记录是错误的。如果要查找多条记录,其实就相当于返回了一个集合,集合内元素的类型是Map<Object,Object>。
//定义方法返回Map
Map<Object,Object> selectMapById(Integer id);
<!--
返回Map
1)列名是map的key,列值是map的value
2)只能最多返回一行记录,多于一行会发生异常
-->
<select id="selectMapById" resultType="java.util.HashMap">
select id,name from student where id=#{id}
</select>
@Test
public void testSelectMap(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<Object,Object> map = dao.selectMapById(1001);
System.out.println(map);
}
7.2 resultMap的使用
resultMap:可以自定义sql的结果和java对象属性的映射关系,更灵活地把列值赋值给指定属性。常用在列名和java对象属性名不一样的情况。
使用方式:
①先定义resultMap,指定列名和属性名的对象关系;
②在<select>中把resultType替换为resultMap。
/**
* 使用resultMap定义映射关系
*/
List<Student> selectAllStudents();
<!--
使用resultMap
1)先定义resultMap
2)在select标签,使用resultMap来引用1定义的。
-->
<!--
定义resultMap
id:自定义名称,表示你定义的这个resultMap
type:java类型的全限定名称
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!--列名和java属性的关系-->
<!--
主键列,使用id标签
column:列名
property:java类型的属性名
-->
<id column="id" property="id"/>
<!--非主键列使用result-->
<result column="name" property="name"/>
<result column="email" property="email"/>
<result column="age" property="age"/>
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name,email,age from student
</select>
@Test
public void testSelectAllStudents(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectAllStudents();
for(Student student : students){
System.out.println(student);
}
sqlSession.close();
}
7.3 列名和属性名不同的两种解决方式
1.使用resultMap。
2.使用列别名,将别名取为java对象的属性名。
推荐使用第一种方式。
7.4 模糊查询like两种方式
1.在java代码中指定like的内容。(推荐方式)
//第一种模糊查询,在java代码中指定like的内容
List<Student> selectLikeOne(String name);
<!--第一种like,java代码中指定like的内容,推荐这种方式-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like #{name}
</select>
@Test
public void testSelectLikeOne(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectLikeOne("李%");//java代码中指定
for(Student student : students){
System.out.println(student);
}
sqlSession.close();
}
2.在mapper文件中进行字符串拼接。其中#{}两边的空格必须有。
//第二种模糊查询,name就是"李"值,在mapper中拼接 like "%" 李 "%"
List<Student> selectLikeTwo(String name);
<!--第二种like,在mapper文件中拼接like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like "%" #{name} "%"
</select>
@Test
public void testSelectLikeTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectLikeTwo("李");
for(Student student : students){
System.out.println(student);
}
sqlSession.close();
}
PS:根据动力节点课程整理,如有侵权,联系删除。