# Kleines Beispiel zur Verwendung der Derby DB in Java 6



## Thomas Darimont (14. März 2007)

Hallo,

hier mal ein kleines Beispiel wie man in einer Java 6 Anwendung die mitgelieferte Derby Datenbank verwenden kann.

Damit das Beispiel läuft muss man das derby.jar in den Classpath legen:
C:\Programme\Java\jdk1.6.0\db\lib\derby.jar


```
/**
 * 
 */
package de.tutorials;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author Tom
 */
public class DerbyEmbeddedDatabaseExample {

  /**
   * @param args
   */
  public static void main(String[] args) throws Exception {
    Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
    Properties properties = new Properties();
    properties.put("user", "user1");
    properties.put("password", "user1");
    Connection connection = DriverManager.getConnection("jdbc:derby:c:/TEMP/tutorialsDB;create=true", properties);

    createTableTestIfItDoesntExistYet(connection);
    populateTableTestIfItHasNotBeenPopulatedYet(connection);
    showContentsOfTableTest(connection);
    
    connection.close();
  }

  /**
   * @param connection
   * @throws SQLException
   */
  private static void showContentsOfTableTest(Connection connection) throws SQLException {
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM test");
    int columnCnt = resultSet.getMetaData().getColumnCount();
    boolean shouldCreateTable = true;
    while (resultSet.next() && shouldCreateTable) {
      for(int i = 1; i <= columnCnt;i++){
        System.out.print(resultSet.getString(i) +  " ");
      }
      System.out.println();
    }
    resultSet.close();
    statement.close();
  }

  private static void populateTableTestIfItHasNotBeenPopulatedYet(Connection connection) throws Exception {

    boolean shouldPopulateTable = true;
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT COUNT(*) FROM test");
    if (resultSet.next()) {
      shouldPopulateTable = resultSet.getInt(1) == 0;
    }
    resultSet.close();
    statement.close();

    if (shouldPopulateTable) {
      System.out.println("Populating Table test...");
      PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO test VALUES (?,?)");
      String[] data = { "AAA", "BBB", "CCC", "DDD", "EEE" };
      for (int i = 0; i < data.length; i++) {
        preparedStatement.setInt(1, i);
        preparedStatement.setString(2, data[i]);
        preparedStatement.execute();
      }
      preparedStatement.close();
    }
  }


  private static void createTableTestIfItDoesntExistYet(Connection connection) throws Exception {
    ResultSet resultSet = connection.getMetaData().getTables("%", "%", "%", new String[] { "TABLE" });
    int columnCnt = resultSet.getMetaData().getColumnCount();
    boolean shouldCreateTable = true;
    while (resultSet.next() && shouldCreateTable) {
      if (resultSet.getString("TABLE_NAME").equalsIgnoreCase("TEST")) {
        shouldCreateTable = false;
      }
    }
    resultSet.close();
    if (shouldCreateTable) {
      System.out.println("Creating Table test...");
      Statement statement = connection.createStatement();
      statement.execute("create table test (id int not null, data varchar(32))");
      statement.close();
    }
  }
}
```

Gruß Tom


----------



## jeipack (15. März 2007)

Thx a lot.
Nimm ich gleich mal in meine Favoriten 


```
connection.getMetaData().getTables("%", "%", "%", new String[] { "TABLE" });
```
 Macht das das gleiche wie ein SHOW TABLES?
Ahja nach der Beschreibung können die ersten zwei Pattern (die ersten zwei "%") durch null ersetzt werden, so werden trozdem alle miteinbezogen, es wird aber nicht zuerst nach einer Übereinstimmung gesucht.

Gruss


----------



## Vatar (15. März 2007)

Ich bevorzuge hierfür immer eine DataSource, da ich es persönlich etwas übersichtlicher finde.


```
public void startDatabase(String location)  {
	ds = new EmbeddedDataSource();
	ds.setCreateDatabase("create");
	ds.setDatabaseName(location); // location = "C:/Test/DB"
	try {
		ds.getConnection();
	} catch (SQLException e) {
		e.printStackTrace();
	}
}

public void stopDatabase(){
	ds.setShutdownDatabase("shutdown");
	try {
		ds.getConnection();
	} catch (SQLException e) {
		// SQLException wird immer geworfen, da nach dem Beenden keine Connection mehr
		// vorhanden ist. Designbedingte Exception
	}
}
```

Wer das ganze mal auf einem Handy/PDA laufen lassen will braucht das *EmbeddedDataSource* nur durch ein *EmbeddedSimpleDataSource* zu ersetzen.


----------



## flashray (26. April 2007)

Hallo,

warum muss derby.jar runtergeladen und eingebunden werden, wenn es schon heißt es ist in das JDK6 eingegliedert?


Vg Erdal


----------



## thieste (30. Januar 2008)

Hallo,

das Beispiel funktioniert ja ganz gut aber.. das mit den properties user und password.. haut irgendwie nicht hin.. 

Wenn ich den Benutzer/Passwort ändere oder auch ganz weglasse.. wird trotzdem der Tabelleninhalt ausgeben.. sind password und user nicht genau dafür da.. dass das nicht passiert..  create=true habe ich nach dem ersten "Lauf" auf false gestellt.. damit nicht ne neue DB angelegt wird.


----------



## Thomas Darimont (30. Januar 2008)

Hallo,

das war ja auch nur ein kleines einfaches Beispiel ;-)
Schau mal hier: (JavaDB = Apache Derby)
http://today.java.net/pub/a/2007/03/20/javadb-end-to-end-security.html

Gruß Tom


----------



## thieste (31. Januar 2008)

Hey vielen Dank.. das sind genau die Infos die ich gesucht hatte..


----------



## MusYa (18. Dezember 2008)

hey, 

mit dem Derby DB klappt es wunderbar bis auf die DELETE-Anweisung. Ich habe 2 Varianten schon durchprobiert, aber bei keinem von den 2 Varianten hat es klappen wollen. Kann mir jemand dabei weiterhelfen?


```
Statement stmt = connection.createStatement();
        String sql = "DELETE FROM myTableName WHERE colName='a'";
        stmt.executeUpdate(sql);
        stmt.close();
```
 
und


```
Statement stmt = connection.createStatement();
        String sql = "DELETE FROM myTableName WHERE colName=?";
        PreparedStatement pstmt = connection.prepareStatement(sql);
        pstmt.setString(1, "a");
        deleteCount = pstmt.executeUpdate();
```

Immer wieder bekomme ich denselben Fehler:
 "java.sql.SQLSyntaxErrorException: Column 'A' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE  statement then 'A' is not a column in the target table."


----------



## MusYa (18. Dezember 2008)

hey, 

ich hab es hinbekommen. Ich musste nur noch clearParameters(); hinzufügen.


```
PreparedStatement pstmt = con.prepareStatement("DELETE FROM bilgi WHERE ColName = ?");
pstmt.clearParameters();
pstmt.setString(1, "a");
pstmt.executeUpdate();
pstmt.close();
```


----------



## takidoso (13. August 2009)

flashray hat gesagt.:


> Hallo,
> 
> warum muss derby.jar runtergeladen und eingebunden werden, wenn es schon heißt es ist in das JDK6 eingegliedert?
> Vg Erdal



Ich wollte mich der Frage mal anschließen, da ich gerade mal versucht habe die jar Dateien zu finden, die ich in einer Java 6 Umgebung eigetnlich vermutet hätte.

Muss man derby tatsächlich nachinstallieren auch bei Java 6?
Wenn ja, was ist dann eigetnlich von Java 6 dann übernommen worden bezogen auf Derby?

mit nachbohrenden Grüßen

Takidoso


----------



## Mister D (18. September 2009)

Hallo,

ich stehe vor dem Problem (auch schon das ganze Netz abgesucht), dass ich meine (embedded) Datenbank gerne  in dem  *.jar file ausliefern möchte. 

Leider gibt es dabei aber noch ein Problem:
Der Absolute Pfad in der getConnection(..) verhindert dies! Mit dem relativen Pfad klappts aber auch noch nicht so recht. Die erzeugte DB soll unter $TARGET\db  liegen 

Fall1: absoluter pfad ==> ok
verbindung = DriverManager.getConnection("jdbc:derby:I:/workspace/test/App/db/app2008");

Fall2 : relativ zum $TARGET\bin-  ordner ==> FEHLER
verbindung = DriverManager.getConnection("jdbc:derby:../../db/app2008");

Wie muss der realitve pfad dür heissen?
Was muss ich bzgl. DERBY_INSTALL und der CLASSPATH-Var. beachten um die DB dann in dem *jar File nach aussen hin weitergeben zu können?

Danke schon mal für Eure Hilfe


----------



## Thomas Darimont (18. September 2009)

Hallo,

bei mir funktioniert folgendes Szenario:
1) Obiges Beispiel laufen lassen (damit die Datenbank erstellt wird)
2) Datenbank URL umstellen auf: "jdbc:derby:./tutorialsDB"
3) DerbyEmbeddedDatabaseExample als ausführbares Jar exportieren (derby.jar etc. in zusätzlichem Verzeichnis mitliefern) -> Export as runnable jar / copy required libraries into sub-folder.
4) In Schritt 1 erstellte Datenbank (Verzeichnis) in das Zielverzeichnis des unter 3) erstellten jars kopieren.

Schon sollte es Funktionieren.

Wenn du die db wirklich im Jar File ablegen willst könntest du mal versuchen diese über eine spezielle jar-File URL anzusprechen:
jar:file:/test.jar!tutorialsDB
Kann sein, dass du dann die DB im Read-Only Modus starten musst um Fehler zu vermeiden.

Gruß Tom


----------



## Mister D (21. September 2009)

Hallo Thomas,

vielen Dank für deine Antwort. Beruhigend zu wissen, dass es schon geht. ;-) 

Ich werde es demnächst mal auf diesem Wege versuchen.

Happy coding!


----------



## Mister D (21. September 2009)

Da fällt mir noch was ein:

In der eigentlichen App. könnte der User ja den Pfad zur DB konfigurierbar festlegen und genau dort wartet dann zb. das selbstkopierte Datenbankverz. samt aller Files auf den Zugriff. Das sollte das Problem der Weitergabe erstmal einfach lösen.

Letztendlich muss es aber auch möglich sein, die DB vor den Blicken des Users verstecken zu können. Kennt vielleicht jemand diesbzgl. Tutorials im Netz?


----------



## Mister D (21. September 2009)

@Thomas

Jetzt bin ich etwas schlauer. 
Also die Weitergabe per DB-Directory funktioniert nun super (Danke auch für die Eclipse-Tipps).

Allerdings scheint es bei der aktuellen Derby Version zu einer Abweichung in der Betrachtung des Application-Root-Directory's zu kommen?
Denn im Gegensatz zur Doku, die beschreibt, das "../meineDB" den Pfad zur $APP\meineDB sein sollte, ist es nun einfach: meineDB  (siehe unten)

statt : "jdbc:derby:./meineDB" ==> "jdbc:derby:meineDB";
Derby Version 10.5

@all
liesse sich das von jemanden bestätigen ;-)?


----------



## darie17 (12. August 2010)

Hallo zusammen,

ich habe ein bisschen gegoogelt und diesen Beitrag gefunden. Ich verwende zur Zeit Derby als Embedded DB in einer kleinen Java Applikation.

Vorab noch eine Info - benutze für dieses Projekt Netbeans 6.9, jdk1.6.0_21, Windows 7 Pro 64 Bit

So, alles funktioniert im Debug mode prima, ich kann Tabellen anlegen, Daten aus den Tabellen lesen usw.

Wenn ich aber meine Applikation mit einem Installer einpacke und es wie ein normales Programm in Program Files installiere, bekomme ich immer beim Start des Programms (wann die Verbindung zur DB stattfinden muss) eine Exception:

*Failed to create database 'C:\Program Files\MeineApp\meineDB', see the next exception for details.*

So, nach einem langen Debug habe ich folgendes festgestellt: solange ich meine Anwendung *nicht* in Program Files installiere, funktioniert alles einwandfrei. Deswegen ahne ich, es geht hier nur um Schreibrechte der Anwendung in dem Program Files Ordner.

Angenommen ich habe Recht, wie kann ich das einstellen, dass Derby, bzw. meine Anwendung Schreibrechte auf solche Ordner hat?

Vielen Dank!


----------



## dareios (3. Januar 2013)

kann ich auch mit dieser ij.bat ne datenbank erstellen, die auch einen user und ein password hat? Wenn ja, wie mache ich das in der ij.bat?


----------



## xrax (20. September 2013)

Hi all,

Hm,- ich finde meine DB nicht 

Hab das Bsp. von oben verwendet.

Wurden nun die Daten in C:\TEMP\tutorialsDB\seg0 abgelegt (könnter gemäß Datum sein) oder baut Derby noch weitere Dateien auf ?

Grüße
xrax


----------



## Thomas Darimont (20. September 2013)

Hallo,

wenn du das ursprüngliche Beispiel verwendet hast sollten die Daten am genannten Ort abgespeichert werden - habe das gerade wieder überprüft (mit JDK 1.7.0u40)

Gruß Tom


----------



## Man without Key (2. September 2014)

@thomas & Vater

Ihr habt zwei Alternative Wege aufgezeigt die Verbindung zur DB herzustellen - wo ist denn jetzt dabei der Unterschied?

Also Vergleich mit _Treiber embeddedDriver  vs.  Datenquelle mit EmbeddedDataSource-Objekt_

Grüße

Jay Jay


----------

