Java实现SQLite数据库克隆

题目要求

Write a program (in Java and using JDBC) that clones a SQLite database and produces a textual “backup” of the contents. This textual backup should consist of SQL statements that will recreate the contents of the original database i.e. CREATE TABLE and INSERT … INTO instructions. Ideally, you should be able to recreatLe the original database by using the text files your program produces as input to SQLite. Your program must NOT use the system schema tables found in SQLite; any access to schema information must use the appropriate JDBC methods.

编写一个程序(使用Java和JDBC)克隆一个数据库并生成一个“备份”文本文件。此备份文本应该由sql语句组成,这些语句将重新创建原始数据库的内容,即create table和insert into指令。理想情况中,这些语句能被作为SQLite的输入来重新构建数据库。您的程序中不应该使用.schema去获取SQLite的内容,任何内容的获取都应该通过JDBC来实现

过程整理

每次拿到一个看起来复杂的需求时,都应该充分理解题目并把其分为互不干扰的几个部分,然后对每一部分再具体分析解决问题。

在本题中主要的内容是获取数据库中的内容并将其复制到一个新的数据库,同时还需要将生成的一些sql语句记录下来。

复制数据库可以被分为三个主要步骤

  1. 数据库中表结构的构建
  2. 表中数据的读取
  3. 读取到的数据传入新数据库中

而记录sql则需要在每一次执行sql语句前将其记录下来,并输出到文本中

让我们进一步整理一下技术要点
(特别注意:将会使用一些SQLite特有的方法,不通用于其他数据库系统)

在读取表结构时,可以使用一个非常好用的方法

  • select * from sqlite_master WHERE type = “table”;

此语句能够直接获取到表的名字和建表的语句,即你不需要使用metadata去繁杂的操作一个个获取字段再组装成sql语句,也不用考虑主键,外键,联合主键的判断问题。且当此语句读取到的表不需要考虑外键问题,它会按照表最初被添加的顺序排序,可以直接执行。
而如果你将table换成index,你则可以获取到所有表的建立索引语句,同样可以直接执行,但要注意的一点是SQLite中如果自动为该表建立了主键索引,查询到的数据会显示为sqlite_autoindex_表名,而不会显示具体的索引语句(因为根本没有主动建立索引,是系统自动添加的)

在读取数据时,我们对于每一个读取到的数据的插入都要对应表中的结构,所以我们可以构建两个StringBuilder对象用于构建结构和数据,在拼接sql语句时只用

  • insert into 表名(keyString) values(valueString);

而实际上的结果就会是

  • insert into 表名(‘字段1’,‘字段2’,‘字段3’…) values(‘数据1’,‘数据2’,‘数据3’…);

这里我建议将每一个数据和字段都用单引号包裹起来,这样数据中如果有双引号则不需要处理,如果有单引号则用两个单引号转义代替即可。

而到了输出文本部分,通过File类和输出流在每次执行语句之前或之后记录下来即可,这里我选择使用PrintStream类,因为其能更方便的将异常信息记录下来(通过e.printStackTrace(printStream))

大体的过程就整理完成了,现在就可以开始分部编写代码了

分步实现

首先就是整体的框架部分

public class CopyDB {
    // 文件类,用于生成文本
    private static File file; 
    // 输出流
    private static PrintStream printStream;


    public static void main(String[] args){
        // SQLite数据库地址
        String location = "jdbc:sqlite://e:\\LU\\";
        // 数据库的名字,注意带上.db
        String database = "Chinook.db";
        // 准备两个连接,一个连接被克隆的数据库,一个用于创建新数据库
        Connection conn, newConn;
        // 提前准备好,用于适应try-catch
        PreparedStatement ps;
        ResultSet rs;

        try{
            // 获取数据库名,去掉最后的.db
            String databaseName = database.substring(0,database.length()-3);
            // 创建文件
            file = new File("e://LU//"+databaseName+"Data.txt");
            file.createNewFile();
            // 绑定输出流
            printStream = new PrintStream(file);

            // 加载驱动
            Class.forName("org.sqlite.JDBC");
            // 绑定连接
            conn = DriverManager.getConnection(location+database);
            newConn = DriverManager.getConnection(location + "new" +database);

            // 在新连接中创建表结构
            ps = conn.prepareStatement("select * from sqlite_master WHERE type = \"table\";");
            rs = ps.executeQuery();
            createStructure(rs,newConn);

            // 在新连接中创建索引
            ps = conn.prepareStatement("select * from sqlite_master WHERE type = \"index\";");
            rs = ps.executeQuery();
            createIndex(rs,newConn);

            // 这里是为了获取表名
            ps = conn.prepareStatement("select * from sqlite_master WHERE type = \"table\";");
            rs = ps.executeQuery();

            // 对所有的表依次转移数据
            String tableName;
            while (rs.next()) {
                tableName = rs.getString(2);
                ps = conn.prepareStatement("select * from '" +tabl
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值