2010-07-07 3 views
2

Je travaille sur un programme pour stocker et gérer les résultats des tests. Les tests ont des propriétés telles que la date, la durée et aussi les résultats. Cependant, certains tests mesurent la pression, d'autres la température ... J'espère que vous avez l'idée. Donc, tous les tests n'ont pas les mêmes attributs. J'ai d'abord pensé à extraire les résultats des tests de la table de test dans des tableaux de résultats individuels, créant ainsi une relation 1: 1. Et pour que les résultats des tests restent extensibles, je voulais que les résultats soient stockés dans Maps plutôt que dans Beans.Hibernate: Mappage dynamique (basé sur la carte) et statique (basé sur le Bean)

Cependant, il semble que Hibernate n'aime pas mon approche. Quelqu'un at-il de l'expérience avec ce type de cartographie? Y a-t-il une meilleure alternative?


EDIT pour l'exemple et des explications plus

-------- 
| Test | 
|id  | 
+--------+ 
|date | 
|duration| 1  1 ---------- 
|...  | --------- | Medium | 
--------   |testID | 
        +----------+ 
        |medium | 
        |pressure | 
         ---------- 

moyen serait une propriété qu'un test peut avoir. Comme d'autres propriétés pourraient être ajoutées, je ne veux pas coder en dur la classe Medium mais plutôt la mapper en tant que Map, en stockant les trois attributs. Ma pensée était que Test aurait un Map<String, Map<String, Object>> pour représenter toutes les propriétés qui lui sont associées.

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class name="Test" lazy="false"> 

    <id name="id"> 
    <generator class="native"/> 
    </id> 

    <property name="datum"/> 

    <many-to-one name="material" class="Material"/> 

    <set name="testgeraete" table="Test_Testgeraet" lazy="false"> 
    <key column="testID"/> 
    <many-to-many column="geraetID" class="Testgeraet"/> 
    </set> 

    <!-- Here it's getting important --> 

    <one-to-one name="medium" entity-name="Medium" constrained="false" lazy="false" 
       access="com.hoerbiger.versuchsdb.hibernate.TestAccessor"/> 

</class> 
</hibernate-mapping> 

Lorsque le com.hoerbiger.versuchsdb.hibernate.TestAccessor est un PropertyAccessor pour accéder à la carte que je veux utiliser pour les relations

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">id</param> 
    </generator> 
    </id> 

    <one-to-one name="id" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

Pour essayer ce qui fonctionne, j'ai utilisé cette méthode principale. Notez les dernières lignes

@SuppressWarnings("unchecked") 
public static void main(String[] args) { 
    Session s = Helper.getSessionfactory().getCurrentSession(); 
    s.beginTransaction(); 
    //Change to dynamic session 
    s = s.getSession(EntityMode.MAP); 

    Map<String, Object> test = (Map<String, Object>) s.createQuery("from Test").iterate().next(); 
    //for me, prints "25" 
    System.out.println(test.get("id")); 

    Map<String, Object> medium = new HashMap<String, Object>(); 
    medium.put("id", test); 
    medium.put("medium", "Luft"); 
    medium.put("pressure", 40); 

    s.save("Medium", medium); 
    s.getTransaction().commit(); 
    System.out.println("---"); 
    s = Helper.getSessionfactory().getCurrentSession(); 
    s.beginTransaction(); 

    Test t = (Test) s.createQuery("from Test").iterate().next(); 
    //for me, prints "null, 2010-07-07 00:00:00.0" (Test.toString()) 
    System.out.println(t); 
    //"25" 
    System.out.println(t.getId()); 
    //"{medium={id=null, 2010-07-07 00:00:00.0, ...}}" 
    System.out.println(t.getProperties()); 
    //"true" 
    System.out.println(t.getProperties().get("medium").get("id") == t); 

    //This is really weird - hibernate loads the map with a Test stored, but when 
    //saving, it expects a Long. With this line, the Commit succeeds 
    t.getProperties().get("medium").put("id", t.getId()); 
    s.getTransaction().commit(); 
} 

Qu'est-ce qui se passe avec ces dernières lignes? Est-ce un bug en hibernation ou une mauvaise configuration?

+0

Pourquoi voulez-vous une carte si la relation est 1: 1? Je pense que montrer du code Java (un exemple de base) aiderait à comprendre ce que vous aimeriez implémenter. En outre, utilisez-vous des mappages XML ou des annotations? Et quelle version d'Hibernate (pré JPA 2.O ou pas)? –

+0

Salut!Merci pour votre aide, en essayant d'affiner ma question, j'ai appris pas mal de choses. J'emploie 3.5.3 et éditerai ma question à ce qui se passe mal maintenant –

Répondre

1

Après un peu plus readup, je travaillais ce que mon erreur était: À l'heure actuelle, mon mapping moyen ressemble à ceci:

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">id</param> 
    </generator> 
    </id> 

    <one-to-one name="id" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

Mais il devrait ressembler à ceci:

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">test</param> 
    </generator> 
    </id> 

    <one-to-one name="test" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

le problème étant d'utiliser "id" dans la contrainte de générateur et un-à-un

Hibernate utilise deux attributs pour représenter une clé primaire de contrainte un-à-un, dans mon cas:

  • id est le PK & FK, à savoir test.getId(), un long
  • test est la référence à l'objet étranger, il auto

Depuis la carte est de type pas sûr, vous peut remplacer le long stocké en premier par un test. Les deux valeurs sont simplement lues dans la même entrée de carte. En changeant les deux occurrences de id à tester, la référence a sa propre entrée et n'écrase plus la valeur de l'id

Questions connexes