【问题标题】:DatabaseIOException When Executing Query "Delete"执行查询“删除”时出现 DatabaseIOException
【发布时间】:2012-08-10 11:21:32
【问题描述】:

谁能帮忙告诉我我的代码有什么问题?我正在尝试连接到 SQLite 数据库,并执行一些查询。尝试创建和打开数据库,创建并插入表时,没有返回异常。但是当我尝试执行删除语句时,

DatabaseIOException: 文件系统错误 (12)

总是返回。我不确切知道异常的原因。你能告诉我通常是什么导致这种异常吗?我什至不知道什么时候需要关闭数据库,什么时候不需要。 this solution 也让我很困惑。

这是我的代码:

public class DatabaseManager {

    Logger log = new Logger();
    Database db;

    public DatabaseManager() {
        createDatabase();
    }

    private void createDatabase() {

        // Determine if an SDCard is present 
        boolean sdCardPresent = false;
        String root = null;
        Enumeration enum = FileSystemRegistry.listRoots();
        while (enum.hasMoreElements()) {
            root = (String) enum.nextElement();
            if(root.equalsIgnoreCase("sdcard/")) {
                sdCardPresent = true;
            }     
        }
        if(!sdCardPresent) {
            alert("This application requires an SD card to be present. Exiting application...");
        }          
        else {    
            try {
                URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
                db = DatabaseFactory.openOrCreate(uri);
                db.close();
                //alert("Database OK!");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                //alert("Exception in createDatabase(): " + e);
            }
        }
   }

private void alert(final String message) {
    UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
            Dialog.inform(message);
            System.exit(0);
        }
    });
}

private void createTableTask() {
    try {
        URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
        db = DatabaseFactory.open(uri);
        Statement st = db.createStatement("CREATE TABLE IF NOT EXISTS t_task (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                + "client TEXT, task TEXT)");
        st.prepare();
        st.execute();
        st.close();
        db.close();
        //alert("Table Task created!");
    } catch (Exception e) {
        // TODO: handle exception
        //alert("Exception in createTableTask(): " + e);
    }
}

private void insertTableTask() {

    String[] clients = { "Budi Setiawan", "Dian Kusuma", "Joko Ahmad", "Titi Haryanto", "Wahyu" };
    String[] tasks = { 
        "Penawaran terhadap instalasi server",
        "Follow up untuk keperluan produk terbaru",
        "Pendekatan untuk membina relasi", 
        "Penawaran jasa maintenance",
        "Penawaran terhadap instalasi database" 
    };

    try {
        URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
        db = DatabaseFactory.open(uri);

        for(int i = 0; i < clients.length; i++) {
            Statement st = db.createStatement("INSERT INTO t_task (client, task) VALUES (?, ?)");
            st.prepare();
            st.bind(1, clients[i]);
            st.bind(2, tasks[i]);
            st.execute();
            st.close();

        }
        db.close();
    } catch (Exception e) {
        // TODO: handle exception
        //alert("Exception in insertTableTask(): " + e);
    }

}

public void loadInitialData() {
    createTableTask();
    insertTableTask();
}

public Cursor getTasks() {
    // TODO Auto-generated method stub
    Cursor results = null;
    try {
        URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
        db = DatabaseFactory.open(uri);
        Statement st = db.createStatement("SELECT client, task FROM t_task");
        st.prepare();
        results = st.getCursor();

        return results;
    } catch (Exception e) {
        // TODO: handle exception
        //alert("Exception: " + e);
    }

    return results;
}

public void delete(String string) {
    // TODO Auto-generated method stub

    try {
        URI uri = URI.create("/SDCard/databases/MyAdvanceUI/myadvanceui.db");
        db = DatabaseFactory.open(uri);
        Statement st = db.createStatement("DELETE FROM t_task WHERE client=?");
        st.prepare();
        st.bind(1, string);
        st.execute();
    } catch (Exception e) {
        // TODO: handle exception
        alert("Exception: " + e);
    }
    }

}

感谢您的帮助。

【问题讨论】:

  • 表示数据库连接的对象上的close 方法应始终位于finally 块内。
  • 使用 db.commitTransaction(); db.close();它可能会起作用。

标签: sqlite blackberry java-me


【解决方案1】:

我没有看到您在selectdelete 操作之后关闭语句并关闭数据库。很可能您无法打开数据库,因为它没有正确关闭。

严重警告当用户将设备作为外部驱动器安装到 PC 时,SD 卡不可用。有些设备没有预装 SD 卡。 5 个操作系统设备上的数据库操作真的很慢。您的 alert 方法代码不会关闭数据库,在下一次应用程序启动后打开它可能会出现问题。

警告正如@pankar 在评论中提到的,您应该添加finally {},您肯定会在其中关闭资源。在您当前的实现中,如果您在执行中遇到异常,您将永远不会关闭数据库。

重大改进您无需在每个循环中都创建和准备语句。只需在for 之前完成。绑定并执行每个循环。并在for 之后关闭声明。

改进 您可以在应用程序运行周期中保留一个打开的数据库。它将为您节省一些代码行和打开关闭的时间。

符号 将参数命名为“字符串”是一种不好的做法。我会将其重命名为更有意义的名称。

【讨论】:

  • 好的,感谢您的回答和建议。我非常感激。现在我只是在应用程序运行时保持数据库连接,并在应用程序关闭时关闭连接。
  • 你没有例外了吗?
  • 是的,现在它不再显示任何异常。我只是在重写方法 requestClose() 的主类(扩展 UiApplication)和 closeDatabase()(我也创建它)的构造函数中调用方法 openDatabase()(我创建的)。
猜你喜欢
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
相关资源
最近更新 更多