# Datenbankzugriffe über JAX-WS und JPA



## musiKk (10. Feb 2010)

Hallo,

ich wusste nicht, ob Data Tier oder SOA, drum hab ichs zu allgemein.

Ich möchte Zugriffe auf eine Datenbank über einen Webservice kapseln. Der Webservice nutzt serverseitig JPA um mit der Datenbank zu kommunizieren. Die Entity-Klassen, die dazu erstellt werden, sind auch die, die über den Webservice verschickt werden. Daher zunächst mal: Ist das eine gute Idee? Ich wollte es nämlich vermeiden, noch ein separates Modell zu erstellen, weil das ja eh fast nur kopiert wäre. Außerdem wäre die Konvertierung DB-Modell -> XML-Modell ja nochmal aufwändig.

Weiterhin bekomme ich Probleme, wenn es um Objektbeziehungen geht und davon gibt es reichlich. Im konkreten Fall habe ich eine ManyToMany-Beziehung. Der Owner der Beziehung soll über den Webservice angefragt werden können. Wird ein solches Objekt dann über den Webservice verschickt, wird die ManyToMany-Beziehung immer aufgelöst. Ob der FetchType LAZY oder EAGER ist, spielt keine Rolle - spätestens wenn die Objekte auf dem Server serialisiert werden, findet die Auflösung ja statt (und bei LAZY gibts noch ganz andere Probleme, weil die Transaktion schon weg ist: [c]failed to lazily initialize a collection of role: pkg.Category.items, no session or session was closed[/c]). Das spricht ja dann doch wieder für ein getrenntes Model; das Nachladen der referenzierten Daten sollte auch über den Webservice erst nachträglich erfolgen können. Wie geht man einen solchen Fall am sinnvollsten an?

Weil DIA mein Lieblingsprogramm ist, habe ich mal ein kleines Bild dazu gemalt. In dem Fall ist das Problem, dass ich die Items einer Category gerne auch lazy über den Webservice behandeln möchte...

Vielleicht kann mich ja jemand erleuchten.

Danke schonmal
mK


----------



## Gelöschtes Mitglied 5909 (10. Feb 2010)

ich würde Entity und JAXB Transfer Objekt trennen. Dann bist du felxibler, wenn du z.B. mal kompliziertere Anfragen machen willst und das normale Entity Bean nicht ausreicht. 

Außerdem hast du dann clientseitig keine dependency zum Server. (oder baust du nur den server?)

Desweiteren kannst du dadurch ggf requests sparen und dadurch die performance verbessern. Statt die ganzen Item Objekte reinzuhauen würde ich nur die Ids dazupacken und die auch in einer query laden (nur die Ids).

Ich würde so ein To nehmen:


```
<categoryList>
<category>
   <id>1</id>
   <items>1 2 3 4 5 6 7 8</items>
</category>

<category>
   <id>2</id>
   <items>10 11 12</items>
</category>
</categoryList>
```

die items so als Liste zu serialisieren geht einfach mit @XmlList.

Dann kannst du dir noch einen Service bauen der 1-n Items lädt und die Ids wieder übergeben.
Kommt aber auch drauf an wie oft du die Items brauchst und wie "groß" die sind.

Wenn du nicht immer alle infos brauchst, dann kannst du auch noch die Namen oder so + Ids adden.
Dann würde ich an deiner Stelle mit JSon arbeiten, geht ja ganz easy


```
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
```

Wenn du des dann im browser ankuckst kriegst du xml und beim client würde ich den content type json setzen


----------



## musiKk (11. Feb 2010)

Hi raiL,

danke für Deine Antwort.



raiL hat gesagt.:


> ich würde Entity und JAXB Transfer Objekt trennen. Dann bist du felxibler, wenn du z.B. mal kompliziertere Anfragen machen willst und das normale Entity Bean nicht ausreicht.



Ok, das ist schonmal eine Aussage. Ich dachte bisher, dass das nicht so gut ist, weil das Mapping zwischen Entity und TO ja nur wieder viel manuelle Arbeit mit sich führt. Da müsste man sich doch überlegen, ob man überhaupt JPA einsetzt. Per JDBC könnte man ja gleich das TO entsprechend der Anforderungen füllen (wobei da zugegebenerweise wieder die Kopplung zwischen Service und DAO stark wird).
Wenn ich mir das so vorstelle, kommt etwas in der Art heraus (wieder auf mein Lieblingsbeispiel Category/Item übertragen und mit ausgeschriebenen Packagenamen):

```
@WebService(...
public class DbService {

	@EJB
	private MyDao dao;

	public pkg.to.Category getCategoryByName(String name) {
		pkg.dao.Category daoCat = dao.getCategoryByName(name);
		pkg.to.Category toCat = new pkg.to.Category();
		toCat.setName(daoCat.getName());
		// toCat.set(... usw
		return toCat;
	}
	
}
```
Und das dann für recht viele verschiedene Klassen. Irgendwie kommt mir das recht umständlich vor, selbst wenn man das ganze in ein Converter-Objekt auslagert. Vielleicht denke ich da aber auch noch etwas in die falsche Richtung.

Was aber wieder für ein separates Modell spricht, ist, dass JAXB im Gegensatz zu JPA offenbar nicht mit Zyklen im Objektgraph zurechtkommt. Da muss also so oder so eingegriffen werden.



> Außerdem hast du dann clientseitig keine dependency zum Server. (oder baust du nur den server?)


Letzten Endes wird sowohl Server als auch Client von uns erstellt. Der Ausgangspunkt ist bisher jedoch der Service. Der Service-Client wird über [c]wsimport[/c] generiert und dann in eine Anwendung eingebunden.



> Desweiteren kannst du dadurch ggf requests sparen und dadurch die performance verbessern. Statt die ganzen Item Objekte reinzuhauen würde ich nur die Ids dazupacken und die auch in einer query laden (nur die Ids).



Ja, das ist eine Möglichkeit. Ich habe JPA bisher vor allem clientseitig eingesetzt und es möglichst vermieden, mich explizit mit IDs zu beschäftigen. Bei dem Service ist das aber vielleicht wirklich besser.

Das waren schonmal gute Anregungen. Wenn ich noch weitere Probleme habe, werde ich es euch schon wissen lassen.


----------



## Gelöschtes Mitglied 5909 (15. Feb 2010)

Für das mapping kannst du dir ggf. Mit reflection behelfen. Wenn beides gleich ist kannst du die Felder einfach per reflection kopieren, ansonsten kannst du einen custom mapper verwenden.

edit: ich las grad es geht ja um jax-ws und nicht jax-rs wie ich erst dachte, macht aber warscheinlich keinen unterschied


----------



## musiKk (15. Feb 2010)

Ja, darüber hatte ich auch nachgedacht. Sogar kurz so weit, eigene Annotations dafür zu verwenden. Nur dann hätte ich ein Mapping von SQL nach Entities und dann noch eins zu den TOs und dann noch eins von dort zu XML ...

Ich habe mir von Suns Beschreibung mehr oder weniger die erste Variante genommen; jedes Objekt ist selbst dafür zuständig, ein geeignetes TO zu erzeugen. Das klappt bisher eigentlich ganz gut.


----------



## megachucky (1. Mrz 2010)

> Letzten Endes wird sowohl Server als auch Client von uns erstellt. Der Ausgangspunkt ist bisher jedoch der Service. Der Service-Client wird über wsimport generiert und dann in eine Anwendung eingebunden.



Wenn ihr beides erstellt (und vermutlich beides in Java realisiert wird), wieso dann überhaupt Web Services? Diese würde ich nur verwenden, wenn
a) der Client nicht in Java realisiert wird oder
b) der Client von anderen Firmen / Partnern implementiert und verwendet wird.

Auf Server-Seite EJB in Kombination mit JPA und auf dem Client ein Application Client würden meiner Meinung nach ausreichen, sofern obiges nicht erfüllt ist...


----------



## musiKk (6. Mrz 2010)

Das kann schon sein. Ich habe als Anforderung bisher jedoch immer Webservice erhalten. Dadurch sollte man ja auch bei Änderungen flexibler bleiben.


----------

