一、动态代理

使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象,不要自己写实现了

回顾没有动态代理的代码:
StudentDao–Dao层的接口

1
2
3
4
5
6
7
8
9
public interface StudentDao {

//查询student表的所有的教据
List<Student> selectStudent();

//插入方法
int insertStudent(Student student);

}

StudentDaoImpl–Dao层的接口的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class StudentDaoImpl implements StudentDao {

@Override
public List<Student> selectStudent() {
// 使用工具类获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 定义sql语句的唯一标识
String sqlId = "com.apps.dao.StudentDao.selectStudent";
// 查询
List<Student> studentsList = sqlSession.selectList(sqlId);
// 关闭
sqlSession.close();
return studentsList;
}

@Override
public int insertStudent(Student student) {
// 使用工具类获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 定义sql语句的唯一标识
String sqlId = "com.apps.dao.StudentDao.insertStudent";
// 查询
int insert = sqlSession.insert(sqlId, student);
// 提交事物
sqlSession.commit();
// 关闭
sqlSession.close();
// 返回
return insert;
}

}

注意:MyBatisUtils.getSqlSession();是自己定义的工具类用于获取SqlSession对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.apps.utils;

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 java.io.IOException;
import java.io.InputStream;

/**
* @author hk Email:2113438464@qq.com
* @ClassName MyBatisUtils
* @Description : 作用
* @date 2021/4/17
*/
public class MyBatisUtils {

//SqlSessionFactory对象
// SqlSessionFactory : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。
// 在整个项目中,有一个就够用了。
private static SqlSessionFactory factory;

static {
try {
// 1、定义mybatis主配置文件的名称,从类路径的根开始(target/clasess)
String config = "mybatis-config.xml";
// 2、读取这个config表示的文件--mybatis中的一个类, 负责读取主配置文件
InputStream in = Resources.getResourceAsStream(config);
// 3、SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}

// 获取SqlSession对象的方法
public static SqlSession getSqlSession() {
return factory.openSession();
/*
openSession()方法说明:
1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
2. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
*/
}

}

回到我们的StudentDaoImpl–Dao层的接口的实现类,我们看selectStudent()方法,我们通过调用sqlSession对象的selectList方法传入Dao接口的方法全限定名称,这个selectList方法底层就是根据方法全限定名称,获取方法返回值,使用指定的sql语句等。实现这个Dao接口中的方法很麻烦,大部分操作都相同。

所以sqlSession对象给了我们getMapper()方法,传入dao接口.class,获取dao接口的实现类对象,它的底层就是通过反射来实现的,如调用getMapper()方法实现selectStudent()方法时,它会获取这方法的全限定名称,通过全限定名称使用指定的sql语,内部区分调用sqlSession对象的selectList()方法,然后关闭对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class TestStudentDao {

@Test
public void testSelectStudent() {
/*
* 使用mybatis的动态代理机制,使用sqlSession.getMapper(dao接口)
* getMapper()获取dao接口对于的实现类对象
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 传入dao接口的class,获取实现类
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
// 调用studentDao的方法,执行数据库的操作
List<Student> studentList = studentDao.selectStudent();
// 打印
studentList.forEach(student -> System.out.println(student));
}

@Test
public void testInsertStudent() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 反射
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
// 设置参数
Student s = new Student(1005,"小李子","sb@qq.com",33);
// 用studentDao的方法,执行数据库的操作
int i = studentDao.insertStudent(s);
// 提交事物
sqlSession.commit();
// 打印
System.out.println(i);
}

}

不用写dao层实现类,现在只要定义接口,在使用、测试时通过sqlSession.getMapper(接口.class)获取实现类。