0%

spring-data

SpringData

按应用场景分

  • 关系数据库:Mysql、PostgreSQL、Oracle、SqlServer、SQLite
  • 键值数据库:Redis、Memcached、LevelDB、RocksDB、Tair、Hbase、Cassandra
  • 文档数据库:MongoDB
  • 图形数据库:Neo4j
  • 时序数据库:OpenTSDB、InfluxDB

按存储方式分

  • 行式存储数据库:Mysql、PostgreSQL、Oracle、SqlServer、SQLite
  • 列式存储数据库:Hbase、Cassandra
  • 键值存储数据库:Redis、Memcached、LevelDB、RocksDB、Tair、Hbase、Cassandra
  • 文档存储数据库:MongoDB
  • 图形存储数据库:Neo4j

SpringMysql

Framework

Jdbc

JdbcUtils

JdbcTemplate

Jpa

Hibernate

JpaTemplate

Mybatis

Basic

SqlSession

核心对象的作用

  • SqlSession:会话,负责抽象的数据库操作和事务
  • Executor:执行器,负责具体的数据库操作和事务,执行sql语句,管理事务和缓存
  • Statement:sql语句
  • Connection:数据库连接,可被复用但同一时刻只能被一个使用者使用

SqlSession的实现类

  • DefaultSqlSession:不是线程安全的
  • SqlSessionManager:是线程安全的
  • SqlSessionTemplate:是线程安全的

ps:SqlSessionManager和SqlSessionTemplate的线程安全是通过ThreadLocal实现的

Mapper

Mapper是数据持久对象(PO),执行多条sql语句,执行sql是通过SqlSession来实现的

ps:Mapper的线程安全取决于SqlSession的线程安全,Mapper使用了SqlSessionTemplate来保证线程安全

Mapper和SqlSession的关系

  • Mapper里的方法执行多条sql时,方法不使用事务时,每条sql都会创建一个SqlSesssion对象
  • Mapper里的方法执行多条sql时,方法使用事务时,多条sql只会创建一个SqlSesssion对象

ps:Mapper获取SqlSession时会先在事务管理器的ThreadLocal里面查找,找不到就创建SqlSession对象使用
ps:有事务时新创建的SqlSession会注册到事务管理器的ThreadLocal中,无事务时不会注册

Usage

Field
id

返回主键方案

  • 数据库支持主键自增时:useGeneratedKeys + keyProperty
  • 数据库不支持主键自增时:selectKey
type
mapping

类的属性名和表的字段名不一样的解决办法

  • 启用下划线转驼峰的配置
  • 在sql中起别名保持一致
  • 使用ResultMap自定义映射
Query

动态 sql 标签

  • <if></if>
  • <choose></choose>(when, otherwise)
  • <foreach></foreach>
  • <where></where>
  • <set></set>
  • <trim></trim>
  • <bind/>
fuzzy(模糊查询)
pagenation(分页查询)

分页查询方案

  • 使用RowBounds来完成内存分页(它是针对ResultSet结果集执行的内存分页,而非物理分页)
  • 直接在sql中写分页条件来完成物理分页
  • 通过分页插件来完成物理分页

ps:分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql语句并改写sql,改写时会根据方言(dialect)添加对应的物理分页条件

reference(关联查询)
  • 一对一查询(selectOne): association + result、association + select
  • 一对多查询(selectOne):collection + result、collection + select
  • 多对一查询(selectMany): association + result、association + select
  • 多对多查询(selectMany):collection + result、collection + select

ps:result方式是连接查询,需要在sql中进行join
ps:select方式是分步查询,不需要在sql中进行join
ps: 多对一 本质上还是 一对一多对多 本质上还是 一对多

Param
  • 参数名称
  • 参数个数
    • 单个参数
    • 多个参数
  • 参数类型
    • 基本类型
    • 对象类型
    • 容器类型
      • Map
      • Array/List/Set
Result
Cache

Extend

tkMybatis

ps:insert、update有Selective方法代表插入或者更新非null字段

MybatisPlus
MyBatisFlex

Question

${}和#{}的区别
  • ${}是属性替换符,生成sql时会直接替换成属性的值(不会被转义)
  • #{}是参数占位符,生成sql时会被处理为问号并通过PreparedStatement设置参数执行(会转义)
where中的1=1的作用

为了保证没有筛选条件时sql语句的正确性

Problem

Cache
一级缓存

一级缓存是session范围的

因为一级缓存是session范围的,所以BSession的更新不会使ASession的缓存失效,ASession再次查询时还会读缓存,导致BSession数据的更新读不到

二级缓存

二级缓存是mapper范围的

因为二级缓存是mapper范围的,所以BMapper的更新不会使AMapper的缓存失效,AMapper再次查询时还会读缓存,导致BMapper数据的更新读不到

Transaction

Basic

Usage

  • 编程式事务管理:TransactionTemplate、TransactionManager
  • 声明式事务管理:@Transactional、TransactionProxyFactoryBean
  • 配置式事务管理:Aspectj AOP

Invalid

事务的失效场景

  • 所有AOP失效的场景(例外是事务对protected也不生效)
  • 多线程或者异步调用(事务是线程隔离的)
  • 事务传播方式使用不当

ps:@Transactional是通过AOP实现的,所以失效的场景包含AOP失效的场景

事务不回滚的场景

  • 异常被吞掉了
  • 未指定rollbackFor参数时抛出的异常不是RuntimeException
  • 指定rollbackFor参数时抛出的异常和指定的异常不匹配

Rollback

Propagation

事务传播方式处理的是两个方法之间的事务关系,比如加入当前事务或者新建事务等等

事务传播方式

  • PROPAGATION_REQUIRED:如果当前存在事务就加入当前事务,否则就以新建事务的方式运行
  • PROPAGATION_SUPPORTS:如果当前存在事务就加入当前事务,否则就以非事务的方式运行
  • PROPAGATION_MANDATORY:如果当前存在事务就加入当前事务,否则就抛出异常
  • PROPAGATION_REQUIRES_NEW:以新建事务的方式运行,如果当前存在事务就挂起当前事务
  • PROPAGATION_NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务就挂起当前事务
  • PROPAGATION_NEVER:以非事务的方式运行,如果当前存在事务就抛出异常
  • PROPAGATION_NESTED:如果当前存在事务就开启嵌套事务运行,否则就新建事务运行

ps:传播方式为PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED时如果存在当前事务,当前事务会被挂起
ps:传播方式为PROPAGATION_NESTED时嵌套事务回滚不会影响主事务,但主事务回滚会将嵌套事务一起回滚了

事务传播处理

  • 当前事务存在时
    • 加入当前事务
    • 挂起当前事务
    • 抛出异常
  • 当前事务不存在时
    • 新建事务
    • 非事务
    • 抛出异常

Question

Spring事务之为什么要加在Service层

Spring事务之到底能不能加到Controller层

Spring事务实现为什么不推荐@Transactional注解

  • 使用不当时事务不会生效,比如同类方法调用等
  • 容易出现长事务问题,占用数据库连接
  • 事务内的非数据库操作不能回滚,会导致不一致的问题

Problem

  • @Transactional + @Async:在事务方法里面调用异步方法时异步方法可能读不到最新的数据(因为事务可能还没有提交)
  • @Transactional + @Retryable:对事务方法进行重试可能读不到最新的数据(因为隔离级别为可重复读时只会在事务启动时生成快照)
  • @Transactional + Lock:锁的提前释放导致锁的作用失效(因为解锁会先于事务提交执行)

Async

事务方法A调用异步方法B会启动另一个事务B(因为事务是线程隔离的),因为事务A和B之间存在隔离性,所以异步方法B执行时,如果事务方法A未结束时是查不到变更的数据的(因为此时事务A还未提交),如果事务方法A已结束是可以查到变更的数据的(因为此时事务A已提交)

Retry

重试如果在事务开始之后可能会不起作用(隔离级别为可重复读时只在事务启动时生成快照)

Lock

解锁如果在事务提交之前可能会导致业务逻辑错误

Exception

SpringCache

Framework

Jedis

Redisson

RedisTemplate

SpringMongoDB

SpringElasticsearch

只想买包辣条