Pergunta

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.

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:

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:

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.

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.

Any help would be wonderful.

Some other information: I'm building with gradle.

compile 'com.j256.ormlite:ormlite-jdbc:4.48'
compile 'org.xerial:sqlite-jdbc:3.7.2'
Foi útil?

Solução 2

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

Outras dicas

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:

String connectionName = "jdbc:sqlite:" + dbFile.getPath() + "/db.sqlite";
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top