1

私はこのような単純なクラスを持っています:

@DatabaseTable(tableName = "VlpTag")
public class VlpTag implements Serializable {

    private static final long serialVersionUID = -4912974444196844860L;

    @DatabaseField(generatedId = true)
    private int id;

    @DatabaseField(foreign = true, columnName = "buid", canBeNull = false, foreignAutoCreate = true, foreignAutoRefresh = true)
    private VlpVirtualApp vApp;

    @DatabaseField
    private long lastUpdated;

    @DatabaseField(index=true)
    private String tagValue;

    @DatabaseField(dataType = DataType.ENUM_INTEGER)
    private TagType tagType;

    public static enum TagType {
        UUID, TAG
    };

    public VlpTag() {
        // needed by ormlite
    }
}

次に、TableUtils を使用してテーブルが存在しない場合は作成します。

TableUtils.createTableIfNotExists(MySQLConnection.getInstance()
            .getConnection(), VlpTag.class);

テーブルが存在しない場合は問題ありません。テーブルが存在しても、ORMLite はインデックスが存在するという例外を発生させます。

java.sql.SQLException: SQL statement failed: CREATE INDEX `VlpTag_tagValue_idx` ON `VlpTag` ( `tagValue` )
    at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
    at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:464)
    at com.j256.ormlite.table.TableUtils.doCreateTable(TableUtils.java:440)
    at com.j256.ormlite.table.TableUtils.createTable(TableUtils.java:220)
    at com.j256.ormlite.table.TableUtils.createTableIfNotExists(TableUtils.java:61)
    at com.banctecmtl.ca.vlp.controller.listvmupdater.DatabaseUpdater.<init>(DatabaseUpdater.java:47)
    at com.banctecmtl.ca.vlp.controller.listvmupdater.ListVMUpdater.<init>(ListVMUpdater.java:42)
    at com.banctecmtl.ca.vlp.controller.VlpController.<init>(VlpController.java:75)
    at com.banctecmtl.ca.vlp.view.webview.server.VlpControllerServiceImpl.init(VlpControllerServiceImpl.java:32)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)
    at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:256)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
    at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:616)
    at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
    at com.google.gwt.dev.shell.jetty.JettyLauncher$WebAppContextWithReload.doStart(JettyLauncher.java:468)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
    at org.mortbay.jetty.handler.RequestLogHandler.doStart(RequestLogHandler.java:115)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
    at org.mortbay.jetty.Server.doStart(Server.java:222)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
    at com.google.gwt.dev.shell.jetty.JettyLauncher.start(JettyLauncher.java:672)
    at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
    at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1068)
    at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:811)
    at com.google.gwt.dev.DevMode.main(DevMode.java:311)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Duplicate key name 'VlpTag_tagValue_idx'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1362)
    at com.j256.ormlite.jdbc.JdbcCompiledStatement.runExecute(JdbcCompiledStatement.java:62)
    at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:458)
    ... 29 more

このバグは既にバグ リストで報告されており、同じ問題を抱えているため、解決されたのではないかと考えていました。私はMYSQLとormlite-core-4.33.jar.

ここで私が間違っていることはありますか、それとも問題がありますか?

ありがとう

4

1 に答える 1

1

この問題の修正を追加しました。https://github.com/ethangui/ormlite-core-4.42-sourcesを参照してください。

CREATE TABLE ステートメントの作成時

元のソリューション:

PRIMARY KEY ステートメントを追加した後:

CREATE TABLE IF NOT EXIST table_name ...columns... PRIMARY KEY (id)

それは連結します:

,CREATE INDEX index_name ON column name;

これにより、本質的に 2 つの別個の SQL クエリになります。最初にテーブルを作成し、次にインデックスを追加します。適切なテーブルが既に存在しない限り、期待どおりに機能します-テーブルを作成し、インデックスを追加します。このような場合、最初のステートメントは何も実行しませんが、2 番目のステートメントは引き続きインデックスを作成しようとしますが、その後失敗します。

私の解決策: CREATE TABLE の後に別のクエリを追加する代わりに、最初のステートメント内に ADD INDEX を移動しました。したがって、

CREATE TABLE IF NOT EXIST table_name ...columns... PRIMARY KEY (id)

それから

,KEY index_name (column_name);

したがって、テーブルが存在する場合、ステートメント全体がスキップされるため、テーブルもインデックスも作成されません。

注意事項:

  1. 現在、実装では、インデックスを追加するための index=true データ フィールド アノテーションのみがチェックされます。

  2. テーブルがインデックスなしで事前に存在する場合、ステートメント全体がスキップされるため、インデックスは追加されません。

  3. MySQL でのみテストされています。

于 2012-11-07T19:30:55.783 に答える