对比数据的痛苦
不知道你是否也像我一样,在快乐编写代码的时候,必须进行一些数据库的数据对比工作。
诚然,一般的数据差异,比如是每一行的内容不同,市场上有比较成熟的 compare2 等对比工具。
但是如果是对比数据的每一列是否相同,这个就会变得比较麻烦。
v1.0 纯人工对比
我们在做一些数据迁移等功能时,经常需要对比数据是否正确,最常见的方法就是人工一列一列的对比。
一开始老马也是这么和同事对的,对了几天之后感觉效率实在是低,而且还容易看花眼。
于是我就是琢磨,这个东西用程序对比应该会简单很多。
v2.0 半人工对比
说干就干,我花半天时间实现了一个基于 jsqlparser 可以解析类似于 insert into xxx (xx, xx, xx) values (xx, xx, xx); 的工具类。
然后对比 2 边的数据,这下对于一张表上百个字段的对比,一些变得快了许多,准确率也高了很多。
不要问我为什么会有上百个字段,这都是历史沉淀下来的瑰宝。。。
ps: insert into 语句是否通过数据库连接工具手工导出的。
后来又发现另一个问题:表太多,如果想换一个数据对比,我手工导出一遍又要花费数十分钟的时间,关键是重复且枯燥。
既然重复,那么可以使用程序实现吗?
v3.0 对比基本自动化
于是我下班后熬夜实现了这个版本: java 程序实现了数据的导出持久化,然后进行修改前后的差异对比。
下面我分享一下自己的思路,以及核心源码,文末有下载福利。
希望对你工作和学习提供帮助。
整体理念
我希望这个工具是 MVP 的理念,由简单到复杂,后期逐渐丰富特性。
要有可拓展性,目前支持 mysql/oracle/sql server 等主流数据库,用户可以定制化开发。
尽可能少的依赖,使用原生的 jdbc,不需要引入 mybatis 等框架。
核心依赖
下面列举一下我用到的核心依赖:
fastjson 用于数据持久化为 json
mysql-connector-java 数据库连接驱动
jsqlparser 辅助工具,解析 sql 使用,非必须
实现思路根据指定的 jdbc 连接信息,自动选择对应的 jdbc 实现。
执行对应的 sql,将结果解析为 map,进行 JSON 持久化
对持久化的 json 进行差异对比,展现出差异结果
有了这个思路,一切就会变得朴实无华。
当然在此之前,需要我们把代码实现出来,下面进入写BUG环节:
jdbc 实现
核心接口
考虑到后期不同数据库实现,我们统一定义一个查询接口/** * JDBC 访问层 * @author 老马啸西风 * @date 2017/8/1 */ public interface JdbcMapper { /** * 执行查询语句 * @param querySql * @return */ ResultSet query(String querySql); } 复制代码
抽象实现
这里提供了基本的抽象实现。
子类只需要实现对应的连接获取信息即可。public abstract class AbstractJdbcMapper implements JdbcMapper { protected JdbcVo jdbcVo; public AbstractJdbcMapper(JdbcVo jdbcVo) { this.jdbcVo = jdbcVo; } /** * 获取数据库连接 * @return */ protected abstract Connection getConnection(); @Override public ResultSet query(String querySql) { ResultSet rs = null; Connection connection = getConnection(); try { Statement stmt = null; stmt = connection.createStatement(); rs = stmt.executeQuery(querySql); } catch (Exception e) { System.out.println("SQL: " + querySql); throw new ExportdbException(e); } return rs; } } 复制代码
JdbcVo 连接信息
这个对象主要是数据库连接信息对象:public class JdbcVo { /** * 驱动类名称 */ private String driverClassName; /** * 数据库链接 */ private String url; /** * 用户名称 */ private String username; /** * 密码 */ private String password; //getter &