个人记账报表工具是Java入门实战中非常经典的项目,核心目标是帮助用户记录日常收支、按时间或分类统计金额,最终生成可视化的报表数据。整个项目可以分为数据层、业务层、表现层三个部分,分别负责数据存储、逻辑处理、用户交互。

项目前期准备
技术选型
开发个人记账报表工具可以选择以下技术栈:
- 开发语言:Java 8及以上版本
- 数据库:MySQL 5.7及以上,用于存储记账数据
- 界面开发:JavaFX或者Swing,实现可视化操作界面
- 报表生成:JasperReports,用于生成PDF或Excel格式的报表
- 构建工具:Maven,管理项目依赖
需求梳理
核心功能需求包括:
- 记账功能:支持录入收支类型、金额、时间、备注信息
- 查询功能:支持按时间范围、收支类型筛选记账数据
- 统计功能:按日、周、月、分类统计收支总额
- 报表功能:生成统计报表并支持导出
数据库设计
首先需要设计存储记账数据的表结构,核心表为记账记录表,建表语句如下:
CREATE TABLE `account_record` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录ID', `type` tinyint(1) NOT NULL COMMENT '类型 1收入 2支出', `category` varchar(20) NOT NULL COMMENT '分类 如餐饮 工资', `amount` decimal(10,2) NOT NULL COMMENT '金额', `record_time` date NOT NULL COMMENT '记账时间', `remark` varchar(100) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_record_time` (`record_time`), KEY `idx_type_category` (`type`,`category`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='记账记录表';
核心功能实现
记账数据录入
首先需要实现数据录入的DAO层方法,这里使用JDBC操作数据库,示例代码如下:
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDate;
public class AccountRecordDao {
// 新增记账记录
public boolean addRecord(Connection conn, int type, String category, BigDecimal amount, LocalDate recordTime, String remark) throws SQLException {
String sql = "INSERT INTO account_record (type, category, amount, record_time, remark) VALUES (?, ?, ?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, type);
ps.setString(2, category);
ps.setBigDecimal(3, amount);
ps.setObject(4, recordTime);
ps.setString(5, remark);
int rows = ps.executeUpdate();
ps.close();
return rows > 0;
}
}
收支统计功能
按月份统计收支的SQL语句和对应Java实现如下:
-- 按月份统计收支总额
SELECT
DATE_FORMAT(record_time, '%Y-%m') AS month,
type,
SUM(amount) AS total_amount
FROM account_record
WHERE record_time BETWEEN ? AND ?
GROUP BY month, type
ORDER BY month ASC;
对应的Java查询方法:
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class AccountStatService {
// 按时间范围统计收支
public List<StatResult> statByTimeRange(Connection conn, LocalDate startTime, LocalDate endTime) throws SQLException {
List<StatResult> resultList = new ArrayList<>();
String sql = "SELECT DATE_FORMAT(record_time, '%Y-%m') AS month, type, SUM(amount) AS total_amount FROM account_record WHERE record_time BETWEEN ? AND ? GROUP BY month, type ORDER BY month ASC";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, startTime);
ps.setObject(2, endTime);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
StatResult result = new StatResult();
result.setMonth(rs.getString("month"));
result.setType(rs.getInt("type"));
result.setTotalAmount(rs.getBigDecimal("total_amount"));
resultList.add(result);
}
rs.close();
ps.close();
return resultList;
}
}
// 统计结果实体类
class StatResult {
private String month;
private int type;
private BigDecimal totalAmount;
// 省略getter setter方法
}
报表生成
使用JasperReports生成PDF报表的核心代码示例:
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.pdf.JRPdfExporter;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReportService {
// 生成收支统计PDF报表
public void generatePdfReport(Connection conn, List<StatResult> statData, String outputPath) throws Exception {
// 编译jrxml模板文件
String jrxmlPath = "src/main/resources/stat_report.jrxml";
String jasperPath = JasperCompileManager.compileReportToFile(jrxmlPath);
// 填充报表数据
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(statData);
Map<String, Object> params = new HashMap<>();
params.put("reportTitle", "个人收支统计报表");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPath, params, dataSource);
// 导出为PDF
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputPath));
exporter.exportReport();
}
}
项目测试与优化
完成核心功能开发后,需要进行功能测试,验证记账录入、查询、统计、报表生成等功能是否正常。同时可以针对数据库查询做优化,比如给常用的查询字段添加索引,避免全表扫描。如果是桌面端工具,还可以添加数据备份功能,防止数据丢失。
总结
开发个人记账报表工具可以覆盖Java开发中的多个核心知识点,从基础的JDBC操作、面向对象编程,到数据库设计、第三方库使用,都是实际开发中常用的技能。开发者可以在基础功能之上扩展更多功能,比如添加预算管理、多用户支持、图表可视化等,进一步提升项目的完整度。