# Umgang mit hsqldb



## Alex_winf01 (17. Nov 2007)

Ich schreibe ein Java-Programm, indem ich eine hsqldb-Datenbank mitliefere. Da dieses Programm mehrbenutzerfähig sein soll, muss es ja im Server-Modus laufen. Nun liefere ich das Programm mit der Datenbank auf CD-ROM aus. Während der Entwicklung stelle ich die DB einfach auf Server um (mithilfe der GUI-Oberfläche).

Nun muss man das ja auch beim Kunden machen (hsqldb mitliefern im Server-Modus) und der Systemadministrator beim Kunden muss auch verschiedene Anwender anlegen können. D. h. der Anwender hat dann eine Schaltfläche "Neuen Anwender anlegen".

Meine Frage:

wie kann ich das 

a) während der "Installation" des Programms auf den Server-Status umschalten? Oder kann ich die hsqldb bereits im Server-Modus ausliefern?
b) wie kann ich bei einer hsqldb-Datenbank umsetzen, dass der Anwender (Systemadministrator) auch neue Anwender anlegen kann? Ich hab daran gedacht, eine Tabelle Anwender create, in der dann Login-Name, Passwort, Anwendergruppe usw. gespeichert wird. Und sobald der Systemadministrator sich einloggt, wird die Schaltfläche "Neuen Anwender anlegen" aktiviert und es wird ein Insert in diese Tabelle gemacht.

Kann mir da jemand helfen?


----------



## HoaX (18. Nov 2007)

Alex_winf01 hat gesagt.:
			
		

> Meine Frage:
> 
> wie kann ich das
> 
> a) während der "Installation" des Programms auf den Server-Status umschalten? Oder kann ich die hsqldb bereits im Server-Modus ausliefern?


 indem du es entsprechend programmierst



			
				Alex_winf01 hat gesagt.:
			
		

> b) wie kann ich bei einer hsqldb-Datenbank umsetzen, dass der Anwender (Systemadministrator) auch neue Anwender anlegen kann? Ich hab daran gedacht, eine Tabelle Anwender create, in der dann Login-Name, Passwort, Anwendergruppe usw. gespeichert wird. Und sobald der Systemadministrator sich einloggt, wird die Schaltfläche "Neuen Anwender anlegen" aktiviert und es wird ein Insert in diese Tabelle gemacht.
> 
> Kann mir da jemand helfen?


siehe antwort zu a).

zu so allgemeinen fragen kann man nur so allgemeine antworten geben ...


----------



## Alex_winf01 (18. Nov 2007)

Ich habe mir folgendes Beispiel von hsqldb.org angesehen:


```
/* Copyright (c) 2001-2005, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.sample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Title:        Testdb
 * Description:  simple hello world db example of a
 *               standalone persistent db application
 *
 *               every time it runs it adds four more rows to sample_table
 *               it does a query and prints the results to standard out
 *
 * Author: Karl Meissner [email]karl@meissnersd.com[/email]
 */
public class Testdb {

    Connection conn;                                                //our connnection to the db - presist for life of program

    // we dont want this garbage collected until we are done
    public Testdb(String db_file_name_prefix) throws Exception {    // note more general exception

        // Load the HSQL Database Engine JDBC driver
        // hsqldb.jar should be in the class path or made part of the current jar
        Class.forName("org.hsqldb.jdbcDriver");

        // connect to the database.   This will load the db files and start the
        // database if it is not alread running.
        // db_file_name_prefix is used to open or create files that hold the state
        // of the db.
        // It can contain directory names relative to the
        // current working directory
        conn = DriverManager.getConnection("jdbc:hsqldb:"
                                           + db_file_name_prefix,    // filenames
                                           "sa",                     // username
                                           "");                      // password
    }

    public void shutdown() throws SQLException {

        Statement st = conn.createStatement();

        // db writes out to files and performs clean shuts down
        // otherwise there will be an unclean shutdown
        // when program ends
        st.execute("SHUTDOWN");
        conn.close();    // if there are no other open connection
    }

//use for SQL command SELECT
    public synchronized void query(String expression) throws SQLException {

        Statement st = null;
        ResultSet rs = null;

        st = conn.createStatement();         // statement objects can be reused with

        // repeated calls to execute but we
        // choose to make a new one each time
        rs = st.executeQuery(expression);    // run the query

        // do something with the result set.
        dump(rs);
        st.close();    // NOTE!! if you close a statement the associated ResultSet is

        // closed too
        // so you should copy the contents to some other object.
        // the result set is invalidated also  if you recycle an Statement
        // and try to execute some other query before the result set has been
        // completely examined.
    }

//use for SQL commands CREATE, DROP, INSERT and UPDATE
    public synchronized void update(String expression) throws SQLException {

        Statement st = null;

        st = conn.createStatement();    // statements

        int i = st.executeUpdate(expression);    // run the query

        if (i == -1) {
            System.out.println("db error : " + expression);
        }

        st.close();
    }    // void update()

    public static void dump(ResultSet rs) throws SQLException {

        // the order of the rows in a cursor
        // are implementation dependent unless you use the SQL ORDER statement
        ResultSetMetaData meta   = rs.getMetaData();
        int               colmax = meta.getColumnCount();
        int               i;
        Object            o = null;

        // the result set is a cursor into the data.  You can only
        // point to one row at a time
        // assume we are pointing to BEFORE the first row
        // rs.next() points to next row and returns true
        // or false if there is no next row, which breaks the loop
        for (; rs.next(); ) {
            for (i = 0; i < colmax; ++i) {
                o = rs.getObject(i + 1);    // Is SQL the first column is indexed

                // with 1 not 0
                System.out.print(o.toString() + " ");
            }

            System.out.println(" ");
        }
    }                                       //void dump( ResultSet rs )

    public static void main(String[] args) {

        Testdb db = null;

        try {
            db = new Testdb("db_file");
        } catch (Exception ex1) {
            ex1.printStackTrace();    // could not start db

            return;                   // bye bye
        }

        try {

            //make an empty table
            //
            // by declaring the id column IDENTITY, the db will automatically
            // generate unique values for new rows- useful for row keys
            db.update(
                "CREATE TABLE sample_table ( id INTEGER IDENTITY, str_col VARCHAR(256), num_col INTEGER)");
        } catch (SQLException ex2) {

            //ignore
            //ex2.printStackTrace();  // second time we run program
            //  should throw execption since table
            // already there
            //
            // this will have no effect on the db
        }

        try {

            // add some rows - will create duplicates if run more then once
            // the id column is automatically generated
            db.update(
                "INSERT INTO sample_table(str_col,num_col) VALUES('Ford', 100)");
            db.update(
                "INSERT INTO sample_table(str_col,num_col) VALUES('Toyota', 200)");
            db.update(
                "INSERT INTO sample_table(str_col,num_col) VALUES('Honda', 300)");
            db.update(
                "INSERT INTO sample_table(str_col,num_col) VALUES('GM', 400)");

            // do a query
            db.query("SELECT * FROM sample_table WHERE num_col < 250");

            // at end of program
            db.shutdown();
        } catch (SQLException ex3) {
            ex3.printStackTrace();
        }
    }    // main()
}    // class Testdb
```

Nun ist dieses Beispiel aber für eine standalone DB. Wie muss ich das denn im Code einstellen, dass es eine Server-DB wird?


----------



## HoaX (18. Nov 2007)

ich möchte dir schwer ans herz legen die doku zu hsqldb zu lesen bevor du sollche fragen stellt. kapitel 1 lautet nämlich "Running and Using Hsqldb" ...


----------



## Alex_winf01 (19. Nov 2007)

@ HoaX

Also in dem Kapitel steht:


```
try {
        Class.forName("org.hsqldb.jdbcDriver" );
    } catch (Exception e) {
        System.out.println("ERROR: failed to load HSQLDB JDBC driver.");
        e.printStackTrace();
        return;
    }

    Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "sa", "");
```

So weit so gut, die Zeile mit der Connection ändern ist ja kein Thema, ABER: es steht da ja auch ein paar Zeilen weiter oben:





> java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb



Führe ich das in der Kommandozeile aus, bekomme ich folgende Fehlermeldung:



> Exception in thread "main" java.lang.NoClassDefFoundError: org/hsqldb/Server


----------



## HoaX (19. Nov 2007)

dann findet er halt die klasse nicht?! sicher dass unter "../lib/hsqldb.jar" die jar-datei liegt? das sind grundlagen ...

btw kannst du den server auch aus deiner anwendung direkt starten http://hsqldb.org/doc/guide/ch04.html#N10BBC


----------



## Alex_winf01 (19. Nov 2007)

Also die jar-Datei liegt definitiv im Verzeichnis lib. Die Datei Server.java liegt allerdings standardmäßig unter 





> C:\hsqldb_1_8_0_8\hsqldb\src\org\hsqldb


.


----------



## HoaX (19. Nov 2007)

du führst aber keine .java sondern eine .class aus. und die ist im hsqldb.jar. wenn die nicht in ../lib liegt dann findet der die halt nicht also korrigiere den classpath und es tut


----------



## Alex_winf01 (19. Nov 2007)

@ HoaX

Classpath korrekt eingestellt. Steht auf dem Lib-Ordner (schon wegen dem JDBC-Treiber). Trotzdem funktioniert das nicht.


----------



## HoaX (19. Nov 2007)

zeig doch mal deinen exakten aufruf und den inhalt der im classpath stehenden verzeichnisse


----------



## Alex_winf01 (19. Nov 2007)

In der Path-Variable steht:



> c:\Programme\oracle\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Programme\CA\SharedComponents\CAUpdate\;C:\Programme\CA\SharedComponents\ThirdParty\;C:\Programme\CA\SharedComponents\SubscriptionLicense\;C:\PROGRA~1\CA\ETRUST~1;C:\PROGRA~1\CA\SHARED~1\SCANEN~1;C:\Programme\CA\SharedComponents\ScanEngine;C:\hsqldb_1_8_0_8\hsqldb\lib\;



Dann bin ich in die DOS-Eingabeaufforderung und gebe den Befehl 





> java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb


 ein.

Da findet er dann die Server-Datei nicht. Ich bin ratlos. :?  Weil als Standalone läuft das Ding ohne Schwierigkeiten.


----------



## HoaX (19. Nov 2007)

die Path-Variable hat damit nix zu tun. es geht hier um denn _CLASS_path.

ligt denn unter ../lib die hsqldb.jar?


----------



## Alex_winf01 (19. Nov 2007)

Also hier in meinem Java-Buch steht, dass man unter Windowx XP die CLASSPATH-Variable unter System, Systemeigenschaften, Umgebungsvariable PATH ändern soll.

Ich habe aber zur Sicherheit in der MS-DOS-Eingabeaufforderung auch den CLASSPATH händisch eingetragen:



> SET CLASSPATH=C:\hsqldb_1_8_0_8\hsqldb\lib\;



Anschließend Neustart -> Befehl neu eingetippt -> selbe Fehlermeldung.


----------



## HoaX (19. Nov 2007)

dann solltest du dein buch definitiv wegschmeißen.

in den path macht es höchstens sinn das "bin" verzeichnis einzugragen, so dass man von überall aus java und javac aufrufen kann.

da die classdateien im hsqldb.jar liegen musst du dieses angeben im classpath, nicht das lib verzeichnis



			
				Alex_winf01 hat gesagt.:
			
		

> So weit so gut, die Zeile mit der Connection ändern ist ja kein Thema, ABER: es steht da ja auch ein paar Zeilen weiter oben:
> 
> 
> > java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb


da stehts doch, du musst nur richtig abschreiben ... (-cp gibt den classpath an)


----------



## Alex_winf01 (19. Nov 2007)

Also muss ich dann den CLASSPATH wie folgt setzen:


```
SET CLASSPATH=C:\hsqldb_1_8_0_8\hsqldb\lib\hsqldb.jar;
```

So geht es nämlich auch nicht (schon ausprobiert).

Im übrigen: Du bist flott im antworten.


----------



## HoaX (19. Nov 2007)

lass doch mal die CLASSPATH-Variable weg. der "richtige" weg ist den path beim aufruf mit anzugeben. wie du es selbst aus deinem buch zitiert hat, mit -cp

also probier doch mal

java -cp C:\hsqldb_1_8_0_8\hsqldb\lib\hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb


----------



## Guest (19. Nov 2007)

@ HoaX

jetzt funzt es. :applaus:  :applaus:


----------



## HoaX (19. Nov 2007)

wär ich nie drauf gekommen


----------



## Alex_winf01 (19. Nov 2007)

@ HoaX

was ich noch nicht verstanden habe, wie ich den Server aus der Anwendung heraus starten kann. Ich habe das entsprechende Kapitel gelesen, aber ich verstehe es nicht. Könntest Du mir ein Beispiel geben, wie ich das aus der Anwendung heraus starte?

Dann habe ich noch eine Frage:


```
Connection con = DriverManager.getConnection("jdbc:hsqldb:hsql://hostname/musicShop", "sa", "");
```

So läuft ja die Connections für den Server. So weit so gut, ABER. Ich liefere das Programm auf CD aus. D. h. die DB liegt nicht bei uns auf dem eigenen Server, sondern das Programm wird im Netzwerk des Anwenders installiert. Und dort wird auch irgendwo im Netzwerk die Datenbank liegen. Das kann auf Laufwerk r:\, d:\ oder z:\ sein. Wie kann ich das abfangen?


----------



## Alex_winf01 (20. Nov 2007)

Kann mir keiner helfen? Ich verzweifel bald.


----------



## HoaX (20. Nov 2007)

ich weiß nicht was du da abfangen willst ... auf welchem laufwerk das ding läuft is doch wurscht. der server macht einen tcpport auf, auf den du dich verbindest.

die doku sagt


			
				hsqldb.org hat gesagt.:
			
		

> Starting a Server from your application
> 
> If you want to start the server from within your application, as opposed to the command line or batch files, you should create an instance of Server or Web Server, then assign the properties in the form of a String and start the Server.


was ist da nicht zu verstehen? zusätzlich gibts noch http://hsqldb.org/doc/src/org/hsqldb/Server.html


----------



## Alex_winf01 (20. Nov 2007)

Wenn es irgendwo auf dem Laufwerk liegt, muss ich dem doch sagen, WO die Datenbank liegt:


```
Connection con = DriverManager.getConnection("jdbc:hsqldb:hsql://hostname/musicShop", "sa", "");
```

Unter hostname kann ich ja schlecht localhost oder irgendwas fixes hinschreiben. Das sieht doch bei jedem anders aus.

Und das Problem mit dem Server aus der Anwendung heraus starten: Wie muss das Code-mäßig aussehen? Sowas wie:


```
Server server = new Server(C:\hsqldb_1_8_0_8\hsqldb\lib\hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb);
```

Kannst Du mir ein kurzes Beispiel geben?


----------



## Alex_winf01 (20. Nov 2007)

Vielleicht so:


```
public static void main(String[] args) 
{

        Testdb db = null;

        try 
        {
            db = new Testdb("db_file");
        } catch (Exception ex1) {
            ex1.printStackTrace();    // could not start db

            return;                   // bye bye
        }
}
```

Wäre das das Starten des Servers aus der Anwendung heraus?


----------



## HoaX (20. Nov 2007)

ich habe dir den link genannt zur Serverklasse, da steht doch dort welche methoden du aufrufen kannst und was diese machen. evtl solltest du erstmal die grundlagen lernen bevor du dich auf eine datenbankanwendung stürzt. btw bieten IDEs wie netbeans oder eclipse oder ... auch eine autovervollständigung an die auch die infos aus der javadoc mit anzeigen.

ich sehe immernoch kein problem mit der connection url. wenn die anderes lautet musst du dir die halt vorher entsprechend zusammenbasteln im programm, lass deine fantasie spielen!


----------



## Alex_winf01 (20. Nov 2007)

Hab schon mal ne Datenbankanwendung programmiert, allerdings mit MySQL und da musste ich den Server nicht aus der Anwendung heraus starten. Danke aber trotzdem.


----------

