Java 三剑客模拟数据库操作
文章目录
-
- 前言
- 数据结构设计
-
- 1. 表结构模拟
- 2. 关联关系模拟
- 基础CRUD操作
-
- 1. INSERT操作
- 2. SELECT操作
- 3. UPDATE操作
- 4. DELETE操作
- JOIN操作模拟
-
- 1. INNER JOIN
- 2. LEFT JOIN
- 3. RIGHT JOIN
- 4. FULL OUTER JOIN
- 高级功能扩展
-
- 1. 索引优化
- 2. 事务支持
- 3. 分页查询
- 性能对比与限制
- 完整代码示例
-
- 数据库模拟器核心类
- 运行结果
- 总结
前言
当你迷茫的时候,请点击 总目录大纲 快速查看前面的技术文章,相信你总能找到前行的方向
另外,本文相关代码已上传 gitee仓库,欢迎关注收藏
以下将基于Java集合框架(List/Set/Map)模拟MySQL数据库的核心操作,涵盖SELECT、INSERT、UPDATE、DELETE以及各类JOIN操作。通过数据结构的组合实现关系型数据库的核心功能。
数据结构设计
假设有两个表,一个用户表,一个订单表,两者以 用户id
来关联
1. 表结构模拟
用Map
表示数据库表:
- Key:主键(如用户ID)
- Value:行数据(字段名到值的映射)
构建 map 工具方法
// 构建 map 工具方法private static Map<String, Object> mapOf(Object... args) { HashMap<String, Object> map = new HashMap<>(16); int len = args.length; for (int i = 0; i < len; i += 2) { if (i + 1 > len) { return map; } Object key = args[i]; Object val = args[i + 1]; if (key != null) { map.put(key.toString(), val); } } return map;}
模拟users表(主键为id)
// 模拟users表(主键为id)Map<String, Map<String, Object>> users = new HashMap<>();users.put(\"1\", mapOf(\"id\", \"1\", \"name\", \"Alice\", \"age\", 25));users.put(\"2\", mapOf(\"id\", \"2\", \"name\", \"Bob\", \"age\", 30));
2. 关联关系模拟
用List
存储关联表(如订单表),通过外键关联:
// 模拟orders表(外键user_id关联users.id)List<Map<String, Object>> orders = new ArrayList<>();orders.add(mapOf(\"order_id\", \"A1\", \"user_id\", \"1\", \"amount\", 100));orders.add(mapOf(\"order_id\", \"A2\", \"user_id\", \"2\", \"amount\", 200));
基础CRUD操作
1. INSERT操作
向集合插入新数据:
// 插入新用户Map<String, Object> newUser = mapOf(\"id\", \"3\", \"name\", \"Charlie\", \"age\", 28);users.put(newUser.get(\"id\").toString(), newUser);
2. SELECT操作
通过条件筛选数据:
// 查询年龄>25的用户(模拟WHERE)List<Map<String, Object>> result = users.values().stream() .filter(user -> (int) user.get(\"age\") > 25) .collect(Collectors.toList());
3. UPDATE操作
修改指定记录:
// 更新用户2的年龄users.computeIfPresent(\"2\", (k, v) -> { v.put(\"age\", 35); return v;});
4. DELETE操作
移除指定记录:
// 删除用户3users.remove(\"3\");
JOIN操作模拟
SQL JOIN操作用于把来自两个或多个表的行结合起来
1. INNER JOIN
获取两表交集数据:
List<Map<String, Object>> innerJoinResult = orders.stream() .filter(order -> users.containsKey(order.get(\"user_id\"))) .map(order -> { Map<String, Object> user = users.get(order.get(\"user_id\")); return mapOf( \"user_name\", user.get(\"name\"), \"order_id\", order.get(\"order_id\"), \"amount\", order.get(\"amount\") ); }).collect(Collectors.toList());
原理:通过外键过滤有效订单,再合并用户信息
2. LEFT JOIN
保留左表所有数据,右表无匹配时补null
:
List<Map<String, Object>> leftJoinResult = orders.stream() .map(order -> { Map<String, Object> user = users.getOrDefault(order.get(\"user_id\"), null); Map<String, Object> row = new HashMap<>(order); row.put(\"user_name\", user != null ? user.get(\"name\") : null); return row; }).collect(Collectors.toList());
原理:遍历左表(订单),强制关联右表(用户),无匹配则填充空值
3. RIGHT JOIN
保留右表所有数据(通过反转LEFT JOIN实现):
Set<Object> ordersSet = orders.stream().map(order -> order.get(\"user_id\")).collect(Collectors.toSet());List<Map<String, Object>> rightJoinResult = users.values().stream().flatMap(user -> { Object userId = user.get(\"id\"); // user 多出部分 if (!ordersSet.contains(userId)) { return Stream.of(mapOf(\"user_name\", user.get(\"name\"), \"order_id\", null, \"amount\", null)); } // 交集 return orders.stream().filter(order -> order.get(\"user_id\").equals(user.get(\"id\"))) .map(order -> mapOf(\"user_name\", user.get(\"name\"), \"order_id\", order.get(\"order_id\"), \"amount\", order.get(\"amount\"))); }).collect(Collectors.toList());
原理:以用户表为基准,反向关联订单表
4. FULL OUTER JOIN
通过LEFT JOIN
和RIGHT JOIN
的并集模拟:
Set<Map<String, Object>> fullJoin = new HashSet<>(leftJoinResult);fullJoin.addAll(rightJoinResult);List<Map<String, Object>> fullOuterJoinResult = new ArrayList<>(fullJoin);
原理:利用集合的并集操作实现全外连接
高级功能扩展
1. 索引优化
用Map<Object, List
构建字段索引:
// 为年龄字段创建索引Map<Integer, List<Map<String, Object>>> ageIndex = users.values().stream() .collect(Collectors.groupingBy(user -> (int) user.get(\"age\")));
2. 事务支持
通过操作日志实现原子性:
// 事务操作示例List<Runnable> transaction = new ArrayList<>();transaction.add(() -> users.put(\"4\", mapOf(\"id\", \"4\", \"name\", \"Dave\")));transaction.add(() -> orders.add(mapOf(\"order_id\", \"A3\", \"user_id\", \"4\")));transaction.forEach(Runnable::run); // 原子提交
3. 分页查询
结合Stream
的skip
和limit
:
// 分页查询(每页2条,第1页)List<Map<String, Object>> page = users.values().stream() .skip(0).limit(2) .collect(Collectors.toList());
性能对比与限制
关键限制:
- 数据规模超过10万级时,嵌套循环JOIN性能急剧下降
- 无法实现真正的ACID事务
- 缺乏MySQL的查询优化器自动选择执行计划
完整代码示例
数据库模拟器核心类
import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import java.util.stream.Collectors;import java.util.stream.Stream;public class TestDbLsm { /** * 构建map * * @param args 参数 * @return Map */ private static Map<String, Object> mapOf(Object... args) { HashMap<String, Object> map = new HashMap<>(16); int len = args.length; for (int i = 0; i < len; i += 2) { if (i + 1 > len) { return map; } Object key = args[i]; Object val = args[i + 1]; if (key != null) { map.put(key.toString(), val); } } return map; } public static void main(String[] args) { // 模拟users表(主键为id) Map<String, Map<String, Object>> users = new HashMap<>(); users.put(\"1\", mapOf(\"id\", \"1\", \"name\", \"Alice\", \"age\", 25)); users.put(\"2\", mapOf(\"id\", \"2\", \"name\", \"Bob\", \"age\", 30)); System.out.println(\"users: \" + users); // 模拟orders表(外键user_id关联users.id) List<Map<String, Object>> orders = new ArrayList<>(); orders.add(mapOf(\"order_id\", \"A0\", \"user_id\", \"0\", \"amount\", 0)); orders.add(mapOf(\"order_id\", \"A1\", \"user_id\", \"1\", \"amount\", 100)); orders.add(mapOf(\"order_id\", \"A2\", \"user_id\", \"2\", \"amount\", 200)); System.out.println(\"orders: \" + orders); // 插入新用户 testAdd(users); // 查询年龄>25的用户(模拟WHERE) testQuery(users); // 更新用户2的年龄 testUpdate(users); // 删除用户3 testDelete(users); // INNER JOIN testInnerJoin(orders, users); // LEFT JOIN: (order left join user) List<Map<String, Object>> leftJoinResult = testLeftJoin(orders, users); // RIGHT JOIN: (order right join user = user left join order) List<Map<String, Object>> rightJoinResult = testRightJoin(orders, users); // FULL JOIN testFullJoin(leftJoinResult, rightJoinResult); // 为年龄字段创建索引 testIndex(users); // 事务操作示例 testTransaction(users, orders); // 分页查询(每页2条,第1页) testPage(users); } private static void testPage(Map<String, Map<String, Object>> users) { List<Map<String, Object>> page = users.values().stream() .skip(0).limit(2) .collect(Collectors.toList()); System.out.println(\"分页查询: \" + page); } private static void testTransaction(Map<String, Map<String, Object>> users, List<Map<String, Object>> orders) { List<Runnable> transaction = new ArrayList<>(); transaction.add(() -> users.put(\"4\", mapOf(\"id\", \"4\", \"name\", \"Dave\"))); transaction.add(() -> orders.add(mapOf(\"order_id\", \"A3\", \"user_id\", \"4\"))); // 原子提交 transaction.forEach(Runnable::run); System.out.println(\"事务操作: \" + transaction); } private static void testIndex(Map<String, Map<String, Object>> users) { Map<Integer, List<Map<String, Object>>> ageIndex = users.values().stream() .collect(Collectors.groupingBy(user -> (int) user.get(\"age\"))); System.out.println(\"为年龄字段创建索引: \" + ageIndex); } private static void testFullJoin(List<Map<String, Object>> leftJoinResult, List<Map<String, Object>> rightJoinResult) { Set<Map<String, Object>> fullJoin = new HashSet<>(leftJoinResult); fullJoin.addAll(rightJoinResult); List<Map<String, Object>> fullOuterJoinResult = new ArrayList<>(fullJoin); System.out.println(\"FULL JOIN: \" + fullOuterJoinResult); } private static List<Map<String, Object>> testRightJoin(List<Map<String, Object>> orders, Map<String, Map<String, Object>> users) { Set<Object> ordersSet = orders.stream().map(order -> order.get(\"user_id\")).collect(Collectors.toSet()); List<Map<String, Object>> rightJoinResult = users.values().stream().flatMap(user -> { Object userId = user.get(\"id\"); // user 多出部分 if (!ordersSet.contains(userId)) { return Stream.of(mapOf(\"user_name\", user.get(\"name\"), \"order_id\", null, \"amount\", null)); } // 交集 return orders.stream().filter(order -> order.get(\"user_id\").equals(user.get(\"id\"))) .map(order -> mapOf(\"user_name\", user.get(\"name\"),\"order_id\", order.get(\"order_id\"), \"amount\", order.get(\"amount\"))); } ).collect(Collectors.toList()); System.out.println(\"[order] RIGHT JOIN [user]: \" + rightJoinResult); return rightJoinResult; } private static List<Map<String, Object>> testLeftJoin(List<Map<String, Object>> orders, Map<String, Map<String, Object>> users) { List<Map<String, Object>> leftJoinResult = orders.stream() .map(order -> { Map<String, Object> user = users.getOrDefault(order.get(\"user_id\"), null); Map<String, Object> row = new HashMap<>(order); row.put(\"user_name\", user != null ? user.get(\"name\") : null); return row; }).collect(Collectors.toList()); System.out.println(\"[order] LEFT JOIN [user]: \" + leftJoinResult); return leftJoinResult; } private static void testInnerJoin(List<Map<String, Object>> orders, Map<String, Map<String, Object>> users) { List<Map<String, Object>> innerJoinResult = orders.stream() .filter(order -> users.containsKey(order.get(\"user_id\"))) .map(order -> { Map<String, Object> user = users.get(order.get(\"user_id\")); return mapOf( \"user_name\", user.get(\"name\"), \"order_id\", order.get(\"order_id\"), \"amount\", order.get(\"amount\") ); }).collect(Collectors.toList()); System.out.println(\"INNER JOIN: \" + innerJoinResult); } private static void testDelete(Map<String, Map<String, Object>> users) { users.remove(\"3\"); System.out.println(\"删除用户3: \" + users); } private static void testUpdate(Map<String, Map<String, Object>> users) { users.computeIfPresent(\"2\", (k, v) -> { v.put(\"age\", 35); return v; }); System.out.println(\"更新用户2的年龄: \" + users); } private static void testQuery(Map<String, Map<String, Object>> users) { List<Map<String, Object>> result = users.values().stream() .filter(user -> (int) user.get(\"age\") > 25) .collect(Collectors.toList()); System.out.println(\"查询年龄>25的用户: \" + result); } private static void testAdd(Map<String, Map<String, Object>> users) { // 插入新用户 Map<String, Object> newUser = mapOf(\"id\", \"3\", \"name\", \"Charlie\", \"age\", 28); users.put(newUser.get(\"id\").toString(), newUser); newUser = mapOf(\"id\", \"4\", \"name\", \"Doge\", \"age\", 30); users.put(newUser.get(\"id\").toString(), newUser); System.out.println(\"插入新用户: \" + users); }}
运行结果
users: {1={name=Alice, id=1, age=25}, 2={name=Bob, id=2, age=30}}orders: [{amount=0, user_id=0, order_id=A0}, {amount=100, user_id=1, order_id=A1}, {amount=200, user_id=2, order_id=A2}]插入新用户: {1={name=Alice, id=1, age=25}, 2={name=Bob, id=2, age=30}, 3={name=Charlie, id=3, age=28}, 4={name=Doge, id=4, age=30}}查询年龄>25的用户: [{name=Bob, id=2, age=30}, {name=Charlie, id=3, age=28}, {name=Doge, id=4, age=30}]更新用户2的年龄: {1={name=Alice, id=1, age=25}, 2={name=Bob, id=2, age=35}, 3={name=Charlie, id=3, age=28}, 4={name=Doge, id=4, age=30}}删除用户3: {1={name=Alice, id=1, age=25}, 2={name=Bob, id=2, age=35}, 4={name=Doge, id=4, age=30}}INNER JOIN: [{amount=100, user_name=Alice, order_id=A1}, {amount=200, user_name=Bob, order_id=A2}][order] LEFT JOIN [user]: [{amount=0, user_id=0, order_id=A0, user_name=null}, {amount=100, user_id=1, order_id=A1, user_name=Alice}, {amount=200, user_id=2, order_id=A2, user_name=Bob}][order] RIGHT JOIN [user]: [{amount=100, user_name=Alice, order_id=A1}, {amount=200, user_name=Bob, order_id=A2}, {amount=null, user_name=Doge, order_id=null}]FULL JOIN: [{amount=200, user_name=Bob, order_id=A2}, {amount=100, user_id=1, order_id=A1, user_name=Alice}, {amount=200, user_id=2, order_id=A2, user_name=Bob}, {amount=0, user_id=0, order_id=A0, user_name=null}, {amount=100, user_name=Alice, order_id=A1}, {amount=null, user_name=Doge, order_id=null}]为年龄字段创建索引: {35=[{name=Bob, id=2, age=35}], 25=[{name=Alice, id=1, age=25}], 30=[{name=Doge, id=4, age=30}]}事务操作: [tool.TestDbLsm$$Lambda$22/159413332@7cd84586, tool.TestDbLsm$$Lambda$23/1028214719@30dae81]分页查询: [{name=Alice, id=1, age=25}, {name=Bob, id=2, age=35}]Process finished with exit code 0
总结
通过结合Java集合与算法,可实现对关系型数据库核心功能的近似模拟,但需根据实际场景权衡性能与功能完整性。