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 对象,以确保线程安全。

上一篇 python标准库math用法精要
下一篇 数据结构之队列的使用(附面试题)

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: