# Frage zum Erfassen von hinzufügten und entfernten Objekten



## UnkiDunki (15. Mrz 2010)

Hi,

ich habe eine Frage zu einer bestimmten Umsetzung:

Eine Person hat n Adressdaten, die in der Datenbank in einer eigenen Tabelle erfasst werden und über eine andere Tabelle mit deren IDs und der Personen-IDs miteinander verknüpft werden.

Nun habe ich ein Formular, welches in Tabs die Adressdaten anzeigt und man diese ggf. löschen kann indem man das entsprechende Tab schließt. 
Wenn man dann auf "Speichern" oder "Übernehmen" klickt, sollen dann die Adressdaten bzgl. der Person aktualisiert werden.

Neue hinzugefügte Daten sind ja kein Problem, aber wie geht man mit entfernten Daten um.

1. Möglichkeit: Bevor man die vorhanden Adressdaten der Datenbank hinzufügt, löscht man zuvor alle bereits vorhandenen Adressdaten und fügt bei Löscherfolg bequem die neuen hinzu.

2. Möglichkeit: Sobald ein Tab geschlossen wird, wird ein Query abgesetzt, dass diese Adressdaten, sofern vorhanden, direkt löscht. So ist man zwar immer auf dem aktuellen Stand, aber wenn man jetzt z.B. auf "Abbrechen" geht, sind die Daten bereits "unwiederuflich" entfernt worden. Also nicht wirklich optimal.

Fazit: Die 1. Möglichkeit macht am meisten Sinn, allerdings habe ich das Gefühl, dass das ziemlich "dirty" ist, erst alle vorhandenen zu löschen und dann die INSERTs abzusetzen.
FRAGE: Gibt es da ne elegante Methode, Art und Weise, "Besitzobjekte" eines Objektes in der Art wíe oben beschrieben zu ändern bzw. aktualisieren oder wird in der Regel doch immer zur 1. Möglichkeit gegriffen?

Vielen Dank im Voraus


----------



## Firestorm87 (16. Mrz 2010)

Wie wäre es mit Option 3:

Ich merke mir, welche Daten gelöscht werden sollen und setzte den Query erst ab, wenn auf Übernehmen geklickt wird?


----------



## Gast2 (16. Mrz 2010)

Wie wäre es mit Transaktionen? Du setzt die Query ab und wenn man auf Abbrechen machst ein rollback und sonst ein commit...


----------



## UnkiDunki (16. Mrz 2010)

@Firestorm87:
Ok, wäre ne Idee... neue, noch nicht gespeicherte Tabs haben sowieso keine ID und sind beim Schließen sowieso uninteressant und für die anderen könnte ich ein Array machen, in das ich bei ihrem Schließen deren IDs hinzufüge...

@SirWayne: Ja, an Transaktionen hatte ich in der Tat auch schon gedacht, nur befürchte ich dann ein Problem mit Überschneidungen, wenn man ein anderes Objekt öffnet und das gleiche macht, da ich auf ein statisches Connection-Objekt zugreife, dass sich jeder teilt... Vielleicht nicht ganz gut gelöst, aber als ich die Datenverbindung immer bei Gebrauch neu erstellt habe, also eine Instanz, wo es noch nicht statisch war, hatte ich ähnliche Probleme mit Transaktionen...


----------



## maki (16. Mrz 2010)

> da ich auf ein statisches Connection-Objekt zugreife, dass sich jeder teilt


Aua!



> Vielleicht nicht ganz gut gelöst


Das ist keine Lösung 



> ber als ich die Datenverbindung immer bei Gebrauch neu erstellt habe, also eine Instanz, wo es noch nicht statisch war, hatte ich ähnliche Probleme mit Transaktionen...


.. die sich sicher lösen lassen


----------



## UnkiDunki (16. Mrz 2010)

Also bei jedem Einsatz der DB wieder zurückschwenken zu... ?


```
DBConnection dbCon = new DBConnection();
dbCon.connect();
con = dbCon.getConnection();
```

Denn so hatte ich es anfangs...


----------



## Gast2 (16. Mrz 2010)

Nein, nutze Connection Pooling! 

Und dann jedesmal wenn du eine Connection brauchst quasi ein [c]Connection con = pool.getConnection()[/c] Wie du dir eine Connection aus dem Pool holst hängt davon ab was für ein Pooling du nutzt.

Wenn DBConnection ein ConnectionPool ist neheme ich alles zurück


----------



## UnkiDunki (16. Mrz 2010)

Neee... brauchst nichts zurückzunehmen 

Empfiehlst du da einen speziellen Link zum Einsatz von Connection Pooling?
Bin jetzt schon mal auf Chapter 8 Continued: Connection Pooling gestoßen, was ganz i.O. zu sein scheint, gegenteilige Meinung?

Benutze H2 (embedded mode) und da habe ich folgende Klasse gefunden: MiniConnectionPoolManager - A lightweight standalone JDBC connection pool manager...

Die Frage ist, wie ich dieses dann benutze... kann doch nicht vor jedem Datenbankzugriff folgendes einbinden:


```
org.h2.jdbcx.JdbcDataSource dataSource = new org.h2.jdbcx.JdbcDataSource();
dataSource.setURL ("jdbc:h2:file:c:/temp/testDB");
MiniConnectionPoolManager poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
...
Connection connection = poolMgr.getConnection();
...
connection.close();
```

Die ersten beiden Zeilen benötige ich ja z.B. nur beim Start meines Programmes... setze ich dann das auf statische Variablen, um wenigstens darauf überall Zugriff zu haben oder wie mache ich das ganze "global"?


----------



## Gast2 (16. Mrz 2010)

UnkiDunki hat gesagt.:


> ```
> org.h2.jdbcx.JdbcDataSource dataSource = new org.h2.jdbcx.JdbcDataSource();
> dataSource.setURL ("jdbc:h2:file:c:/temp/testDB");
> MiniConnectionPoolManager poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
> ...



Hängt immer ein bisschen davon ab wie man es gerne hat 

Gerne wird z.B. ein Singleton Pattern genommen um den ConnectionManager zu wrappen


```
public final class MyConnectionManager{
 private static MyConnectionManager instance;
 private MiniConnectionPoolManager poolMgr;

 private MyConnectionManager(){
  org.h2.jdbcx.JdbcDataSource dataSource = new org.h2.jdbcx.JdbcDataSource();
  dataSource.setURL ("jdbc:h2:file:c:/temp/testDB");
  poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
 }

 public static MyConnectionManager getInstance(){
 if (instance == null ){
   instance = new MyConnectionManager();
 } 
 return instance;
 }
 
 public Connection getConnection(){
    return poolMgr.getConnection();
 }

}
```

Keine Garantie auf Tipfehler - ist nur hier im Editior zusammengeknipst. Wie du die Properties wie die URL und so setzt bleibt deiner Kreativität überlassen. 

Jetzt kannst du überall in deiner Anwendung [c]MyConnectionManager.getInstance().getConnection()[/c] aufrufen. 

Ist halt nur eine Möglichkeit.


EDIT:

Ja, der MiniConnectionPoolManager sieht ganz nützlich aus. Was man für ein ConnectionPooling verwendet hängt immer eng mit zusammen was man eigentlich vorhat. Für einfache Anforderungen scheint der die JDBC Pools ganz gut zu nutzen.


----------



## UnkiDunki (16. Mrz 2010)

Alles klar. Danke Dir! Werde das gleich ausprobieren 

UPDATE: Super, funktioniert! Jetzt komme ich wieder zum eigentlichen Thema zurück: Möglichkeit 3 oder doch mit Transaktionen lösen?
Was ist da eleganter?
Wenn wir dann mit Transaktionen arbeiten, dann muss ich ja auch sicherstellen, dass die Person während ihrer Lebenszeit EINE Connection hat, oder sehe ich das falsch?

Vielleicht dazu noch ne andere Sache, sorry wegen leicht Offtopic:

Ich arbeite ja mit Personen und deren Adressdaten wie oben zu lesen... würdet ihr grundsätzlich gefragt, in der Personenklasse eine ArrayList für Adressdaten machen und die beim Instanziieren einer Person direkt befüllen, falls die Person bereits über solche Daten verfügt oder würdet ihr das unabhängig lösen und beim Öffnen des entsprechenden Detailfensters mit "eigenständigen" Objekten ( alle Adressdaten via PersonenID instanziiert) arbeiten?
Wenn man jetzt möglichst realitätsnah programmiert, wie man ja eigentlich sollte, dann doch gleich in der Klasse Person ermitteln und
dann a la 
	
	
	
	





```
person.getAddressData.get(i)
```
 verfahren...

Das heisst aber dann, dass ich jetzt beim Schließen eines Tabs (bei Transaktion)... ja... wo führe ich dann das DELETE aus? Bzw. ich muss dann ja irgendwie die AdressDaten in der Person aktuell halten, oder nicht... mhmmm bin verwirrt...

Sorry, für die vielen Fragen, aber sonst lerne ich es nie


----------

