-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Variable Properties
PostPosted: Wed Jun 28, 2006 3:32 pm 
Newbie

Joined: Wed Jun 28, 2006 2:57 pm
Posts: 5
Hallo zusammen!

Ich habe folgendes Problem:
ich möchte eine Artikelliste verwalten, von der ich aber die Eigenschaften nicht kenne, weil diese zur Laufzeit vom Anwender definiert werden können.

Ich kenne Hibernate bislang soweit, daß ich für Properties die jeweiligen getter/setter Methoden in den entsprechenden Java Klassen implementieren muß (z.B. get-/setName(), is-/setActivated(), ...).

Ich möchte vermeiden, zur Laufzeit die Tabellen ändern zu müssen und diese an die Properties anzupassen. Also ist meine Idee:
In der Tabelle ArticleProperties wird abgelegt, welche Eigenschaften ein Artikel haben kann. In der Tabelle Articles wird dann pro Eigenschaft eine Datenzeile abgelegt, in der die Id der Property und der entsprechende Wert liegt.

Beispielsweise definiert ein Anwender seine Artikel mit den Eigenschaften Name, Farbe und Gewicht, dann sieht ArticleProperties so aus:
Code:
propId   propName
01         Name
02         Farbe
03         Gewicht


Mit 2 Artikeln würde Articles so aussehen:
Code:
artId   propId       value
111     01             Bleistift
111     02             blau
111     03             0.010
112     01             Stuhl
112     02             schwarz
112     03             7,431
[/i]

Zur Implementierung kann ich also keine getter/setter für Farbe, Name, Gewicht erstellen, da ich diese Eigenschaften ja noch nicht kenne. Also werden diese Eigenschaften also in einer Map abgelegt:
Code:
class Article {
  private Long id;
  private Map properties = new HashMap();

  // die Article id
  private setId (Long id) {
    this.id = id;
  }
  // id = propId
  public void setProperty(Integer id, String value) {
    properties.put(id, value);
  }
  // oder
  public void setProperty(String name, String value {
    properties.put(name, value}
  }
  public int getPropertyCount() {
    return properties.size();
  }
  ...
}


Nun zu meinen 2 Problemen:
1.) Ein Artikel setzt sich aus mehreren Zeilen zusammen. Wie sieht das Hibernate Mapping aus?
2.) Kann man Hibernate überhaupt erklären, aus der einen Tabelle den Wert als Key, aus der anderen Tabelle den Wert als Value an eine Methode zu übergeben, s.d. das Setzen der Property so aussieht:
Code:
   setProperty ( "Name", "Bleistift" );

oder die Id wird mit abgelegt:
Code:
  setProperty ( 01, "Bleistift" );

und genaugenommen müßte Hibernate ja 3 Aufrufe durchführen:
Code:
  setProperty ( 01, "Bleistift" );
  setProperty ( 02, "blau"  );
  setProperty ( 03, "0.010" );

Aufgegeben habe ich in der Doku bei Kapitel 7.3.2 (Association Mappings, many to one) und bin der Meinung, ich habe noch keine Lösung für mein Problem gefunden.

Könnt ihr mir helfen?

1000 Dank für jede Idee und viele Grüße,
Christoph


Top
 Profile  
 
 Post subject: Re: Variable Properties
PostPosted: Thu Jun 29, 2006 5:15 am 
Newbie

Joined: Mon Apr 24, 2006 5:56 am
Posts: 7
Hi,

Bin mir nicht sicher ob ich dien Problem richtig verstanden habe... aber ich rede mal wie mir der Schabel gewachsen ist... und du schimpfst mich einfach wenn du der Meinung bist ich hätte dein Post nicht aufmerksam genug gelesen ;)

also...

du hast Artikel... die haben bspw ne ID, nen Namen, und was weiß ich was noch alles. Obendrein haben diese Artikel Eigenschaften. Nicht jeder Artikel definiert aber die selben eigenschaften. ZB hätte der Artikel "Bier" die Eigenschaft "Alkoholgehalt" während der Artikel "Tisch" die Property "Holzart" hätte.

Wenn das mal so stimmt dann würde das Tabellenschema folgendermaßen aussehen:

Article: (id, name, .....);
Property: (id, name, value, articleId);

Deine Java-Klasse demnach:

Code:
class Article{
  private Long id;
  private String name;
...
  private Set<Propert> properties;
}

class Property{
  private Long id;
  private String name;
  private String value;


(mapping-file trivial)

dh. du kannst dir einen Artikel aus der db holen und hast die Properties als Liste. Das ist dir aber nicht konfortabel genug, du willst ne Map.

Wenn ichs soweit mal richtig aufgefasst habe, dann dürfte der Rest auch kein Problem mehr sein.

In deiner ARtikel Klasse nimmst du ne map statt ein set und in der mapping-file steht irgendwo

Quote:
<map name="properties" lazy=... cascade=.... >
<key column="articleid"/>
<index column="name" type="string"/>
<element type="string" column="value"/>
</map>


hört sich jetzt zumindest laut meinem schlauen Buch so einfach an... hab sowas noch nie ausprobiert


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 29, 2006 3:54 pm 
Newbie

Joined: Wed Jun 28, 2006 2:57 pm
Posts: 5
dirtyharri wrote:
Bin mir nicht sicher ob ich dien Problem richtig verstanden habe...

Leider nicht ganz aber schimpfen werde ich trotzdem nicht... ;-)

dirtyharri wrote:
Nicht jeder Artikel definiert aber die selben eigenschaften.

Doch. Die definierten Eigenschaften gelten für alle Artikel. Aber der Anwender kann diese Eigenschaften selber anlegen/löschen.

Auch wenn es viel Getipper ist, erkläre ich es mal anders:
Der Anwender definiert einmal die Eigenschaften, die für alle Artikel gültig sind (Name, Größe, Gewicht, Farbe, ..., was immer der Anwender benötigt). Ich als Entwickler kenne zur Implementierung weder Anzahl noch Beschriftung.

Deshalb muß ich, wenn ich die Artikel anzeigen/ändern/anlegen möchte, selber erst mal wissen, welche Eigenschaften denn existieren, wofür die Tabelle Property herhalten soll.

Wird später mal eine Eigenschaft hinzugefügt oder gelöscht, so gilt dieses für alle Artikel.
Somit steht also in Property:
- PropertyId
- PropertyName

In der Artikel Tabelle stehen somit die Zuordnungen der jeweiligen PropertyId und dem entsprechenden Wert des Artikels:
- ArticleId
- PropertyId
- ArticlePropertyValue

Das hat dann aber zur Folge, daß z.B. bei 5 Eigenschaften, jeder Artikel aus 5 Datensätzen in der Artikel Tabelle besteht. Jeder dieser Datensätze repräsentiert jeweils eine der Eigenschaften.

Die Artikel Klasse hält somit die ArtikelId. Und da ich jede Anzahl an Eigenschaften bedienen können muß, möchte ich diese in einer Map ablegen:
Map<PropertyId, ArticlePropertyValue>

Ich hoffe, das war besser erklärt.

dirtyharri wrote:
dh. du kannst dir einen Artikel aus der db holen und hast die Properties als Liste.


Ab hier taucht ja mein Problem auf. Was ich Hibernate erklären möchte, was es eigentlich tun soll:

- hole alle Datensätze aus der Tabelle Article, bei denen die articleId identisch ist
- erstelle genau ein Objekt Article mit dieser articleId
- übergebe aus jedem dieser Datensätze propertyId und articlePropertyValue als Key/Value Paare an die Map<propertyId, articlePropertyValue)

Oder denke ich hier zu kompliziert?

Den Hinweis mit dem mapping-file (<map name=...) schaue ich mir mal genauer an. Damit kenne ich mich noch nicht aus und muß die Doku schmökern.

Da ich mich erst am Samstag wieder darum kümmern kann, werde ich mich wohl frühestens Samstag Nachmittag wieder melden können.

Wennn du mit meinen neuen Erklärungen nochmal Vorschäge hättest, würde ich mich darüber freuen.
Wenn du meinst, ich sollte die DB Struktur doch anders machen, bin ich auch da für Vorschäge offen. ;)

Bis dahin erstmal 1000 Dank und viele Grüße,
Christoph


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 30, 2006 4:51 am 
Newbie

Joined: Sun Jun 25, 2006 1:08 pm
Posts: 7
OK... Ich glaube ich verstehe... du willst mehrere Tabellenzeilen aus Artikel holen... und die irgendwie durch die scharze Box schicken in dem das Wunder passiert und ein Artikelobjekt herausbekommen.

Ich glaub dein denkfehler liegt darin, dass du nur zwei Tabellen verwenden willst. Du willst ja anscheinen in der Artikeltabelle die id auf ein Property halten... obwohl der Artikel ja mehrere Properties haben kann. Es ist ja eigentlich eine m:n-Beziehung: Ein Artikel --> mehrere Eigenschaften; eine Eigenschaft zu mehreren Artikeln.

Vorschlag daher folgendermaßen:

Articles (articleID, name, ... irgendwas);
Properties (propID, name);

Dann brauchst du eine zwischentabelle die für das mapping verantwortlich ist (welcher article hat welche properties mit welchen Werten)

Article_Property_Value (articleID, propID, value)

Man beachte den zusammengesetzten Primärschlüsse [articleID, propID]

Was du mit dem Schema machen kannst ist folgendes (angenommen das ganze soll ein dynamisches Webprojekt werden):

Der Admin loggt sich ein und sieht eine Konfigurationsmasek, wo er unter anderem einstellen kann welche Properties für das System zu verfügung stehen sollen. Er fügt jene Properties hinzu die nötig sind. Am Ende schaut die PropertiesTabelle zB so aus:

propID, name
1, Farbe
2, Größe
3, Gewicht

Danach loggt sich ein User ein und legt einen neuen Artikel an. Dazu geht er auf die Artikelmaske. Er gibt die Daten ein, drückt submit. Folgendes steht in der Artikeltabelle:

ArticleID; name
1, Haus

Danach sieht er die ausgabemaske für Artikel und da stehen eine Liste von Properties für diesen Artikel (die bisher noch leer). Unter dieser Liste ein Drop-Downfeld, ein TextFeld und ein Commit-Button. Im Drop-DownFeld befindet sich eine Liste von Strings die aus der Tabelle Properties geladen werden, also steht im Dropdownfeld Farbe, Größe, Gewicht. Man wählt eine Property, vergibt ihm mit dem Textfeld einen Wert, drückt auf submit und es wird ein neuer Eintrag in der Zwischentabelle erzeugt. zb

ArticleID, PropID, value
1, 1, grün

Bitte sag, dass das nun das ist was du brauchst.

Probleme bei dem Ganzen:
- Du kannst schwer abprüfen ob alle relevanten Properties gesetzt wurden
- Du weißt ja nicht nur nicht, welche Properties in deinem System einmal eingesetzt werden, du weißt ja auch nicht welche DAtentypen es sind. Es ist praktisch unmöglich so damit zu Arbeiten, zB weil die Operation "nach Größe sortieren" ja wissen müsste, dass die Größe eine Zahl ist.
- Dh du müsstest demjenigen der die property anlegt auch noch ein mittel in die Hand legen mit dem er den Datentyp spezifizieren kann.

Ein interessanter Ansatz wäre wenn du dem (in unserem Bsp) Admin einfach die full-qualified Java-Klasse für jede Property angeben lässt. dann kannst du auf der Java-Seite mit Class.forName(...) das jeweilige Objekt erzeugen, und die Property-Value reinschmeißen... aber das geht vorerst mal zu weit...


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 06, 2006 4:53 am 
Newbie

Joined: Wed Jun 28, 2006 2:57 pm
Posts: 5
Moin!
Entschuldigung, wenn ich mich erst jetzt wieder melde, aber ich hab noch soo viel umme Ohren, und demnächst bin ich auch noch viel unterwegens, s.d. ich nur wenig hierzu kommen werde.

d80harri wrote:
OK... Ich glaube ich verstehe... du willst mehrere Tabellenzeilen aus Artikel holen... und die irgendwie durch die scharze Box schicken in dem das Wunder passiert und ein Artikelobjekt herausbekommen.

*Jubel* Genau! Wo bekomme ich diese BlackBox? :-D

d80harri wrote:
Ich glaub dein denkfehler liegt darin, dass du nur zwei Tabellen verwenden willst.

Kein Problem, noch ne Mapping Tabelle einzubauen. Ich habe alle Freiheiten ...

d80harri wrote:
Du willst ja anscheinen in der Artikeltabelle die id auf ein Property halten... obwohl der Artikel ja mehrere Properties haben kann. Es ist ja eigentlich eine m:n-Beziehung: Ein Artikel --> mehrere Eigenschaften; eine Eigenschaft zu mehreren Artikeln.

Auch, wenn ich mich wiederhole, das Grundziel ist:
- Anwender/Administrator bestimmt die Properties, die für alle Artikel gelten
- Zur Laufzeit gibt es pro Artikel nur ein Objekt

Mein Problem bleibt halt nach wie vor:
ich[/] kenne Hibernate nur soweit, daß ich zu den Properties in der DB die entsprechenden getter/setter Methoden in meiner Objektklasse benötige. Bei mir werden aufgrund der definierbaren Artikel-Eigenschaften diese aber anonym sein. Die Lösung wird wohl wirklich Richtung set, map oder list sein, wie du es vorher schon mal vorgeschlagen hast.

d80harri wrote:
Vorschlag daher folgendermaßen:
Articles (articleID, name, ... irgendwas);
Properties (propID, name);

Dann brauchst du eine Zwischentabelle die für das mapping verantwortlich ist (welcher article hat welche properties mit welchen Werten)

Article_Property_Value (articleID, propID, value)

Man beachte den zusammengesetzten Primärschlüsse [articleID, propID]


d80harri wrote:
Was du mit dem Schema machen kannst ist folgendes (angenommen das ganze soll ein dynamisches Webprojekt werden):
[...]

Das GUI ist letztendlich noch offen, aber vorerst wird es ein MyFaces GUI werden. Könnte sein, daß mal SWING dazu kommt.

d80harri wrote:
Bitte sag, dass das nun das ist was du brauchst.

Es sieht mir so danach aus. ;)

d80harri wrote:
Probleme bei dem Ganzen:
- Du kannst schwer abprüfen ob alle relevanten Properties gesetzt wurden

Irrelevant. Nicht gesetzte Properties sind schlicht und einfach leer(-strings).

Das Datentyp-Problem wird ggf. wirklich über eingene Typenklassen definiert, wie es zum Multipizieren von Anzahl x Preis usw. notwendig wäre.

Ich danke dir vorerst vielmals!!
So [i]richtig intesiv
werde ich wohl ab Mitte August dazu kommen und bestimmt wieder Fragen stellen. ;-)
Bis dahin werde ich mit der Hibernate-Doku und der Mapping Tabelle mal sehn, ob ich mein gewünschtes Ziel erreichen werde. Aber der Credit soll hier dank deiner ausführlichen Bemühungen auf jeden Fall verteilt werden. ;)

Also nochmals vielen Dank und bis demnächst,
Christoph


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.