MyBatis俩种实现方式:
1:基于Mapper接口的使用方式:
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
User user = new User();
user.setUser_name("abd");
user.setUser_id(99);
user.setPassword("12345");
UserDao userDao = session.getMapper(UserDao.class);
userDao.login(user);
2:直接使用SqlSession
对象来执行SQL语句,也是更底层和更早期的MyBatis使用方式。
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
User user = new User();
user.setUser_name("abd");
user.setUser_id(99);
user.setPassword("12345");
//另一种更底层也是更早期的执行方式
//前面一个参数是namespace(Mapper接口接口类全限定名).标签id名,后面一个参数是SQL执行所需参数
session.insert("com.example.spring_suns.Dao.UserDao.login",user);
对俩种实现方式进行分析:
事实上,第一种执行方式就是使用代理模式对第二种执行方式的封装(为了提升代码的可读性和可维护性)。
代理模式三种应用场景:
1:给原始对象增加额外功能
2:远程代理(网络通信,输出传输(RPC,Dubbo))
3:无中生有,看不见类文件,却能进行使用(比如MyBatis中使用Mapper接口的实现类)
我们在使用Mapper接口时,并没有对其进行实现,却能进行使用,调用其方法,就是MyBatis内部通过代理调用了SqlSession封装的数据库操作。
具体代理过程:
MyBatis代理Mapper接口实现主要通过俩个类:MapperProxyFactory和MapperProxy
MapperProxyFactory:
MapperProxyFactory调用JDK动态代理的Proxy.newProxyInstance方法:
MapperProxy继承Invocation实现Invoke方法,Invoke方法调用上述MyBatis第二种实现方式的MapperMethod的各种方法:
查看其内部调用的invoke方法:
执行SqlSession的对应操作(调用上述第二种MyBatis实现方式)
由此印证了MyBatis使用代理进行封装的整个底层逻辑
自定义实现上述通过代理封装sqlSession数据库操作的过程:
public class SelfMapperProxy {
@Test
void myMapperProxy() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
Class[] classes = new Class[]{UserDao.class};
//动态代理
UserDao userdao = (UserDao)Proxy.newProxyInstance(SelfMapperProxy.class.getClassLoader()
,classes,new SelfHandler(session,UserDao.class));
//通过Mapper接口调用对应方法
User user = new User();
user.setUser_name("abd");
user.setUser_id(99);
user.setPassword("12345");
userdao.login(user);
}
}
public class SelfHandler implements InvocationHandler {
private SqlSession session;
private Class daoClass;
public SelfHandler(SqlSession session, Class daoClass) {
this.session = session;
this.daoClass = daoClass;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用SqlSession数据库操作
return session.insert(daoClass.getName() + "." + method.getName());
}
}