Files
java/Project/assetmanager/docs/code-design.md
2026-05-26 20:47:59 +08:00

946 lines
32 KiB
Markdown
Raw Permalink 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.
# 资产管理系统 — 整体代码设计思路
---
## 一、分层设计思路
### 1.1 四层职责划分
| 层次 | 包路径 | 职责 | 核心原则 |
|------|--------|------|---------|
| 表示层 | `view/` | 用户交互、数据展示、事件响应 | 只做展示与交互,不包含业务逻辑 |
| 业务逻辑层 | `service/` | 业务规则校验、流程控制、事务协调 | 不含SQL不包含UI逻辑 |
| 数据访问层 | `dao/` | 数据库CRUD操作、SQL封装 | 只做数据存取,不含业务判断 |
| 实体层 | `entity/` | 数据载体,与表结构对应 | 纯POJO无业务逻辑 |
### 1.2 层间调用规则
```
view ──调用──▶ service ──调用──▶ dao ──操作──▶ MySQL
│ │ │
│ ├── util ├── util/DBUtil
│ ├── entity ├── entity
│ └── exception └── exception
├── util/ValidatorUtil表单即时校验
└── entity界面数据绑定
```
**严格规则:**
- view 只能调用 service**禁止直接调用 dao**
- service 只调用 dao 和 util**禁止包含 Swing 组件引用**
- dao 只操作数据库,**禁止包含业务判断逻辑**
- entity 被所有层共享,**禁止依赖其他任何层**
### 1.3 数据流转示例(资产录入)
```
用户填写表单 → AssetDialog收集输入 → 构造Asset对象
→ ValidatorUtil校验字段 → AssetService.addAsset(asset)
→ 校验资产编号唯一性 → AssetDAO.insert(asset)
→ DBUtil获取连接 → PreparedStatement执行SQL → 释放资源
→ 返回操作结果
→ 界面刷新表格 + 提示成功/失败
```
---
## 二、核心类设计
### 2.1 实体类entity
**设计原则:** 一个实体对应一张表,属性名=字段名(驼峰转换),提供全参构造+getter/setter+toString。
#### User.java
```java
// 字段id, username, password, realName, role, status, createTime, updateTime
// 角色role取值 "admin" / "user"
// 状态status取值 1(启用) / 0(禁用)
// 构造:注册用构造(不含id/time)、查询用全参构造
```
#### Asset.java
```java
// 字段id, assetCode, assetName, categoryId, status, value, purchaseDate, location, description, createTime, updateTime
// 状态status取值 "available" / "borrowed" / "disposed"
// 关联categoryId关联Category界面展示时需关联查询分类名称
```
#### Category.java
```java
// 字段id, categoryCode, categoryName, description, createTime, updateTime
// 用途:资产分类,如"办公设备"、"电子设备"、"家具"等
```
#### Borrow.java
```java
// 字段id, assetId, userId, borrowDate, expectedReturnDate, actualReturnDate, reason, status, approverId, approveTime, approveRemark, createTime, updateTime
// 状态流转pending → approved / rejectedapproved → returned / overdue
```
#### Disposal.java
```java
// 字段id, assetId, userId, reason, status, approverId, approveTime, approveRemark, disposalDate, createTime, updateTime
// 状态流转pending → approved / rejected
```
### 2.2 DAO类dao
#### BaseDAO.java — 通用CRUD模板
```java
// 设计思路抽取所有DAO共用的增删改查操作为模板方法
//
// 核心方法:
// int update(String sql, Object... params) — 通用增删改
// <T> T queryOne(String sql, RowMapper<T> mapper, Object... params) — 查询单条
// <T> List<T> queryList(String sql, RowMapper<T> mapper, Object... params) — 查询列表
// long count(String sql, Object... params) — 统计数量
//
// RowMapper接口将ResultSet行映射为实体对象函数式接口
// @FunctionalInterface
// interface RowMapper<T> { T mapRow(ResultSet rs) throws SQLException; }
//
// 资源管理所有方法内部保证Connection/PreparedStatement/ResultSet正确关闭
// 事务支持提供getConnection()供Service层手动管理事务
```
#### UserDAO.java
```java
// 继承BaseDAO实现用户特有查询
//
// 核心方法:
// User findByUsername(String username) — 按用户名查询(登录验证)
// User findById(int id) — 按ID查询关联查询用
// int insert(User user) — 新增用户
// int updatePassword(int id, String newPassword) — 修改密码
// int updateRole(int id, String role) — 修改角色
// int updateStatus(int id, int status) — 修改状态
// List<User> findAll() — 查询所有用户
// long countByUsername(String username) — 用户名唯一性校验
```
#### AssetDAO.java
```java
// 继承BaseDAO实现资产特有查询
//
// 核心方法:
// int insert(Asset asset) — 新增资产
// int update(Asset asset) — 修改资产
// int deleteById(int id) — 删除资产
// Asset findById(int id) — 按ID查询
// Asset findByAssetCode(String assetCode) — 按编号查询(唯一性校验)
// List<Asset> findAll() — 查询所有
// List<Asset> findByCondition(String name, Integer categoryId, String status, String location)
// — 多条件组合查询
// int updateStatus(int id, String status) — 更新资产状态
// long countByCategoryId(int categoryId) — 统计分类下资产数量(删除前检查)
```
#### CategoryDAO.java
```java
// 继承BaseDAO实现分类特有查询
//
// 核心方法:
// int insert(Category category) — 新增分类
// int update(Category category) — 修改分类
// int deleteById(int id) — 删除分类
// Category findById(int id) — 按ID查询
// List<Category> findAll() — 查询所有
// long countByCategoryCode(String code) — 编号唯一性校验
```
#### BorrowDAO.java
```java
// 继承BaseDAO实现借用特有查询
//
// 核心方法:
// int insert(Borrow borrow) — 新增借用记录
// int updateStatus(int id, String status, Integer approverId, String remark)
// — 更新借用状态(审批)
// int updateReturn(int id, LocalDateTime returnDate) — 登记归还
// Borrow findById(int id) — 按ID查询
// List<Borrow> findByUserId(int userId) — 按借用人查询
// List<Borrow> findByAssetId(int assetId) — 按资产查询
// List<Borrow> findByStatus(String status) — 按状态查询
// List<Borrow> findAll() — 查询所有
// List<Borrow> findOverdue() — 查询逾期未还
```
#### DisposalDAO.java
```java
// 继承BaseDAO实现报废特有查询
//
// 核心方法:
// int insert(Disposal disposal) — 新增报废记录
// int updateStatus(int id, String status, Integer approverId, String remark)
// — 更新报废状态(审批)
// Disposal findById(int id) — 按ID查询
// List<Disposal> findByUserId(int userId) — 按申请人查询
// List<Disposal> findByAssetId(int assetId) — 按资产查询
// List<Disposal> findByStatus(String status) — 按状态查询
// List<Disposal> findAll() — 查询所有
```
### 2.3 Service类service
#### UserService.java
```java
// 用户业务逻辑
//
// 核心方法:
// User login(String username, String password)
// → 校验用户名非空、密码非空
// → MD5加密密码后与数据库比对
// → 检查账户状态(是否禁用)
// → 失败抛出BusinessException
//
// void register(String username, String password, String realName)
// → 校验用户名长度(3-20)、密码长度(6-20)、真实姓名非空
// → 校验用户名唯一性
// → MD5加密密码
// → 调用DAO插入默认角色user、状态1
//
// void changePassword(int userId, String oldPwd, String newPwd)
// → 验证旧密码正确性
// → 校验新密码格式
// → MD5加密新密码后更新
//
// List<User> getAllUsers()
// → 调用DAO查询所有用户
//
// void updateUserRole(int userId, String role)
// → 校验角色值合法性admin/user
// → 调用DAO更新角色
//
// void updateUserStatus(int userId, int status)
// → 校验状态值合法性0/1
// → 调用DAO更新状态
```
#### AssetService.java
```java
// 资产业务逻辑
//
// 核心方法:
// void addAsset(Asset asset)
// → 校验必填项(编号、名称、分类、价值、购入日期)
// → 校验资产编号唯一性
// → 校验价值为正数
// → 校验购入日期不晚于今天
// → 调用DAO插入
//
// void updateAsset(Asset asset)
// → 校验必填项
// → 调用DAO更新
//
// void deleteAsset(int assetId)
// → 检查资产状态,已被借用的不可删除
// → 调用DAO删除
//
// Asset getAssetById(int id)
// → 调用DAO查询
//
// List<Asset> getAllAssets()
// → 调用DAO查询所有
//
// List<Asset> searchAssets(String name, Integer categoryId, String status, String location)
// → 调用DAO多条件组合查询
// → 任意条件可为空null表示不筛选
//
// void updateAssetStatus(int assetId, String status)
// → 校验状态值合法性
// → 调用DAO更新状态
```
#### CategoryService.java
```java
// 分类业务逻辑
//
// 核心方法:
// void addCategory(Category category)
// → 校验分类名称非空、编号非空
// → 校验分类编号唯一性
// → 调用DAO插入
//
// void updateCategory(Category category)
// → 校验必填项
// → 调用DAO更新
//
// void deleteCategory(int categoryId)
// → 检查该分类下是否有资产(引用完整性)
// → 有资产则抛出BusinessException禁止删除
// → 无资产则调用DAO删除
//
// List<Category> getAllCategories()
// → 调用DAO查询所有
//
// Category getCategoryById(int id)
// → 调用DAO查询
```
#### BorrowService.java
```java
// 借用业务逻辑(核心业务,状态流转复杂)
//
// 核心方法:
// void applyBorrow(int assetId, int userId, String reason, LocalDate expectedReturnDate)
// → 校验资产状态必须为"available"
// → 校验预计归还日期晚于今天
// → 校验借用原因非空
// → 创建Borrow记录状态pending
// → 更新资产状态为"borrowed"(预占,审批通过后确认)
// → 注意:此处需事务保证借用记录与资产状态一致
//
// void approveBorrow(int borrowId, int approverId, boolean approved, String remark)
// → 校验借用状态必须为"pending"
// → 校验操作人为管理员
// → 若同意状态改为approved资产状态保持borrowed
// → 若拒绝状态改为rejected资产状态恢复为available
// → 记录审批人、审批时间、审批备注
// → 需事务保证
//
// void returnAsset(int borrowId)
// → 校验借用状态必须为"approved"
// → 更新借用记录状态改returned记录实际归还日期
// → 更新资产状态为available
// → 需事务保证
//
// List<Borrow> getMyBorrows(int userId)
// → 查询当前用户的借用记录
//
// List<Borrow> getPendingBorrows()
// → 查询待审批借用记录
//
// List<Borrow> getAllBorrows()
// → 查询所有借用记录
//
// void checkOverdue()
// → 批量检查逾期approved状态+预计归还日期<今天 → 更新为overdue
```
#### DisposalService.java
```java
// 报废业务逻辑
//
// 核心方法:
// void applyDisposal(int assetId, int userId, String reason)
// → 校验资产状态必须为"available"
// → 校验报废原因非空
// → 创建Disposal记录状态pending
// → 需事务保证
//
// void approveDisposal(int disposalId, int approverId, boolean approved, String remark)
// → 校验报废状态必须为"pending"
// → 校验操作人为管理员
// → 若同意状态改approved资产状态改为disposed记录报废日期
// → 若拒绝状态改rejected资产状态保持available
// → 需事务保证
//
// List<Disposal> getMyDisposals(int userId)
// → 查询当前用户的报废申请
//
// List<Disposal> getPendingDisposals()
// → 查询待审批报废记录
//
// List<Disposal> getAllDisposals()
// → 查询所有报废记录
```
#### StatService.java
```java
// 统计业务逻辑
//
// 核心方法:
// Map<String, Integer> getCategoryStat()
// → 按分类统计资产数量,返回{分类名: 数量}
// → 用于饼图展示
//
// Map<String, Integer> getStatusStat()
// → 按状态统计资产数量,返回{状态名: 数量}
// → 用于柱状图展示
//
// List<Map<String, Object>> getBorrowFrequency(int topN)
// → 统计借用次数TOP N的资产
// → 返回[{资产名, 借用次数}, ...]
//
// Map<String, Double> getValueStat()
// → 按分类统计资产价值汇总
// → 返回{分类名: 总价值}
//
// int getTotalAssetCount()
// → 资产总数
//
// double getTotalAssetValue()
// → 资产总价值
//
// int getBorrowingCount()
// → 当前借出数量
//
// int getOverdueCount()
// → 逾期未还数量
```
### 2.4 界面类view
#### LoginFrame.java
```java
// 登录窗口 — 程序启动入口界面
// 布局:居中显示,用户名/密码输入框 + 登录按钮 + 注册链接
// 事件:
// 登录按钮 → 调用UserService.login()
// 成功 → 隐藏LoginFrame显示MainFrame传入User对象
// 失败 → 弹出错误提示
// 注册链接 → 打开RegisterDialog
// 窗口setSize(400, 300),居中,关闭时退出程序
```
#### RegisterDialog.java
```java
// 注册对话框 — JDialog模态窗口
// 表单:用户名、密码、确认密码、真实姓名 + 注册/取消按钮
// 校验:
// 用户名3-20位 → 即时校验
// 密码6-20位 → 即时校验
// 两次密码一致 → 提交时校验
// 真实姓名非空 → 提交时校验
// 提交 → 调用UserService.register()
```
#### MainFrame.java
```java
// 主窗口 — 功能导航容器
// 布局BorderLayout
// 北部:顶部信息栏(欢迎语 + 当前用户 + 角色 + 修改密码按钮 + 退出按钮)
// 西部左侧导航菜单JList或JButton组
// 菜单项:资产管理、分类管理、借用管理、报废管理、数据统计
// 管理员额外可见:用户管理
// 中部右侧内容区CardLayout切换各功能面板
// 切换逻辑:
// 点击左侧菜单项 → CardLayout.show(对应Panel)
// 切换面板时自动刷新数据
```
#### panel/AssetPanel.java
```java
// 资产管理面板
// 布局:
// 顶部:搜索栏(名称输入 + 分类下拉 + 状态下拉 + 位置输入 + 搜索按钮 + 重置按钮)
// 中部JTable资产列表编号/名称/分类/状态/价值/购入日期/位置)
// 底部:操作按钮(新增/编辑/删除/详情)
// 右下:分页控件(可选)
// 事件:
// 搜索 → 调用AssetService.searchAssets() → 刷新表格
// 新增 → 打开AssetDialog(mode=ADD)
// 编辑 → 选中行 → 打开AssetDialog(mode=EDIT, asset)
// 删除 → 选中行 → 确认对话框 → AssetService.deleteAsset()
// 详情 → 选中行 → 打开AssetDialog(mode=VIEW, asset)
```
#### panel/CategoryPanel.java
```java
// 分类管理面板
// 布局:
// 中部JTable分类列表编号/名称/描述/资产数量/创建时间)
// 底部:操作按钮(新增/编辑/删除)
// 事件:
// 新增 → 打开CategoryDialog(mode=ADD)
// 编辑 → 选中行 → 打开CategoryDialog(mode=EDIT, category)
// 删除 → 选中行 → 确认对话框 → CategoryService.deleteCategory()
// → 捕获BusinessException提示"该分类下有资产,禁止删除"
```
#### panel/BorrowPanel.java
```java
// 借用管理面板
// 布局:
// 顶部Tab切换我的借用 / 待审批 / 全部记录)—— 根据角色显示不同Tab
// 中部JTable借用列表
// 底部:操作按钮(借用申请 / 审批 / 归还)
// 事件:
// 借用申请 → 打开BorrowDialog
// 审批 → 选中待审批行 → 打开ApproveDialog(type=borrow)
// 归还 → 选中已审批行 → 确认归还 → BorrowService.returnAsset()
```
#### panel/DisposalPanel.java
```java
// 报废管理面板
// 布局:
// 顶部Tab切换我的申请 / 待审批 / 全部记录)
// 中部JTable报废列表
// 底部:操作按钮(报废申请 / 审批)
// 事件:
// 报废申请 → 打开DisposalDialog
// 审批 → 选中待审批行 → 打开ApproveDialog(type=disposal)
```
#### panel/StatPanel.java
```java
// 数据统计面板
// 布局:
// 顶部Tab切换分类统计 / 状态统计 / 借用排行 / 价值汇总)
// 中部JFreeChart图表区域
// 底部:汇总数据标签(资产总数/总价值/借出数/逾期数)
// 图表:
// 分类统计 → PieDataset + ChartFactory.createPieChart()
// 状态统计 → DefaultCategoryDataset + ChartFactory.createBarChart()
// 借用排行 → DefaultCategoryDataset + 横向柱状图
// 价值汇总 → DefaultCategoryDataset + 柱状图
```
#### panel/UserPanel.java
```java
// 用户管理面板(仅管理员可见)
// 布局:
// 中部JTable用户列表用户名/姓名/角色/状态/创建时间)
// 底部:操作按钮(修改角色 / 启用禁用)
// 事件:
// 修改角色 → 下拉选择admin/user → UserService.updateUserRole()
// 启用禁用 → 确认对话框 → UserService.updateUserStatus()
```
### 2.5 工具类util
#### DBUtil.java
```java
// 数据库连接管理工具
// 设计思路读取db.properties配置提供连接获取与释放
//
// 核心方法:
// static Connection getConnection() — 获取数据库连接
// static void close(Connection conn) — 关闭连接
// static void close(ResultSet rs, PreparedStatement pstmt, Connection conn)
// — 释放查询资源(重载)
//
// 实现要点:
// 1. 类加载时读取db.properties只读一次
// 2. getConnection()每次创建新连接(课程项目无需连接池)
// 3. close方法判断null后再关闭避免NPE
// 4. 所有DAO方法通过DBUtil获取连接finally块中释放
```
#### MD5Util.java
```java
// MD5加密工具
//
// 核心方法:
// static String encrypt(String input) — 返回32位小写MD5摘要
//
// 实现java.security.MessageDigest("MD5") + Hex转换
```
#### ValidatorUtil.java
```java
// 通用表单校验工具
//
// 核心方法:
// static boolean isEmpty(String str) — 判空null或trim后为空
// static boolean isPositive(BigDecimal value) — 判断为正数
// static boolean isLengthInRange(String str, int min, int max) — 长度范围校验
// static boolean isDateAfter(LocalDate date, LocalDate after) — 日期先后校验
// static boolean isAlphanumeric(String str) — 字母数字校验(用户名)
// static boolean isNumeric(String str) — 纯数字校验
//
// 使用场景:
// Service层校验 + View层即时校验
```
#### DateUtil.java
```java
// 日期工具类
//
// 核心方法:
// static String format(LocalDate date) — LocalDate → "yyyy-MM-dd"
// static String format(LocalDateTime dateTime) — LocalDateTime → "yyyy-MM-dd HH:mm:ss"
// static LocalDate parseDate(String str) — "yyyy-MM-dd" → LocalDate
// static LocalDateTime parseDateTime(String str) — "yyyy-MM-dd HH:mm:ss" → LocalDateTime
```
### 2.6 异常类exception
#### BusinessException.java
```java
// 业务异常继承RuntimeException
// 字段errorCode错误码、message错误描述
// 用途Service层抛出View层捕获并展示给用户
// 示例throw new BusinessException("资产编号已存在")
```
#### DBException.java
```java
// 数据库异常继承RuntimeException
// 字段message错误描述、cause原始SQLException
// 用途DAO层抛出Service层捕获后包装为BusinessException或直接向上传播
```
---
## 三、业务逻辑设计
### 3.1 登录注册流程
```
登录流程:
用户输入 → ValidatorUtil判空 → UserService.login()
→ UserDAO.findByUsername() → 用户不存在?→ 抛异常"用户名或密码错误"
→ MD5Util.encrypt(输入密码) → 与数据库密码比对 → 不匹配?→ 抛异常"用户名或密码错误"
→ status==0→ 抛异常"账户已被禁用"
→ 返回User对象 → LoginFrame隐藏 → MainFrame显示
注册流程:
用户输入 → ValidatorUtil校验格式 → 确认密码一致性
→ UserService.register() → 用户名唯一性校验 → MD5加密密码 → UserDAO.insert()
```
### 3.2 资产CRUD流程
```
录入:表单填写 → ValidatorUtil校验 → AssetService.addAsset()
→ 编号唯一性校验 → 价值正数校验 → 日期合理性校验 → AssetDAO.insert()
修改:选中行 → 回填表单 → 修改字段 → AssetService.updateAsset()
→ 校验必填项 → AssetDAO.update()
删除:选中行 → 确认对话框 → AssetService.deleteAsset()
→ 检查资产状态(borrowed不可删) → AssetDAO.deleteById()
查询:输入条件 → AssetService.searchAssets()
→ 任意条件为null则不筛选 → AssetDAO.findByCondition() → 返回结果列表
```
### 3.3 借用归还流程
```
借用申请:
选择可用资产 → 填写原因+预计归还日期 → BorrowService.applyBorrow()
→ 校验资产状态为available → 创建Borrow(pending)
→ 更新资产状态为borrowed → 事务提交
审批(管理员):
选中待审批记录 → 同意/拒绝 → BorrowService.approveBorrow()
→ 同意Borrow.status → approved资产保持borrowed
→ 拒绝Borrow.status → rejected资产恢复available
→ 事务提交
归还:
选中已审批记录 → 确认归还 → BorrowService.returnAsset()
→ Borrow.status → returned记录实际归还日期
→ 资产状态恢复available → 事务提交
逾期检查:
BorrowService.checkOverdue() → approved + expectedReturnDate < 今天 → overdue
```
### 3.4 报废流程
```
报废申请:
选择可用资产 → 填写报废原因 → DisposalService.applyDisposal()
→ 校验资产状态为available → 创建Disposal(pending)
审批(管理员):
选中待审批记录 → 同意/拒绝 → DisposalService.approveDisposal()
→ 同意Disposal.status → approved资产状态 → disposed
→ 拒绝Disposal.status → rejected资产状态保持available
```
### 3.5 统计查询流程
```
分类统计StatService.getCategoryStat()
→ SELECT c.category_name, COUNT(a.id) FROM t_asset a JOIN t_category c → PieDataset → 饼图
状态统计StatService.getStatusStat()
→ SELECT status, COUNT(*) FROM t_asset GROUP BY status → DefaultCategoryDataset → 柱状图
借用排行StatService.getBorrowFrequency(10)
→ SELECT a.asset_name, COUNT(b.id) FROM t_borrow b JOIN t_asset a GROUP BY a.id → TOP 10
价值汇总StatService.getValueStat()
→ SELECT c.category_name, SUM(a.value) FROM t_asset a JOIN t_category c → 柱状图
```
### 3.6 表单校验设计
```
校验层级:
1. 即时校验View层— 输入时实时反馈
- JTextField.addKeyListener / FocusListener
- 用户名长度、密码长度、数值格式等
2. 提交校验Service层— 提交时完整性校验
- 必填项非空
- 唯一性(用户名、资产编号)
- 业务规则(资产状态、日期合理性)
3. 数据库校验DAO层— 数据库约束兜底
- UNIQUE约束
- NOT NULL约束
- 外键约束
校验反馈:
- 即时校验:字段旁红色提示文字
- 提交校验JOptionPane.showMessageDialog警告
- 数据库校验捕获SQLException转为友好提示
```
### 3.7 数据可视化设计
```
JFreeChart集成
1. Maven依赖org.jfreechart/jfreechart
2. 图表创建ChartFactory + 数据集PieDataset/CategoryDataset
3. 图表展示ChartPanel封装 → 添加到StatPanel
4. 样式定制:标题、颜色、字体、图例
四种图表:
- 饼图PieChart分类数量占比颜色区分各类别
- 柱状图BarChart状态数量对比横向展示
- 排行图借用频率TOP 10降序横向柱状图
- 价值图:各分类资产价值汇总,柱状图
```
---
## 四、数据库交互设计
### 4.1 JDBC连接管理
```java
// DBUtil核心逻辑
// 1. 静态初始化块加载db.properties
static {
Properties props = new Properties();
try (InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("db.properties")) {
props.load(is);
url = props.getProperty("db.url");
username = props.getProperty("db.username");
password = props.getProperty("db.password");
Class.forName(props.getProperty("db.driver"));
} catch (Exception e) {
throw new RuntimeException("数据库配置加载失败", e);
}
}
// 2. 获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
// 3. 释放资源 — 判断null后关闭顺序ResultSet → PreparedStatement → Connection
```
### 4.2 PreparedStatement防注入
```java
// 所有SQL操作均使用PreparedStatement禁止字符串拼接SQL
// 示例:
String sql = "SELECT * FROM t_user WHERE username = ? AND password = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username); // 参数化防SQL注入
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
// ...
}
```
### 4.3 事务管理
```java
// 需要事务的操作:借用申请、借用审批、借用归还、报废审批
// 这些操作涉及多表更新,需保证原子性
//
// 事务管理模式:手动事务控制
// Connection conn = null;
// try {
// conn = DBUtil.getConnection();
// conn.setAutoCommit(false); // 开启事务
//
// // 执行多条SQL...
//
// conn.commit(); // 提交事务
// } catch (Exception e) {
// if (conn != null) conn.rollback(); // 回滚事务
// throw new BusinessException("操作失败:" + e.getMessage());
// } finally {
// if (conn != null) conn.setAutoCommit(true);
// DBUtil.close(conn);
// }
```
### 4.4 BaseDAO通用操作封装
```java
// 通用更新INSERT/UPDATE/DELETE
public int update(String sql, Object... params) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
return pstmt.executeUpdate();
} catch (SQLException e) {
throw new DBException("数据库操作失败", e);
} finally {
DBUtil.close(null, pstmt, conn);
}
}
// 通用查询列表
public <T> List<T> queryList(String sql, RowMapper<T> mapper, Object... params) {
// 类似结构ResultSet遍历 + mapper映射
}
```
---
## 五、规范要求
### 5.1 Java命名规范
| 类型 | 规范 | 示例 |
|------|------|------|
| 类名 | 大驼峰 | AssetService, BorrowDAO |
| 方法名 | 小驼峰 | findByUsername, addAsset |
| 变量名 | 小驼峰 | assetList, currentUser |
| 常量名 | 全大写下划线 | MAX_RETRY_COUNT |
| 包名 | 全小写 | com.asset.service |
| 数据库表名 | t_前缀+小写下划线 | t_asset, t_borrow |
| 数据库字段名 | 小写下划线 | asset_code, create_time |
### 5.2 注释规范
```java
/**
* 资产业务逻辑类
* 提供资产的增删改查、状态管理、数据校验等业务功能
*
* @author 作者名
* @version 1.0
*/
public class AssetService {
/**
* 新增资产
* 校验资产编号唯一性、必填项、价值正数后调用DAO插入
*
* @param asset 资产实体对象
* @throws BusinessException 编号重复、校验不通过时抛出
*/
public void addAsset(Asset asset) {
// 校验资产编号唯一性
// ...
}
}
```
### 5.3 异常处理思路
```
异常分层处理策略:
DAO层捕获SQLException → 包装为DBException向上抛出
Service层捕获DBException → 转为BusinessException对用户友好
Service层业务规则不满足 → 直接抛BusinessException
View层捕获BusinessException → JOptionPane展示错误信息
View层捕获未预期异常 → 记录日志 + 通用错误提示
禁止:
- 禁止空catch块吞掉异常
- 禁止catch Exception后不做处理
- 禁止在DAO/Service层直接弹出UI对话框
```
### 5.4 AI代码校验优化要求
| 校验维度 | 检查要点 |
|----------|---------|
| 逻辑正确性 | 业务流程是否完整、边界条件是否处理 |
| SQL安全性 | 是否使用PreparedStatement、参数是否正确绑定 |
| 资源泄漏 | Connection/Statement/ResultSet是否正确关闭 |
| 命名规范 | 是否符合Java命名规范 |
| 异常处理 | 是否合理捕获/抛出、异常信息是否明确 |
| 代码冗余 | 是否有重复代码可提取到BaseDAO或工具类 |
| 业务完整性 | 状态流转是否正确、事务是否保证 |
---
## 六、课程评分匹配设计
### 6.1 功能完整性(满分保障)
| 课程要求 | 本系统实现 |
|----------|-----------|
| 用户登录注册 | ✅ 登录+注册+修改密码+角色权限 |
| 资产数据增删改查 | ✅ 完整CRUD + 多条件组合查询 |
| 数据可视化展示 | ✅ 4种JFreeChart图表 |
| 表单数据校验 | ✅ 三层校验(即时+提交+数据库) |
| 资产管理基础业务 | ✅ 借用/归还/报废全流程 |
| 功能量级2-3倍 | ✅ 5张表、8个模块、审批流程、统计功能 |
### 6.2 代码质量
| 维度 | 保障措施 |
|------|---------|
| 分层清晰 | 严格四层架构,层间调用规则明确 |
| 命名规范 | 遵循Java命名规范+阿里巴巴开发手册 |
| 注释完整 | 类注释+方法注释+关键逻辑行内注释 |
| 异常处理 | 自定义异常+分层处理+友好提示 |
| SQL安全 | PreparedStatement+参数化查询 |
| 资源管理 | finally块关闭+DBUtil统一释放 |
### 6.3 文档配套
| 文档 | 内容 |
|------|------|
| 架构设计文档 | 技术架构+功能模块+数据库设计+AI规范+感悟 |
| 目录结构文档 | 项目结构+目录功能注释 |
| 代码设计思路文档 | 本文档,完整设计思路 |
| SQL脚本 | 建库建表+初始数据 |
| 代码内注释 | 类/方法/逻辑三层注释 |
### 6.4 创新拓展
| 拓展点 | 说明 |
|--------|------|
| 审批流程 | 借用/报废均需管理员审批,非简单状态切换 |
| 逾期自动检测 | 系统自动检测逾期借用记录 |
| 多维度统计 | 分类/状态/借用/价值四维度可视化 |
| 角色权限 | 管理员/普通用户功能差异化 |
| 组合查询 | 资产支持多条件组合筛选 |
| 数据关联完整性 | 删除分类检查资产引用、删除资产检查借用状态 |