当前位置: 首页 > 图灵资讯 > 技术篇> Mybatis框架学习&&总结

Mybatis框架学习&&总结

来源:图灵教育
时间:2023-06-12 09:20:41

SqlSession

它是Mybatis的顶层接口,它实现了所有的数据库操作。SqlSession对应数据库会话,每次访问都需要创建

在serviceimpl方法中,maper要求两个数据库创建两个sqlsesion

使用SqlSession

// 加载 MyBatis Stringg配置文件 resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession session = sqlSessionFactory.openSession()// 获取 UserMapper Usermaperperper userMapper = session.getMapper(UserMapper.class);// 调用usermapper.save(user);

一级缓存

默认开启是session级别,作用域是sqlsession级别

需要添加事务,每次查询都会创建SqlSession,一级缓存会失效

例如,在同一个serviceimpl的同一方法中执行两次相同的句子basemapper.selectById("1547463041121574914");baseMapper.selectById("1547463041121574914");如果加了@Transactional(rollbackFor = Exception.class)sql只执行一次注释,第二次是使用一级缓存。如果没有添加,也没有事务,执行sql提交一次。每次都会创建sqlsesion,不会使用一级缓存

二级缓存

默认打开,作用域是namespace,还需要mapper.打开xml.

作用于namespace,仔细打开多个sqlsession共享,直接通过navicat等工具手动修改数据库 或者 使用其他mapper修改数据库,第二次获得的仍然是缓存数据。使用其他mapper是指 使用rolemaperperp 修改 user表,userMaper的二级缓存不会失效,因为它是多个sqlsession共享,所以添加事务注释是不可避免的

打开二级缓存:启动类加@EnableCaching对应的mapper @cachenamespaceyml配置mybatistis-plus:  configuration:    # 打开二次缓存    cache-enabled: true

例如,在同一serviceimpl的不同方法中执行相同的句子 public Object select1() {        baseMapper.selectById("1547463041121574914");        return null; }  public Object select2() {        baseMapper.selectById("1547463041121574914");        return null; } 二级缓存将在select2中命中语句,不检查数据库

查询优先级

二级缓存 -> 一级缓存 -> 数据库 查询任何链接中不空的数据,直接返回

缓存失效

updatete发生在缓存作用域 insert delete后,将触发缓存故障,下次查询将直接查看数据库

JDK动态代理

运行时将1.SqlSession 通过getmapper(Class<T>type)获取Mapper接口的代理对象2.DefaultSqlSession 的 getMapper(Class<T>type) 会调用 Configuration 的 getMapper(Class<T> type, SqlSession sqlSession) 第二个参数 SqlSession 也就是调用时会 this 传入了3.Configuration 的 getMapper(Class<T> type, SqlSession sqlSession) 会调用 MapperRegistry 的 getMapper(Class<T> type, SqlSession sqlSession)4.MapperRegistry 的 getMapper(Class<T> type, SqlSession sqlSession) 通过映射表 knownMappers 根据接口类型获取相应的对应类型 MapperProxyFactory 工厂类5.MapperProxyFactory 工厂类,调用 newInstance(SqlSession sqlSession) 创建 Mapper 接口代理对象 MapperProxy, MapperProxy 继承了 Invocationdler6.MapperProxyFactory 工厂类重新调用 newInstance(MapperProxy<T> mapperProxy) 将 MapperProxy 传给 Proxy.newProxyInstance 生成接口代理对象(例如:UserService)(sqlsession在这里完成.getMapper();方法7.调用代理对象 Mapper 方法时(userService.add()),会委托给 MapperProxy 类的 invoke() 方法处理。invoke() 该方法将根据该方法签名以查找相应的方法 MapperMethodInvoker 对象和执行方法8.MapperMethodInvoker 通过分析对象 Mapper 构建接口方法的参数、返回值和注释信息,用于执行 Mapper 工具类的方法

MapperRegistry 是 MyBatis 其中一份注册表用于保存 Mapper 接口类型及对应 MapperProxyFactory 工厂之间的映射关系

MapperProxyFactory 在Mybatis初始化时创建并注册 Configuration 在对象中,每个mapper接口对应一个 MapperProxyFactory .创建代理工厂是一个代理工厂 Mapper 当我们调用接口的代理对象时 Mapper 接口方法时,代理对象将拦截此方法并将其转发给底层 SqlSession 对象,SqlSession 对象负责与数据库互动并执行相应的数据库 SQL 句子,从而完成数据读取、更新等操作。

MapperProxy 实现了 JDK 动态代理的 InvocationHandler 接口,其实例对象被传递给 Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 创建一个方法 Mapper 接口代理对象。调用客户端时 Mapper 接口中的方法实际上是通过的 MapperProxy 的 invoke 该方法用于处理方法调用,该方法将调用信息包装成 MappedStatement 并将参数交给底层 SqlSession 来执行

在 MyBatis 中,每个 Mapper 对应一个 MapperProxyFactory 对象,MapperProxyFactory 会为每个 Mapper 接口创建代理对象。

MapperMethodInvoker 通过分析对象 Mapper 由于界面方法的参数、返回值和注释,构建了界面方法 Mapper 方法的参数、返回值和注释通常是不变的,因此 MapperMethodInvoker 缓存可以提高后续同名方法的执行效率。

cachedInvoker() 方法会将 MapperMethodInvoker 缓存对象,避免重新分析参数、返回值和每个执行方法的注释。MyBatis 内部使用了一个 ConcurrentHashMap 缓存 MapperMethodInvoker 对象,以确保线程安全。