# Entity in Java implementieren



## Hightronicdesign (17. Mrz 2016)

Hallo liebes Forum,

kann mir jemand dabei helfen wie ich eine Entität welche ich in einem ER Diagramm festgehalten habe in Java implementieren kann ?

Konkret: Ich habe im MySQL Workbench ein ER Diagramm erstellt, welches unter anderem eine Table namens "Location" beinhaltet. In dieser Table habe ich Address VARCHAR(255) und EquipmentID INT . 

Jetzt möchte ich dass ganze eben mit Hilfe von einem Java Projekt befüllen, ändern usw.

Es ist mein erster DB Projekt mit Java, deswegen hab ich 0 Ahnung noch davon und brauche mal ein wenig Starthilfe.

Ich benutze Eclipse mit dem JDBC Connector. 

Eine Verbindung zu Datenbank selbst konnte ich schon herstellen.


Danke euch schon mal


----------



## Joose (18. Mrz 2016)

Ein ER Diagramm ist nur ein Abbild/Diagramm/Übersicht deiner Tabellen in der Datenbank. Eine Datenbank selber ist es noch nicht, diese muss dann extra erstellt werden (ich glaube mit MySQL Workbench kann man sich diese aus dem ER generieren lassen.

Die Verbindung zur Datenbank hast du nun ja. Jetzt sollte es doch kein großes Problem mehr darstellen ein Statement auszuführen welches deine Tabellen befüllt.
Wo genau liegt nun dein Problem?


----------



## Hightronicdesign (18. Mrz 2016)

Hi Joose,

genau so habe ich es bisher gemacht. Ich habe mit Workbench das Diagramm gezeichnet. Dann mir die Datenbank inkl aller Tabellen generieren lassen. Hat auch funktioniert.

Jetzt muss ich noch irgendwie rausfinden wie man dass sauber im Java Code implementieren kann.

Wenn ich eine Tabelle namens Location habe. Mache ich dann eine Location.class mit Getter und Setter welche diese Tablle verwalten kann ? Und wie sollen dann die Setter aussehen ? Kann man dort direkt die SQL Befehle unterbringen ?


----------



## SeriousD0nkey (18. Mrz 2016)

Hightronicdesign hat gesagt.:


> Wenn ich eine Tabelle namens Location habe. Mache ich dann eine Location.class mit Getter und Setter welche diese Tablle verwalten kann ? Und wie sollen dann die Setter aussehen ? Kann man dort direkt die SQL Befehle unterbringen ?



Dafür brauchst du meines Wissens nach ein ORM-Framework wie Hibernate. Da brauchst du allerdings auch keine SQL-Befehle (kannst aber auch eigene definieren), sondern das Framework übernimmt die Standardsachen für dich. Aber dafür müsstest du dich in die Dokumentation einlesen und je nach Projektziel ist dies viel zu Overhead.

Gibt aber doch ziemlich viele Tutorials wo die einfache Anbindung über JDBC mit einfachen Statements erklärt wird und wie du die Tabellen mit Daten speist.
Hier zum Beispiel:
http://www.itblogging.de/java/java-mysql-jdbc-tutorial/

Oder einfach Googlen.


----------



## Joose (18. Mrz 2016)

Hightronicdesign hat gesagt.:


> Wenn ich eine Tabelle namens Location habe. Mache ich dann eine Location.class mit Getter und Setter welche diese Tablle verwalten kann ? Und wie sollen dann die Setter aussehen ? Kann man dort direkt die SQL Befehle unterbringen ?



Ja hier werden dann Klassen für deine Tabellen gebraucht.

Wie SeriousD0nkey schon gesagt hat kann man hierzu ein ORM Framework ala Hibernate verwenden. Diese nehmen dir einiges an Arbeit ab (Beispiel: entfall der standard sql befehle, automatisches umwandeln von ResultSet zu Objekten bzw. umgekehrt, ...) sind aber für einen Anfänger vielleicht noch etwas zu kompliziert oder überdimensioniert (aber du solltest es dir auf jedenfall merken und dir später mal anschauen).

Für den Anfang würde ich aber auf einen ORM verzichten und es selber schreiben. SeriousD0nkey hat dir dazu eh schon einen Link gepostet.
Einziger Kritikpunkt bei diesem Beispiel: Es steht alles in einer Klasse drinnen, bitte nicht nachmachen. Ich würde zu einer simplemen Implementation des DAO Pattern (non generic) raten.
So hast du die SQL Statements für jede Tabelle in einer eigenen Klasse stehen.


----------



## Hightronicdesign (18. Mrz 2016)

Gut, so wollte ich es ja auch machen. Nur fehlt mir die vorstellung davon wie die Statements in der Klasse ausschauen können.
Weil bisher kenne ich nur den Klassenstil von Konstruktor  Getter&Setter. Nur wie wirkt sich dass jetzt in Kombination mit SQL aus?

Finde bisher online immer nur solche Beispiele wie SeriousD0nkey gepostet hat.

Fallen dann die Getter Setter einfach weg die man von Java eigentlich kennt ?


----------



## Joose (18. Mrz 2016)

Beispiel DAO mit deiner Klasse Location.
Die Model/Domain Klasse Location bildet die Daten ab und besitzt eben getter&setter um auf die Daten zugreifen zu können.
Die DAO Klasse selbst hat nur ein paar Methoden um eine Location in die DB einzutragen, diese zu ändern oder zu löschen. Ebenfalls können eine oder mehrere ausgelesen werden.

Anmerkungen:
Aufs ExceptionHandling habe ich bewusst verzichtet, wegen des Umfangs. Ein try/catch in den einzelnen Methoden ist sicher nicht vekehrt.
Du kannst hier natürlich beliebig viele Methoden hinzufügen für die unterschiedlichsten SELECT Statements. 
Es gibt 2 createMethoden um dir zu zeigen das du die einzelnen Werte oder aber ein Objekt übergeben kannst. Vorteilhafter wäre es schon ein konkretes Objekt zu übergeben.

Wenn du die DAO Klassen für mehrere Model Klassen schreibst wird dir auffallen das vieles sich wiederholt -> abstraktion 


```
public class Location {
   private int id;
  
   private Equipment equipment;
  
   private String address;
  
   public Location() {
   }
  
   // getter & setter
}

public class LocationDAO {
   private static final String SQL_CREATE = "INSERT INTO Locations(Adresse, EquipmentID) VALUES(? , ?)";
   private static final String SQL_UPDATE = "UPDATE ....";
   private static final String SQL_DELETE = "DELETE ....";
   private static final String SQL_READ_BY_ID = "SELECT * FROM Locations WHERE ID = ?";
   private static final String SQL_READ_ALL = "SELECT * FROM Locations";
  
   private Connection connection;
  
   public LocationDAO() {
     connection = Database.getConnection(); // hier verwendest du einfach deine Klasse, welche die Verbindung zur DB herstellt
   }
  
   public void create(String addresse, Equipment equipment) {
     PreparedStatement stmt = connection.prepare(SQL_CREATE);
     stmt.addParameter(......);
     stmt.execute();
   }

   public void create(Location l) {
     PreparedStatement stmt = connection.prepare(SQL_CREATE);
     stmt.addParameter(l.get.....);
     stmt.execute();
   }
  
   public ArrayList<Location> readAll() {    
     PreparedStatement stmt = connection.prepare(SQL_READ_ALL);
     ResultSet result = stmt.executeQuery();
     ArrayList<Location> locations = new ArrayList<>();
     while(result.hasNext()) {
       Location l = new Location();
       l.setId(result.getInt(...));
       l.setAddress(result.getString(...));
       // der schwierigere part wird hier Equipment, da diese daten aus einer anderen tabelle kommen.
       //Entweder werden diese per JOIN ins SELECT geholt, oder später per LazyLoading und eigenen DAO nachgeladen
     }
     return locations;
   }
}
```


----------



## Meniskusschaden (18. Mrz 2016)

Hier ist noch ein Tutorial, das ich ganz brauchbar finde:


----------



## Dukel (18. Mrz 2016)

Wenn du das erste mal mit Datenbanken zu tun hast würde ich etwas einfacher anfangen.
Versuche erst mal einfache SQL Dinge zu machen. Eine einfache Tabelle abfragen, Daten ändern, löschen und neue Daten schreiben.
Danach kannst du dich an komplexere Ding wie ein OR Mapper wagen.


----------



## Hightronicdesign (18. Mrz 2016)

Wow, die Video Reihe ist echt sehr geil.
Hab mittlerweile echt viel davon umsetzen können. mit dem DAO Design Pattern.

Bin jetzt schon beim letzten und eigentlichen Hauptthema um was es mir noch geht.

Wie ich oben schon erwähnt habe, habe ich 2 Tabellen:


Location
Address (VARCHAR)
EquipmentID (INT)

Equipment
OS
Brand
Model
LocationAddress


Diese beiden Entitäten habe ich bereits in meinem Programm implementiert. Zwischen den beiden Tabellen herrscht eine 1:1 Beziehung.

Genau da fehlt mir jetzt noch die Vorstellung wie so ein Beziehungsverhältnis überhaupt aussieht in einem Code.
Es soll darauf hinaus laufen, dass ein Equipment genau einer Location zugewiesen ist. Nur wie deklariere ich sowas ?
Brauche ich dafür noch ein weiteres Feld in den Tabellen welche dass irgendwie wie eine Art Variable identifizieren kann ?

Danke euch echt für die tolle Hilfe !!


----------



## Joose (18. Mrz 2016)

Hightronicdesign hat gesagt.:


> Genau da fehlt mir jetzt noch die Vorstellung wie so ein Beziehungsverhältnis überhaupt aussieht in einem Code.
> Brauche ich dafür noch ein weiteres Feld in den Tabellen welche dass irgendwie wie eine Art Variable identifizieren kann ?



Du hast einfach 2 Klassen (Location und Equipment). Die eine Klasse hat eine Instanzvariable vom Typ der anderen Klasse.

```
public class Location {
   private String address;
   
   private Equipment equipment;
   .....
}

public class Equipment {
   private String os;
   ....
}
```

Natürlich könntest du es auch genau andersrum machen (Equipment referenziert ein Location Objekt).
Da kommt es dann eher darauf an wie diese Abhängigkeit real dargestellt werden kann. Kann ein Equipment ohne Location bestehen oder nicht?
Anderes Beispiel: KFZ und KFZ-Kennzeichen. Hier würde ich das KFZ ein KFZKennzeichen referenzieren lassen.

Aber es man könnte natürlich eine Ringreferenz erzeugen. Sprich die beiden Objekte referenzieren sich gegenseitig.
Das Problem bei solchen Ringreferenzen ist das man sich möglicherweise ungewollt Endlosschleifen baut 
Beispiel: Für Debugzwecke überschreibst du in beiden Klassen die "toString()" Methode und gibst dort alle Attribute aus. Die "toString()" Methoden der beiden Klassen werden sich nun sooft gegenseitig aufrufen bis das Programm mit einem Fehler (StackOverflow) abstürzt. Hier sollte man also vorsichtig sein


----------



## Hightronicdesign (18. Mrz 2016)

Ok , hab ich mal so angelegt.

Wenn ich für Location einen neuen Eintrag erstelle, geht es.
Nur wenn ich dann für Equipment einen Eintrag anlegen möchte kommt folgendes :


```
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`mydb`.`equipment`, CONSTRAINT `fk_Equipment_Location1` FOREIGN KEY (`Location_Address`) REFERENCES `location` (`Address`) ON DELETE NO ACTION ON UPDATE NO ACTION)
    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:404)
    at com.mysql.jdbc.Util.getInstance(Util.java:387)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
    at at.fhjoanneum.model.EquipmentDAO.addEquipment(EquipmentDAO.java:30)
    at at.fhjoanneum.Main.Main.main(Main.java:30)
```

Wieso sagt der mir irgendwas über die Foreign Keys , die möchte ich doch nicht ändern eigentlich.

So sieht die erstellung aus :


```
locationDAO.addLocation(new Location("Hauptstrasse 1", 1));
            equipmentDAO.addEquipment(new Equipment("Windows 10", "Asus", "Ultrabook", "Hauptstrasse 1"));
```


----------



## Joose (18. Mrz 2016)

Du verletzt eine Fremdschlüsselbeziehung.
Verwendest du die gleiche Verbindung bzw. Transaktion zum Hinzufügen der Daten? Oder machst du jeweils in den DAOs unterschiedliche Verbindungsobjekte auf?
Damit würdest du die Daten auf 2 unterschiedlichen Connections und Transaktionen hinzufügen wollen. Aber die eine Transaktion bekommt solange nichts mit von den Änderungen der anderen Transaktion, bevor diese nicht commited wird.

Lösung: Nachdem du Location hinzugefügt hast musst du entweder deine Verbindung wieder sauber schließen (was ein commit zur Folge haben sollte) oder du sagst selber commit. Danach solltest du ohne Probleme dein Equipment eintragen können.
Oder du verwendest für beide DAOs die gleiche Verbindung + Transkation


----------



## Hightronicdesign (18. Mrz 2016)

Hmmm, klingt schon logisch.

Mein addLocation baut sich wie folgt auf :


```
public void addLocation(Location location) throws SQLException
    {
     
        Connection conn = Database.getInstance().getConnection();
     
        PreparedStatement p = conn.prepareStatement("INSERT INTO location (Address, EquipmentID) VALUES (?,?)");
     
        p.setString(1, location.getAddress());
        p.setInt(2, location.getEquipmentid());
     
        p.executeUpdate();
     
        p.close();
     
    }
```

Nur wenn ich dann am Ende noch Database.getInstance().disconnect(); eintrage sagt er mir dass keine Operation mehr erlaubt ist. Oder gibt es für den Commit eine eigene Variante ohne die Verbindung zur DB komplett zu trennen zwischen den Einträgen ?

EDIT. Hoppla, hab übersehen dass am Ende ein conn.close() fehlt

EDIT2: Dennoch kann ich es nicht kappieren, ich habe das conn.close() in der addEquipment Methode eingetragen, welche nach addLocation aufgerufen wird und es funktioniert. Warum ? War das etwa genau das Thema dass die eine geöffnete Verbindung aufrecht bleibt bis alles fertig ist ?


----------

