6 Stimmen

Anlegen einer Datenbanktabelle, wenn sie im Java-Produktionscode nicht vorhanden ist, und Bestätigung in JUnit

Ich schreibe ein Datenbankprogramm in Java und möchte eine Tabelle erstellen, wenn sie noch nicht vorhanden ist. Ich habe gelernt über DatabaseMetaData.getTables() von Wie kann ich die Existenz einer SQL-Tabelle in Java feststellen? und ich versuche, sie zu nutzen:

private boolean tableExists() throws SQLException {
    System.out.println("tableExists()");

    DatabaseMetaData dbmd = conn.getMetaData();
    ResultSet rs = dbmd.getTables(null, null, this.getTableName(), null);

    System.out.println("TABLE_NAME: " + rs.getString("TABLE_NAME"));

    return rs.getRow() == 1;
}

Das Problem ist, dass rs.getRow() gibt immer zurück 0 auch nachdem die Tabelle erstellt wurde. Verwendung von rs.getString("TABLE_NAME") löst eine Ausnahme aus, die besagt, dass die Ergebnismenge leer ist.

Eine mögliche Lösung, die mir eingefallen ist, ist die Ausführung der CREATE TABLE Anweisung und fangen alle ausgelösten Ausnahmen ab. Die Idee, Ausnahmen für den Kontrollfluss meines Programms zu verwenden, gefällt mir jedoch nicht.

FWIW, ich verwende HSQLDB. Ich würde jedoch gerne Java-Code schreiben, der unabhängig von der RDMS-Engine ist. Gibt es eine andere Möglichkeit zur Verwendung von DatabaseMetaData.getTables() zu tun, was ich will? Oder gibt es eine andere Lösung zum Schreiben meiner tableExists() ¿método?

Hinzugefügt:

Mit Hilfe der hier gegebenen Vorschläge habe ich eine Lösung gefunden, die in meinem Produktionscode zu funktionieren scheint:

private void createTable() throws SQLException {
    String sqlCreate = "CREATE TABLE IF NOT EXISTS " + this.getTableName()
            + "  (brand           VARCHAR(10),"
            + "   year            INTEGER,"
            + "   number          INTEGER,"
            + "   value           INTEGER,"
            + "   card_count           INTEGER,"
            + "   player_name     VARCHAR(50),"
            + "   player_position VARCHAR(20))";

    Statement stmt = conn.createStatement();
    stmt.execute(sqlCreate);
}

Jetzt schreibe ich auch einen JUnit-Test, um sicherzustellen, dass die Tabelle tatsächlich erstellt wird:

public void testConstructor() throws Exception {
    try (BaseballCardJDBCIO bcdb = new BaseballCardJDBCIO(this.url)) {
        String query = "SELECT count(*) FROM information_schema.system_tables WHERE table_name = '" + bcdb.getTableName() + "'";
        Connection conn = DriverManager.getConnection(this.url);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        Assert.assertTrue(rs.next());
        Assert.assertEquals(1, rs.getInt(1));
        Assert.assertFalse(rs.next());
    }
}

Dieser Test schlägt bei der assertEquals() mit der folgenden Meldung:

FAILED: expected: <1> but was: <0>

8voto

Code-Apprentice Punkte 76629

Die Lösung, die ich gefunden habe, scheint zu funktionieren:

private void createTable() throws SQLException {
    String sqlCreate = "CREATE TABLE IF NOT EXISTS " + this.getTableName()
            + "  (brand           VARCHAR(10),"
            + "   year            INTEGER,"
            + "   number          INTEGER,"
            + "   value           INTEGER,"
            + "   card_count           INTEGER,"
            + "   player_name     VARCHAR(50),"
            + "   player_position VARCHAR(20))";

    Statement stmt = conn.createStatement();
    stmt.execute(sqlCreate);
}

Ich musste die IF NOT EXISTS an der richtigen Stelle in meiner SQL-Anweisung.

3voto

Alonso Dominguez Punkte 7592

Von der ResultSet Definition in den Java-Dokumenten:

Ein ResultSet-Objekt unterhält einen Cursor, der auf die aktuelle Zeile der Daten zeigt. Zu Beginn steht der Cursor vor der ersten Zeile. Die next-Methode bewegt den Cursor auf die nächste Zeile, und da sie false zurückgibt, wenn es keine weiteren Zeilen im ResultSet-Objekt gibt, kann sie in einer while-Schleife verwendet werden, um die Ergebnismenge zu durchlaufen.

Sie müssen also immer die next() Methode sonst getRow() wird immer Null zurückgeben, da der Cursor vor der ersten Zeile steht.

1voto

Robin Punkte 1322

Es gibt eine eingebaute mysql-Funktionalität für das, was Sie suchen: http://dev.mysql.com/doc/refman/5.0/en/create-table.html

Kurz gesagt: Einfach anhängen IF NOT EXISTS am Ende Ihrer Abfrage zur Tabellenerstellung.

Editer :
Es gibt keine allgemeine Methode, dies zu tun. Die meisten Datenbanken haben jedoch eine Tabelle information_scheme, eine Abfrage zur Ermittlung der Informationen könnte wie folgt aussehen:

SELECT count(*) FROM information_schema.system_tables WHERE table_schem = 'public' AND table_name = 'user';

Dies funktioniert mit sqlite, mysql, msql, mariadb und postgres und wahrscheinlich vielen anderen.

-2voto

user1590499 Punkte 921

Ich weiß nicht, ob das unbedingt zu Ihren Zielen beiträgt, aber als ich mit Python und MySQL auf dieses Problem stieß, fügte ich einfach eine "Drop Table"-Anweisung vor jeder "Create Table"-Anweisung ein, so dass die Ausführung des Skripts automatisch die vorhandene Tabelle löscht und dann jede Tabelle neu erstellt. Das mag für Ihre Bedürfnisse nicht funktionieren, aber es ist eine Lösung, die ich für mein ähnliches Problem erfolgreich fand.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X