MyBatis的动态代理
MyBatis根据dao的方法调用,获取执行sql语句的信息
MyBatis根据你的dao接口,创建一个dao接口的实现类,并创建这个类的对象
完成SqlSession调用方法,访问数据库
即自己不用再编写实现类了
动态代理的实现
使用SqlSession.getMapper(dao接口.java)获取这个dao接口的对象
对于MyBatis学习(二)最后的项目 进行复制 并改造
复制后导入idea
添加文件路劲进行导入
将文件导入后,修改pom.xml中文件名,修改为和复制后的新项目名(proxyDao)相同
删除接口的实现类文件,删除text中的测试文件,删除target文件,对myapp进行修改
修改myapp后如下
package ys;
import org.apache.ibatis.session.SqlSession;
import ys.dao.StudentDao;
import ys.domain.Student;
import ys.utils.mybatisclass;
import java.util.List;
public class myapp {
public static void main(String[] args) {
// 使用MyBatis动态代理机制,使用SqlSession.getMapper(接口)
// getMapper能获取dao接口对于的实现类对象
SqlSession sqlSession = mybatisclass.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student=new Student();
// 选择添加数据
student.setName("刘备");
student.setEmail("48979.189");
student.setId(8);
student.setAge(45);
// 调用dao方法执行添加数据操作
int nums= dao.insertStudent(student);
// 调用dao 的方法执行查询数据库的操作
List<Student> students =dao.selectStudents();
for (Student stu: students){
System.out.println("学生="+stu);
}
}
}
传参(从java文件将参数传到sql映射文件(mapper文件))
使得sql语句更加灵活,功能更加丰富
1.parameterType:
写在mapper文件中的一个属性,表示dao接口中方法的参数的数据类型。
例如StudentDao接口
public Student selectStudentById(Integer id)
2. 一个简单类型的参数及传参:
简单类型:mybatis把java的基本数据类型和String类型都叫简单类型
在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
基本原理机制(了解)
使用#{ }之后,mybatis执行sql是使用的jdbc中的PreparedStatement对象(自动创建执行)
由mybatis执行下列代码:
//1.mybatis创建Connection ,PreparedStatement对象
String sql="select name,id,age,email from Student where id=?";
PreparedStatement pst = conn.PreparedStatement(sql);
pst.setInt(1,1001);
//2.执行sql封装resultType="ys.domian.Student" 这个对象
ResultSet rs =ps.executeQuery();
Student student =null;
while(rs.next()){
//从数据库取表的一行数据,存到一个java对象属性中
student =new Student();
student.setId(rs.getInt("id");
student.setName(rs.getString("name");
student.setEmail(rs.getString("email");
student.setAge(rs.getInt("age");
}
return student;//把student这个返回值给了dao方法调用的返回值
多个参数传参--按位置传参 (了解)
参数位置从0开始,引用参数语法#{arg位置},第一个参数是#{arg0},第二个是#{arg1}
需要注意的是mybatis-3.3版本及以前的版本用#{0},#{1}的方式,从mybatis开始使用#{arg0}的方式
多个参数传参--使用@Param(掌握)
当Dao接口方法有多个参数时,需要通过名称使用参数,在方法形参前面加入@Param("自定义参数名"),mapper文件使用#{自定义参数名}
多个参数传参--使用java对象属性值作为参数实际值(掌握)
创建一个java实体类,并在接口中定义方法用java类作为类型,进行传值
多个参数传参--使用Map(了解)
Map集合可以存储多个值,使用Map向mapper文件一次传入多个参数。Map集合使用String的key,Object类型的值存储参数,mapper文件使用#{key}引用参数值
实例----各种方法传参的实际应用
将proxyDao项目进行复制,命名为param,修改pom.xml文件中的名字,改为与项目名相同
在接口中定义新的方法(StudentDao.java)
package ys.dao;
import org.apache.ibatis.annotations.Param;
import ys.domain.QueryParam;
import ys.domain.Student;
import java.util.List;
import java.util.Map;
public interface StudentDao {
/**
* 一个简单类型的参数:
* 简单类型:mybatis把java的基本数据类型和String类型都叫简单类型
*
* 在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
* */
// 一个简单类型参数传参
public Student selectStudentById(Integer id);
// 多个参数按位置传参
List<Student> selectByNameAndAge(String name,int age);
// 使用@Param多参数传参
List<Student> selectMultiParam(@Param("personName")String name,
@Param("personAge")int age);
//使用java对象的属性值,作为参数实际值
List<Student> selectMultiObject(QueryParam param);
// 使用Map多参数传值
List<Student> selectMap(Map<String,Object> map);
// 使用$占位符
List<Student> select$(@Param("personSName")String name);
//使用$占位符 替换类名
List<Student> select$order(@Param("VSName")String name);
}
sql映射文件(StudentDao.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="ys.dao.StudentDao">
<!-- parameterType 用来表dao接口中方法参数的数据类型
parameterType它的值是java数据类型的全限定名称或者mybatis定义的别名(mybatis文档中它的定义的)
例如 parameterType="java.lang.Integer
parameterType="int"
不是强制必须写入parameterType,可以不用写
mybatis可以通过反射机制能够发现接口参数的数类型 所以大多数时候我们都不写-->
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="ys.domain.Student">
select name,id,age,email from Student where id=#{id}
</select>
<select id="selectByNameAndAge" resultType="ys.domain.Student">
select name,id,age,email from Student where name=#{arg0} and age=#{arg1}
</select>
<select id="selectMultiParam" resultType="ys.domain.Student">
select name,id,age,email from Student where name=#{personName} or age=#{personAge}
</select>
<!-- 使用java对象的属性值,作为参数实际值
使用对象语法:#{属性名,javaType=类型名称,jdbcType=数据类型 -完整格式(但一般不怎么写)
javaType:指java中的属性数据类型
jdbcType:在数据库中的数类型
例如:#{SName,javaType=java.lang.String,jdbcType=VARCHAR}
常用语法:#{属性名} javaType,jdbcType的值通过mybatis反射能获取,不用提供
-->
<select id="selectMultiObject" resultType="ys.domain.Student">
select name,id,age,email from Student where name=#{SName} or age=#{SAge}
</select>
<!-- Map 多参数传参-->
<select id="selectMap" resultType="ys.domain.Student">
select name,id,age,email from Student where name=#{myName} or age=#{myAge}
</select>
<!-- 使用$占位符-->
<select id="select$" resultType="ys.domain.Student">
select name,id,age,email from Student where name=${personSName}
</select>
<!-- 使用$替换列表名-->
<select id="select$order" resultType="ys.domain.Student">
select * from Student order by ${VSName}
</select>
</mapper>
主方法( myapp.java)
package ys;
import org.apache.ibatis.session.SqlSession;
import ys.dao.StudentDao;
import ys.domain.QueryParam;
import ys.domain.Student;
import ys.utils.mybatisclass;
import java.util.*;
public class myapp {
public static void main(String[] args) {
// 从键盘获取一个值
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要查询的学生id:");
// 从键盘获取值,取出int类型的值赋值给number(意味着只有int类型的值能被获取)
int number = scanner.nextInt();
// 使用MyBatis动态代理机制,使用SqlSession.getMapper(接口)
// getMapper能获取dao接口对于的实现类对象
SqlSession sqlSession = mybatisclass.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
// 调用dao 的方法执行查询数据库的操作 单参数传递
Student students =dao.selectStudentById(number);
System.out.println("学生="+students);
// 调用dao的方法执行查询操作 多参数传值--按位置传参
List<Student> students1=dao.selectByNameAndAge("刘备",45);
students1.forEach(student -> System.out.println(student));
// 调用dao的方法进行查询 多参数传值--@Param
List<Student> students2=dao.selectMultiParam("张三",45);
students2.forEach(stu -> System.out.println(stu));
// 设置java属性值
QueryParam queryParam=new QueryParam();
queryParam.setSAge(45);
queryParam.setSName("隆");
// 调用dao方法进行查询,java对象属性值作为参数实际值 (多参数传值一种)
List<Student> students3=dao.selectMultiObject(queryParam);
students3.forEach(student -> System.out.println(student) );
// 使用Map集合进行多参数传参
Map<String,Object> data=new HashMap<>();
// 往Map集合写值
data.put("myName","隆");
data.put("myAge",20);
List<Student> students4=dao.selectMap(data);
students4.forEach(student -> System.out.println(student));
// 使用$占位符
List<Student> students5=dao.select$("'张三'");
students5.forEach(student -> System.out.println(student));
// 使用$进行列表名的替换
List<Student> students6 =dao.select$order("'id'");
students6.forEach(student -> System.out.println(student));
}
}
#和$(掌握)
#:占位符,告诉mybatis使用实际的参数值代替,并使用PrepareStatement对象执行sql语句,#{}代替sql语句中的“?”。这样更安全,更迅速,通常也是用这个。
select id,name,email,age from Studnet where name=#{name}
// 结果是 select id,name,email,age from Studnet where name=?
// 然后用#{} 的值代替?
$:字符串替换,告诉mybatis使用$包含的“字符串”替换所在位置,使用Statement把sql语句和${}
的内容连接起来,主要用在替换列表名,列名,不同排序等操作,效率比#{}低,容易出现问题。
select id,name,email,age from Studnet where name=${name}
//select id,name,email,age from Studnet where name=""+"刘备"
//${}直接连接在语句上
封装MyBatis输出结果
resultType(返回类型和接口方法的类型的全限定名称是相同的)
执行sql语句得到ResultSet转换的类型,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。resultType和resultMap不能同时使用。
<select id="selectStudentById" resultType="ys.domain.Student">
select name,id,age,email from Student
</select>
resultType是返回的类型,不一定是实体类,可以是任意java类 。原理是指将查询的表的值赋给resultType值中的类中的同名属性
resultType可以返回简单类型
//查询语句
<select id="selectCount" resultType="int"> // 也可以写作resultType="java.long.Integer"(全限定名称)
select count(*) from Student
</select>
//接口方法
int selectCount();
定义别名
在resources文件下的主配置文件中定义
<typeAliases>
//可以指定一个类型一个自定义别名.
//type:自定义类型的全限定名称
//alias:自定义的别名(短小,容易记忆)
<typeAlias type="ys.domain.Student" alias="Stu"/>
</typeAliases>
//sql映射文件的写法
<select id="selectByNameAndAge" resultType="Stu">
select name,id,age,email from Student
</select>
<package name="ys.domain">
<package name="ys.dao">
//name 是包名,这个包中的所有类,类名就是别名(类名不区分大小写)
//在sql映射文件中的写法
<select id="selectByNameAndAge" resultType="Student"> //类名即别名
select name,id,age,email from Student
</select>
查询返回Map
返回map 列名作为key值,列值是value 一一对应
使用map作为返回值 最多返回一行 多行数据会报错
//使用Map作为返回值 -----接口方法
Map<Object,Object> selectObject(Integer id);
//map的全限定名称java.util.HashMap----sql映射文件
<select id="selectObject" resultType="java.util.HashMap">
select id,name from Student where id=#{stu}
</select>
//查询返回map---主方法 mybatisclass.getSqlSession()---工具类封装的方法
SqlSession sqlSession = mybatisclass.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<Object,Object> map =dao.selectObject(1);
System.out.println(map);
resultMap(结果映射)
resultMap可以自定义sql的结果和java对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和java对象属性名不一样的情况
什么时候使用:
1.你自定义列值赋值给哪个属性
2.当你的列名和属性名不一样时,一定要使用resultMap
使用方式:
1.先定义resultMap,指定列名和属性的对应关系
2.在<select>中吧resultType换成resultMap
// resultMap的用法---接口方法
List<Student> selectResultMap();
//sql映射文件写入的内容
<!-- 使用resultMap定义映射关系-->
<!-- 创建resultMap id:自定义的唯一名称 在<select>中使用 type:期望转为java对象的全限定名称或别名-->
<!-- 主键字段使用id 非主键字段使用result-->
<!-- column:列名 property:java属性名-->
<resultMap id="studentMap" type="ys.domain.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="email" property="email"/>
<result column="age" property="age"/>
</resultMap>
<!-- id同样是接口方法名,resultType被resultMap替换,值为之前定义的id值 -->
<select id="selectResultMap" resultMap="studentMap">
select id,name,email,age from Student
</select>
//主方法
List<Student> students7=dao.selectResultMap();
students7.forEach(student -> System.out.println(student));
对于列名与java对象属性名不同时
采用resultMap进行sql语句
// resultMap的用法---接口方法
List<StudentMap> selectResultStudent();
//sql映射文件写入的内容
<resultMap id="studentResultMap" type="ys.domain.StudentMap">
<id column="id" property="stuid"/>
<result column="name" property="stuname"/>
<result column="email" property="stuemail"/>
<result column="age" property="stuage"/>
</resultMap>
<select id="selectResultStudent" resultMap="studentResultMap">
select id,name,email,age from Student
</select>
//主方法
List<Student> students8=dao.selectResultStudent();
students8.forEach(student -> System.out.println(student));
对列表进行命名别名
<select id="ResultStudent" resultType="ys.domain.StudentMap">
select id as stuid,name as stuname ,email as stuemail ,age as stuage from StudentMap
</select>
模糊查询like
1. 方法一
在java代码指定like的内容
// 模糊查询like的用法
List<Student> selectLike(String name);
//sql映射文件----#{} 简单参数传参
<select id="selectLike" resultType="ys.domain.Student">
select * from Student where name like #{name}
</select>
// Like 模糊查询 用法 -----主方法
String name="%张%";
List<Student> students8=dao.selectLike(name);
// List<Student> students8=dao.selectLike("%张%"); 作用与前面两句相同
students8.forEach(student -> System.out.println(student));
2.方法二
在sql映射文件中拼接like内容
// 模糊查询like的用法
List<Student> selectLike2(String name);
//sql映射文件----#{} 简单参数传参
<select id="selectLike2" resultType="ys.domain.Student">
select * from Student where name like "%" #{name} "%"
</select>
// Like 模糊查询 用法 -----主方法
String name="张";
List<Student> students9=dao.selectLike2(name);
students9.forEach(student -> System.out.println(student));