学习日记-spring-day47-9.1
知识点:
1.jdbctemplate-查询后封装成对象集合
知识点 | 核心内容 | 重点 |
API调用方法 | 使用query方法查询并封装多个结果对象,返回List<Monster>集合 | queryForObject(单结果)与query(多结果)的区别 |
SQL参数化查询 | 通过?占位符动态传入参数(如ID > ?),避免SQL拼接风险 | 参数绑定与直接拼接SQL的安全性差异 |
RowMapper复用 | 相同实体类(Monster)的映射逻辑可直接复用RowMapper实现 | 不同查询结果复用同一映射器的前提条件 |
集合结果处理 | 遍历List<Monster>输出查询结果,适用于非唯一性条件查询 | 单结果(Optional)与多结果(List)的适用场景对比 |
JDBC Template核心方法 | query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)的参数结构 | 方法重载(带参数/不带参数)的选择依据 |
2.jdbctemplate-返回单行单列
知识点 | 核心内容 | 重点 |
JDBC单行单列查询 | 使用queryForObject方法查询单行单列数据(如count、特定字段值) | 返回值类型需匹配(如String/Integer/Double) |
SQL语句构造 | SELECT name FROM monster WHERE id=100(参数可动态化) | 硬编码vs参数化查询的安全性差异 |
API选择逻辑 | 通过方法签名推断适用API(queryForObject vs 返回集合的query) | 方法重载场景的区分 |
类型映射 | 需显式声明返回值类型(如String.class/Integer.class) | 基本类型与包装类的选择 |
扩展应用 | 统计查询(SELECT COUNT(*))同样适用单行单列模式 | 聚合函数与类型声明的关联 |
3.jdbctemplate-具名参数
知识点 | 核心内容 | 重点 |
句名参数 | 使用具名参数替代问号占位符,通过参数名称明确对应关系 | 与传统问号参数的区别及优势 |
NamedParameterJdbcTemplate配置 | 需通过构造器注入数据源创建专用模板对象 | 与普通JdbcTemplate的配置差异 |
参数Map构建 | 使用HashMap<String,Object>存储具名参数键值对 | 键名必须与SQL中的参数占位符严格匹配 |
update方法调用 | 通过namedParameterJdbcTemplate.update(sql, paramMap)执行操作 | 返回值仍为受影响行数 |
SQL语句规范 | 参数占位符格式为:paramName(冒号+参数名) | 与问号占位符语法对比 |
实战演示 | 添加蚂蚁精记录(ID:800, name:"蚂蚁精", skill:"喜欢打洞") | 参数映射关系验证 |
4.jdbctemplate-sqlparametersoruce
知识点 | 核心内容 | 重点 |
SQL parameter source用法 | 使用MapPropertySqlParameterSource封装具名参数 | 参数名必须与对象属性名严格匹配 |
参数绑定机制 | 通过对象属性自动绑定SQL参数 | 对象属性名(monsterID)与SQL参数名(ID)不一致导致错误 |
批量操作API | NamedParameterJdbcTemplate.update()方法支持批量处理 | 需使用SqlParameterSource的数组形式 |
错误排查方法 | 根据No value supplied错误提示定位参数绑定问题 | 属性命名规范一致性检查 |
API使用思想 | 通过接口实现类(MapPropertySqlParameterSource)完成功能 | 需掌握Ctrl+B查看接口实现类的技巧 |
5.DAO使用jdbctemplate
知识点 | 核心内容 | 重点 |
JDBC Template常用方法 | select、insert、delete、update等方法的用法 | 掌握各方法的使用场景和参数组织方式 |
使用JDBC Template操作数据库 | 在dao对象中使用JDBC Template完成数据库操作 | 如何将JDBC Template注入到dao对象,并调用相应方法进行数据库操作 |
创建dao类和保存任务 | 创建一个dao类,并编写保存任务的方法 | 如何注入JDBC Template,并组织SQL语句进行保存操作 |
配置扫描包 | 需要配置扫描包,才能将dao类扫描进Spring容器 | 忘记配置扫描包会导致dao类无法被Spring容器管理 |
注意事项 | 1. 保证dao类能够获取到; 2. 检查容器中是否配置了要扫描的包 | 1. dao类获取不到; 2. 未配置扫描包导致dao类无法使用 |
6.事务分类简述
知识点 | 核心内容 | 重点 |
事务分类 | 编程式事务 vs 声明式事务 | 编程式事务手动控制提交/回滚 vs 声明式事务基于AOP自动管理 |
编程式事务流程 | 1. 获取Connection 2. 关闭自动提交 3. 执行CRUD 4. 提交/异常回滚 | setAutoCommit(false) 与 rollback() 的调用时机 |
声明式事务原理 | 基于Spring AOP实现,通过注解或配置简化事务管理 | 与AOP的关联(如环绕通知处理提交/回滚) |
案例对比 | 以商品购买系统演示声明式事务的实际应用 | 编程式事务代码冗余 vs 声明式事务解耦业务逻辑 |
7.声明式事务实例(1)
知识点 | 核心内容 | 重点 |
声明式事务原理 | 通过AOP机制实现事务管理,将业务逻辑与事务控制分离 | 动态代理实现原理 vs 传统编程式事务 |
事务一致性场景 | 用户购买商品涉及三表操作: 商品表查询→用户表扣款→库存表减量 | 余额扣除成功但库存未减的典型不一致案例 |
编程式事务实现 | 手动控制Connection的autoCommit属性,集中编写SQL语句 | 代码冗余问题 vs 事务边界控制优势 |
声明式事务优势 | 方法级事务组装:m1+m2或m2+m3可灵活组合新事务 | AOP动态绑定机制实现业务解耦 |
事务控制要素 | 必须同时满足的原子操作:SELECT查询→UPDATE余额→UPDATE库存 | 单个SQL成功但整体失败的异常处理 |
8.声明式事务实例(2)
知识点 | 核心内容 | 重点 |
声明式事务实现 | 通过创建用户表、商品表、库存表及GoodsDAO类演示事务操作 | 表关联关系(用户余额与商品库存的同步修改) |
JDBC Template应用 | queryForObject()查询价格、update()修改余额/库存 | 参数绑定顺序(SQL问号与实际参数的对应关系) |
DAO层方法设计 | queryPriceById()、updateBalance()、updateStock() | 方法命名与实际功能的一致性(减少操作而非单纯修改) |
测试流程 | 先验证表结构创建,再测试DAO方法有效性 | 确保测试数据一致性(如用户初始余额1000/2000) |
9.声明式事务实例(3)
知识点 | 核心内容 | 重点 |
Spring容器配置 | 使用context:component-scan扫描包实现自动注入 | XML配置与注解扫描的配合使用 |
JDBC Template集成 | 数据源配置与JDBC Template对象创建 | 外部属性文件引用与对象依赖关系 |
DAO层方法测试 | queryPriceById/updateBalance/updateAmount方法验证 | float类型参数传递规范(需加f后缀) |
事务管理基础 | 通过Service层整合多个DAO操作 | 方法调用链的事务边界控制 |
依赖注入实践 | @Autowired实现GoodsDAO注入 | 多模块开发时的包路径混淆问题 |
单元测试规范 | JUnit测试框架结合Spring容器测试 | 测试数据准备与断言验证 |
类型转换要点 | float/double数值类型处理 | 隐式类型转换的编译错误规避 |
配置复用技巧 | JDBC配置跨文件复用 | 多环境配置的兼容性处理 |
10.声明式事务实例(4)
知识点 | 核心内容 | 重点 |
事务管理 | 演示不使用事务导致的数据不一致问题 | 部分SQL成功部分失败导致数据不一致 |
分层架构 | Service层调用DAO层完成商品购买业务 | 依赖注入顺序:Service→DAO→JDBC Template |
方法设计 | buyGoods()方法参数设计(userId/goodsId/amount) | 参数验证在实际开发中的必要性 |
SQL调试 | 通过输出购买信息辅助调试 | 未处理异常时的数据不一致现象 |
包扫描配置 | Spring容器扫描范围配置方案对比 | 精准扫描(dao+service) vs 父包扫描(tx.*) |
事务原子性 | 多个数据库操作应视为整体事务 | 要么全部成功,要么全部回滚 |
11.声明式事务实例(5)
知识点 | 核心内容 | 重点 |
声明式事务管理 | 使用@Transactional注解标记方法,使方法内的数据库操作作为一个原子性事务(全部成功或全部失败) | 注解需配合事务管理器配置,仅加注解不生效 |
事务管理器配置 | 需定义DataSourceTransactionManager bean,并指定关联的数据源(与JDBC Template一致) | 数据源必须一致,否则事务控制失效 |
启用注解驱动 | 需在配置中添加<tx:annotation-driven>标签,并指定事务管理器 | 需注意选择tx命名空间标签(非其他功能标签) |
事务控制验证 | 通过模拟异常场景(如SQL错误)验证数据一致性(余额与库存同时回滚) | 部分成功场景是常见测试用例 |
源码机制 | 事务管理器通过数据源连接控制提交/回滚,@Transactional由AOP代理实现 | Debug源码可观察代理类生成过程 |
12.声明式事务实例(6)
知识点 | 核心内容 | 重点 |
事务管理器工作原理 | DataSourceTransactionManager 的核心作用与配置方法 | 数据源连接与事务控制的关系 |
doBegin方法机制 | 将autoCommit设为FALSE实现手动提交控制 | 默认true与手动false的区别 |
事务提交流程 | doCommit方法在无异常时执行connection.commit() | 提交时机与业务方法执行顺序 |
回滚触发条件 | doRollback方法在异常时执行connection.rollback() | 异常类型与回滚范围 |
AOP动态代理实现 | 通过前置通知(doBegin)、返回通知(doCommit)、异常通知(doRollback)实现事务控制 | 代理对象调用流程与原生代码区别 |
声明式事务优势 | @Transactional注解替代编程式try-catch代码块 | 注解生效条件与配置要求 |
事务隔离级别验证 | 通过debug观察connection.isolationLevel变化 | 不同隔离级别的并发问题表现 |
连接池代理对象 | 通过getConnection()获取的实际是代理连接 | 原生连接与代理连接的方法拦截差异 |
13.事务传播机制问题
知识点 | 核心内容 | 重点 |
声明式事务传播机制 | 多个事务方法嵌套调用时的控制规则(如外层事务管理内层事务的提交/回滚) | 嵌套事务的独立性判断(是否受外层事务接管) |
事务传播场景案例 | multiTxTest方法(事务)调用buyGoods1和buyGoods2(均为事务方法) | 方法间事务边界划分(默认机制 vs 显式配置) |
传播机制核心问题 | 嵌套事务的归属管理(如f1和f2是否独立于外层事务f) | 传播行为类型(REQUIRED/NEW/NESTED等) |
14.事务传播机制种类介绍
知识点 | 核心内容 | 重点 |
事务传播机制种类 | 介绍事务传播属性的七种类型,重点前两种:required和requires new | required vs requires new的区别 |
required传播属性 | 如果当前有事务运行,则在当前事务内执行;否则启动新事务 | 嵌套事务是否回滚取决于外层事务 |
requires new传播属性 | 无论当前是否有事务,都启动新事务,并挂起现有事务(若存在) | 嵌套事务独立提交/回滚,互不影响 |
事务传播示例(required) | f1和f2方法若均使用required,则被统一管理,任一失败整体回滚 | 嵌套事务的原子性表现 |
事务传播示例(requires new) | f1和f2方法若使用requires new,则各自独立,失败互不影响 | 独立事务的隔离性实现 |
15.事务传播机制图解
知识点 | 核心内容 | 重点 |
事务传播机制(Required) | 默认传播机制,若外部方法已开启事务,则内部方法加入同一事务;若外部无事务,则新建独立事务。 | 整体事务管理:内部方法(如f1、f2)失败会导致外部事务整体回滚。 |
事务传播机制(Requires New) | 强制新建独立事务,挂起外部事务;内部方法事务与外部完全隔离,互不影响。 | 独立性:f2成功但f3失败时,仅回滚f3的事务。 |
传播属性指定方法 | 通过@Transactional(propagation=Propagation.REQUIRED/NEW)注解显式声明。 | 易忽略点:默认不写propagation即为REQUIRED。 |
其他传播属性 | SUPPORTS/NOT_SUPPORTED/MANDATORY/NEVER等,仅需了解,开发中较少使用。 | 区分MANDATORY(强制要求外部事务)与NEVER(禁止外部事务)。 |
图示解析 | 通过嵌套方法调用(如f1→f2→f3)对比REQUIRED(统一事务)与REQUIRES_NEW(独立事务)的执行流程。 | 关键差异:REQUIRES_NEW会挂起外部事务并创建新事务上下文。 |
16.事务传播机制应用实例
知识点 | 核心内容 | 重点 |
事务传播机制 | 通过商品购买案例演示事务传播机制的控制逻辑,重点分析REQUIRED和REQUIRES_NEW两种传播属性的差异 | REQUIRED默认机制下多个方法会合并为同一事务(整体回滚),REQUIRES_NEW会创建独立事务(互不影响) |
声明式事务实现 | 使用@Transactional注解标记方法,通过修改propagation属性控制传播行为 | 需区分方法调用层级与事务嵌套关系,避免混淆传播属性的生效范围 |
事务回滚验证 | 通过故意修改SQL语句触发异常,观察不同传播机制下的数据回滚效果 | 重点验证:REQUIRED会连带回滚已成功的操作,REQUIRES_NEW仅回滚当前失败方法 |
环境搭建技巧 | 复制多套DAO/Service方法(如queryPriceById2、updateBalance2)以隔离测试场景 | 需保持方法功能一致性,仅通过后缀区分不同事务控制逻辑 |
其他传播属性 | SUPPORTS/NOT_SUPPORTED等机制 | 注意MANDATORY(强制存在事务)与NEVER(强制无事务)的互斥性 |
17.事务隔离级别说明
知识点 | 核心内容 | 重点 |
事务隔离级别基本概念 | 介绍事务隔离级别的定义及四种类型(读未提交、读已提交、可重复读、可串行化) | 隔离级别的增强顺序及区别 |
Spring声明式事务默认隔离级别 | 默认使用底层数据库(如MySQL)的隔离级别(REPEATABLE READ) | Isolation.DEFAULT源码解析:与数据库默认级别同步 |
MySQL默认隔离级别查询方法 | SELECT @@global.tx_isolation 返回当前数据库隔离级别(示例结果为REPEATABLE READ) | 实际开发中需明确数据库配置 |
可重复读隔离级别特性 | 事务未结束前读取的数据始终一致,其他事务提交的修改不可见 | 易混淆点:与“读已提交”的可见性差异 |
源码追踪与验证 | 通过Spring Isolation 枚举类分析默认隔离级别逻辑 | 关键代码:@Transactional(isolation = Isolation.DEFAULT) |
18.事务隔离级别应用实例(1)
知识点 | 核心内容 | 重点 |
事务隔离级别设置 | 演示默认隔离级别为REPEATABLE_READ的可重复读特性 | 默认隔离级别与自动提交的区别 |
声明式事务测试方法 | 通过GoodsService类中的buyGoodsByTxIsolation方法进行测试 | 事务注解@Transactional的使用方式 |
可重复读隔离级别验证 | 在事务中两次查询同一数据,即使外部修改已提交仍读取原始值 | REPEATABLE_READ与READ_COMMITTED的区别 |
测试环境搭建 | 使用Spring程序与SQLyog工具进行并发操作测试 | 数据库连接工具默认自动提交特性 |
隔离级别修改方法 | 通过@Transactional(isolation=Isolation.XXX)属性修改隔离级别 | 不同隔离级别的适用场景选择 |
19.事务隔离级别应用实例(2)
知识点 | 核心内容 | 重点 |
声明式事务隔离级别修改 | 通过isolation属性设置隔离级别,演示从默认级别改为read commit | 隔离级别生效条件:必须在新事务中才能观察到修改后的效果 |
读已提交(READ COMMITTED)特性 | 可以读取其他事务已提交的数据变更,能获取最新数据 | 与REPEATABLE READ区别:后者在同一事务中多次读取数据保持一致 |
隔离级别修改验证方法 | 通过debug断点调试,观察事务中数据读取的变化过程 | 关键验证步骤:修改数据后立即提交,在新事务中确认读取到最新值 |
默认隔离级别建议 | 推荐保持默认的REPEATABLE READ级别,特殊需求才修改 | 典型误用场景:无明确需求时盲目修改隔离级别 |
事务超时回滚预告 | 下文将讲解事务超时设置与自动回滚机制 | 关联知识点:超时时间与系统性能的平衡 |
20.事务超时回滚(1)
知识点 | 核心内容 | 重点 |
声明式事务超时回滚 | 通过@Transactional(timeout=2)设置事务超时时间为2秒,若方法执行超过该时长则自动回滚 | 默认值timeout=-1表示采用底层事务系统默认超时时间(如MySQL默认60秒) |
超时时间单位 | timeout属性默认以秒为单位(非毫秒) | 需注意数据库支持的最小超时精度(如Oracle可能不支持秒级超时) |
超时回滚验证 | 通过Thread.sleep(4000)模拟4秒操作,触发超时回滚(与设置的2秒对比) | 测试时需确保SQL语句正确,避免非超时导致的异常干扰结果 |
默认超时行为 | 未设置timeout时依赖数据库默认配置,不同数据库差异大(MySQL/Oracle等) | 不支持超时的系统会忽略该属性设置 |
21.事务超时回滚(2)
知识点 | 核心内容 | 重点 |
事务超时模拟 | 在DAO方法后插入Thread.sleep(4000)模拟4秒超时 | 超时位置选择(需在成功执行SQL语句后) |
事务回滚机制 | 超时异常触发Spring事务回滚 | 验证方法:对比数据库余额变化 |
线程基础应用 | 使用Thread.sleep()实现延时 | 时间单位是毫秒(4000ms=4s) |
测试验证流程 | 1. 记录初始余额 2. 执行含超时代码 3. 检查异常日志 4. 验证余额回滚 | 关键验证点:数据库最终状态应与初始一致 |