Files
springboot-scaffold/target/classes/static/transaction.html
likingcode c04235c655 feat: Spring Boot 学习脚手架 v2.0
- 新增 IoC 容器学习模块
- 新增 AOP 切面编程学习模块
- 新增 MyBatis 集成学习模块
- 新增事务管理学习模块
- 新增用户/产品/订单 CRUD
- 新增 7 个交互式学习页面
- 集成性能监控切面
2026-03-07 08:37:40 +00:00

191 lines
9.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事务管理学习 - Spring Boot</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; }
.container { max-width: 1400px; margin: 0 auto; padding: 20px; }
.header { background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); color: white; padding: 30px 20px; text-align: center; margin-bottom: 20px; border-radius: 10px; }
.header h1 { font-size: 2em; }
.nav { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center; }
.nav a { padding: 10px 20px; background: white; border-radius: 20px; text-decoration: none; color: #333; font-size: 0.9em; }
.nav a:hover, .nav a.active { background: #fa709a; color: white; }
.card { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.08); }
.card h3 { color: #fa709a; margin-bottom: 15px; border-bottom: 2px solid #eee; padding-bottom: 10px; }
.acid-box { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin: 20px 0; }
.acid-item { background: #f8f9fa; padding: 20px; border-radius: 10px; text-align: center; border-top: 4px solid; }
.acid-a { border-color: #e74c3c; }
.acid-c { border-color: #3498db; }
.acid-i { border-color: #2ecc71; }
.acid-d { border-color: #9b59b6; }
.acid-item h4 { font-size: 2em; margin-bottom: 10px; }
.btn { padding: 10px 20px; background: #fa709a; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px; }
.btn:hover { background: #e85a8a; }
.btn-danger { background: #e74c3c; }
.result { background: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 5px; margin-top: 10px; font-family: monospace; font-size: 0.9em; overflow-x: auto; max-height: 400px; overflow-y: auto; }
.propagation-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; }
.prop-box { background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #fa709a; }
.prop-box h4 { color: #fa709a; margin-bottom: 8px; }
table { width: 100%; border-collapse: collapse; margin: 15px 0; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
tr:hover { background: #f8f9fa; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🔄 事务管理</h1>
<p>声明式事务 - @Transactional</p>
</div>
<div class="nav">
<a href="index.html">🏠 首页</a>
<a href="ioc.html">📦 IoC</a>
<a href="aop.html">🔪 AOP</a>
<a href="mybatis.html">💾 MyBatis</a>
<a href="transaction.html" class="active">🔄 事务</a>
<a href="users.html">👥 用户</a>
<a href="api.html">🔌 API</a>
</div>
<div class="card">
<h3>📚 ACID 特性</h3>
<div class="acid-box">
<div class="acid-item acid-a">
<h4>A</h4>
<p><strong>Atomicity</strong></p>
<p>原子性</p>
<p style="font-size:0.9em;color:#666;">事务是不可分割的工作单位</p>
</div>
<div class="acid-item acid-c">
<h4>C</h4>
<p><strong>Consistency</strong></p>
<p>一致性</p>
<p style="font-size:0.9em;color:#666;">数据库状态保持一致</p>
</div>
<div class="acid-item acid-i">
<h4>I</h4>
<p><strong>Isolation</strong></p>
<p>隔离性</p>
<p style="font-size:0.9em;color:#666;">事务之间相互隔离</p>
</div>
<div class="acid-item acid-d">
<h4>D</h4>
<p><strong>Durability</strong></p>
<p>持久性</p>
<p style="font-size:0.9em;color:#666;">提交后永久保存</p>
</div>
</div>
</div>
<div class="card">
<h3>🚀 传播行为 (Propagation)</h3>
<div class="propagation-grid">
<div class="prop-box">
<h4>REQUIRED (默认)</h4>
<p>有事务则加入,无则新建</p>
<p style="font-size:0.85em;color:#666;">最常用,适合大多数业务方法</p>
</div>
<div class="prop-box">
<h4>REQUIRES_NEW</h4>
<p>总是新建事务,挂起当前事务</p>
<p style="font-size:0.85em;color:#666;">适合日志记录、独立子任务</p>
</div>
<div class="prop-box">
<h4>SUPPORTS</h4>
<p>有事务则加入,无则以非事务运行</p>
<p style="font-size:0.85em;color:#666;">适合查询方法</p>
</div>
<div class="prop-box">
<h4>NOT_SUPPORTED</h4>
<p>以非事务运行,挂起当前事务</p>
<p style="font-size:0.85em;color:#666;">不需要事务的操作</p>
</div>
<div class="prop-box">
<h4>MANDATORY</h4>
<p>必须在事务中运行,否则抛异常</p>
<p style="font-size:0.85em;color:#666;">强制要求事务</p>
</div>
<div class="prop-box">
<h4>NEVER</h4>
<p>不能在事务中运行,否则抛异常</p>
<p style="font-size:0.85em;color:#666;">确保无事务</p>
</div>
</div>
<button class="btn" onclick="loadPropagation()">查看详细说明</button>
<div id="propResult" class="result"></div>
</div>
<div class="card">
<h3>🔒 隔离级别 (Isolation)</h3>
<table>
<tr><th>级别</th><th>脏读</th><th>不可重复读</th><th>幻读</th><th>说明</th></tr>
<tr><td>READ_UNCOMMITTED</td><td></td><td></td><td></td><td>读未提交,性能最高</td></tr>
<tr><td>READ_COMMITTED</td><td></td><td></td><td></td><td>读已提交Oracle默认</td></tr>
<tr><td>REPEATABLE_READ</td><td></td><td></td><td></td><td>可重复读MySQL默认</td></tr>
<tr><td>SERIALIZABLE</td><td></td><td></td><td></td><td>串行化,性能最低</td></tr>
</table>
<p style="margin-top:10px;color:#666;">✅ = 防止该问题 | ❌ = 可能出现该问题</p>
<button class="btn" onclick="loadIsolation()">查看详细说明</button>
<div id="isoResult" class="result"></div>
</div>
<div class="card">
<h3>🧪 事务回滚演示</h3>
<p>创建订单时触发异常,观察事务回滚效果</p>
<button class="btn" onclick="loadRollback()">查看回滚规则</button>
<div id="rollbackResult" class="result"></div>
</div>
</div>
<script>
async function loadPropagation() {
const result = document.getElementById('propResult');
result.textContent = '加载中...';
try {
const res = await fetch('/api/learning/transaction/propagation');
const data = await res.json();
result.innerHTML = `<strong>传播行为详解</strong>\n\n${JSON.stringify(data, null, 2)}`;
} catch (e) {
result.textContent = '加载失败: ' + e.message;
}
}
async function loadIsolation() {
const result = document.getElementById('isoResult');
result.textContent = '加载中...';
try {
const res = await fetch('/api/learning/transaction/isolation');
const data = await res.json();
result.innerHTML = `<strong>隔离级别详解</strong>\n\n${JSON.stringify(data, null, 2)}`;
} catch (e) {
result.textContent = '加载失败: ' + e.message;
}
}
async function loadRollback() {
const result = document.getElementById('rollbackResult');
result.textContent = '加载中...';
try {
const res = await fetch('/api/learning/transaction/rollback');
const data = await res.json();
result.innerHTML = `<strong>回滚规则</strong>\n\n${JSON.stringify(data, null, 2)}`;
} catch (e) {
result.textContent = '加载失败: ' + e.message;
}
}
</script>
</body>
</html>