标准的SQLite w/ Plain Java错误:“SQL错误或丢失数据库”

时间:2022-10-29 15:44:34

I've been using ORMLite for months on Android in several different projects. It's been great! The other day I started backporting a project of mine that has a plain old java component that I parse some data, and create a sqlite database that I include in an android project.

几个月来,我在几个不同的项目中都使用了ORMLite。这是太棒了!前几天,我开始支持我的一个项目,它有一个简单的旧java组件,我解析一些数据,并创建一个我在android项目中包含的sqlite数据库。

I had been using a jdbc library to call plain sqlite statements, and when I swapped over to ormlite-jdbc with xerial's jdbc library, immediately my code throws an error when I try to create a table in a fresh database file:

我一直使用jdbc库来调用普通的sqlite语句,当我使用xerial的jdbc库交换到ormlite-jdbc时,当我试图在一个新的数据库文件中创建一个表时,我的代码立即抛出了一个错误:

Exception in thread "main" com.test.library.java.exception.BAException: java.sql.SQLException: SQL statement failed: CREATE TABLE IF NOT EXISTS `chapter` (`book` VARCHAR NOT NULL , `chapter` INTEGER , `chapter` VARCHAR NOT NULL , `_id` INTEGER PRIMARY KEY AUTOINCREMENT ) 
    at com.test.parser.Database.createTables(Database.java:109)
    at com.test.parser.Database.<init>(Database.java:81)
    at com.test.parser.runnable.TranslationParserRunnable.run(TranslationParserRunnable.java:35)
    at com.test.parser.Parser.parse(Parser.java:13)
    at com.test.parser.Main.main(Main.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.sql.SQLException: SQL statement failed: CREATE TABLE IF NOT EXISTS `chapter` (`book` VARCHAR NOT NULL , `chapter` INTEGER , `chapter` VARCHAR NOT NULL , `_id` INTEGER PRIMARY KEY AUTOINCREMENT ) 
    at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
    at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:468)
    at com.j256.ormlite.table.TableUtils.doCreateTable(TableUtils.java:442)
    at com.j256.ormlite.table.TableUtils.createTable(TableUtils.java:220)
    at com.j256.ormlite.table.TableUtils.createTableIfNotExists(TableUtils.java:61)
    at com.test.parser.Database.createTables(Database.java:102)
    ... 9 more
Caused by: java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (duplicate column name: chapter)
    at org.sqlite.DB.newSQLException(DB.java:383)
    at org.sqlite.DB.newSQLException(DB.java:387)
    at org.sqlite.DB.throwex(DB.java:374)
    at org.sqlite.NestedDB.prepare(NestedDB.java:134)
    at org.sqlite.DB.prepare(DB.java:123)
    at org.sqlite.PrepStmt.<init>(PrepStmt.java:42)
    at org.sqlite.Conn.prepareStatement(Conn.java:404)
    at org.sqlite.Conn.prepareStatement(Conn.java:399)
    at com.j256.ormlite.jdbc.JdbcDatabaseConnection.compileStatement(JdbcDatabaseConnection.java:131)
    at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:459)
    ... 13 more

To get that error, all I would have to do is:

为了得到这个错误,我需要做的就是:

public Database(File dbFile) {
    try {
      // load the sqlite-JDBC driver using the current class loader
      Class.forName("org.sqlite.JDBC");
    } catch (ClassNotFoundException e) {
      throw new BAException(e);
    }

    dbFile.getParentFile().mkdirs();
    dbFile.delete();

    String connectionName = "jdbc:sqlite:" + dbFile.getPath();
    System.out.println("Connection Path: " + connectionName);

    try {
      mConnectionSource = new JdbcConnectionSource(connectionName);
      createTables();
    } catch (SQLException e) {
      throw new BAException(e);
    }

    createTables();
  }

  private  void createTables() {
    try {
      TableUtils.createTableIfNotExists(mConnectionSource, ExampleTable.class);
    } catch (SQLException e) {
      throw new BAException(e);
    }

  }

An error is thrown when I try to create the tables. The interesting thing is, if I just use straight JDBC everything works fine:

当我试图创建表时,会抛出一个错误。有趣的是,如果我直接使用JDBC,一切都没问题:

public Database(File dbFile) {
        try {
          // load the sqlite-JDBC driver using the current class loader
          Class.forName("org.sqlite.JDBC");
        } catch (ClassNotFoundException e) {
          throw new BAException(e);
        }

        dbFile.getParentFile().mkdirs();
        dbFile.delete();

        String connectionName = "jdbc:sqlite:" + dbFile.getPath();
        System.out.println("Connection Path: " + connectionName);

try {
  Connection connection = DriverManager.getConnection(connectionName);

  Statement statement = null;
  try {
    statement = connection.createStatement();
    statement.setQueryTimeout(30);

    statement.executeUpdate(SQL.CREATE_TABLE_EXAMPLE);
    statement.executeUpdate("CREATE TABLE \"android_metadata\" (\"locale\" TEXT DEFAULT 'en_US')");
    statement.executeUpdate("INSERT INTO \"android_metadata\" VALUES ('en_US')");
  } catch (SQLException e) {
    e.printStackTrace();
  } finally {
    try {
      if (statement != null)
        statement.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

} catch (SQLException e) {
  throw new BAException(e);
}

So again, that works fine, and the equivalent using ORMLite throws a missing database exception. I spent 6+ hours trying to figure this out, and it seems like the issue lies in ormlite. I noticed when running mConnectionSource = new JdbcConnectionSource(connectionName); there is an empty database file created (at least I assume this is the line that creates it), but then I seem to lack the ability to interact with it.

同样,这很好用,而使用ORMLite的等效项会抛出一个丢失的数据库异常。我花了6个多小时来解决这个问题,似乎这个问题就在这个问题上。我注意到在运行mConnectionSource =新的JdbcConnectionSource(connectionName)时;创建了一个空数据库文件(至少我假定这是创建它的行),但是我似乎缺少与之交互的能力。

I haven't been able to find any ormlite code examples interacting with sqlite using DAO's and connection sources. It seems all the jdbc examples are done using an h2 memory database.

我还没有找到使用DAO和连接源与sqlite交互的任何orlite代码示例。似乎所有的jdbc示例都是使用h2内存数据库完成的。

Any help would be wonderful.

任何帮助都是美妙的。

Some other information: I'm building with gradle.

其他信息:我正在用gradle构建。

compile 'com.j256.ormlite:ormlite-jdbc:4.48'
compile 'org.xerial:sqlite-jdbc:3.7.2'

2 个解决方案

#1


1  

immediately my code throws an error when I try to create a table in a fresh database file:

当我试图在一个新的数据库文件中创建一个表时,我的代码立即抛出一个错误:

So on possible problem may be that you seem to be trying to write to a directory instead of a database file:

因此,可能的问题是,您似乎在试图写入一个目录而不是数据库文件:

dbFile.mkdirs();
dbFile.delete();
String connectionName = "jdbc:sqlite:" + dbFile.getPath();
...

Maybe you meant:

也许你的意思:

dbFile.getParentFile().mkdirs();

If dbFile is supposed to be a directory then you need to provide a name after the file:

如果dbFile应该是一个目录,那么您需要在文件之后提供一个名称:

String connectionName = "jdbc:sqlite:" + dbFile.getPath() + "/db.sqlite";

#2


1  

I had 2 columns with the same name. After fixing that, everything worked fine. ORMLite is wonderful.

我有两个同名的列。修好之后,一切都很顺利。ORMLite很精彩。

#1


1  

immediately my code throws an error when I try to create a table in a fresh database file:

当我试图在一个新的数据库文件中创建一个表时,我的代码立即抛出一个错误:

So on possible problem may be that you seem to be trying to write to a directory instead of a database file:

因此,可能的问题是,您似乎在试图写入一个目录而不是数据库文件:

dbFile.mkdirs();
dbFile.delete();
String connectionName = "jdbc:sqlite:" + dbFile.getPath();
...

Maybe you meant:

也许你的意思:

dbFile.getParentFile().mkdirs();

If dbFile is supposed to be a directory then you need to provide a name after the file:

如果dbFile应该是一个目录,那么您需要在文件之后提供一个名称:

String connectionName = "jdbc:sqlite:" + dbFile.getPath() + "/db.sqlite";

#2


1  

I had 2 columns with the same name. After fixing that, everything worked fine. ORMLite is wonderful.

我有两个同名的列。修好之后,一切都很顺利。ORMLite很精彩。