Hibernate: смешивание динамического (на основе карты) и статического (на основе bean) отображения - PullRequest
2 голосов
/ 07 июля 2010

Я работаю над программой для хранения и управления результатами теста. Тесты имеют свойства, такие как дата, продолжительность, а также результаты. Однако некоторые тесты измеряют давление, другие - температуру ... Надеюсь, вы поняли идею. Таким образом, не все тесты имеют одинаковые атрибуты.

Моей первой мыслью было извлечение результатов теста из таблицы тестов в отдельные таблицы результатов, таким образом создавая соотношение 1: 1. И чтобы результаты теста были расширяемыми, я хотел, чтобы результаты сохранялись в Картах, а не в Бинах.

Однако, похоже, что Hibernate не нравится мой подход. У кого-нибудь есть опыт работы с такого рода картографированием? Есть ли лучшая альтернатива?


РЕДАКТИРОВАТЬ для Пример и дальнейшее объяснение

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

Среднее - это одно свойство, которое может иметь тест. Поскольку другие свойства могут быть добавлены, я не хочу жестко кодировать класс Medium, а скорее отобразить его как Map, сохраняя три атрибута. Я думал, что у Test будет Map<String, Map<String, Object>> для представления всех связанных с ним свойств.

<?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>

Где com.hoerbiger.versuchsdb.hibernate.TestAccessor - это PropertyAccessor для доступа к карте, которую я хочу использовать для отношений

<?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>

Чтобы попробовать, что работает, я использовал этот основной метод. Обратите внимание на последние несколько строк

@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();
}

Что за последние строки? Это ошибка в спящем режиме или неправильная конфигурация?

1 Ответ

1 голос
/ 08 июля 2010

После небольшого дополнительного чтения я понял, в чем заключалась моя ошибка: в настоящее время мое среднее отображение выглядит так:

<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>

Но это должно выглядеть так:

<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>

проблема заключается в том, чтобы использовать «id» в генераторе и однозначное ограничение

Hibernate использует два атрибута для представления ограничения первичного ключа «один к одному», в моем случае:

  • id - это PK & FK, то есть test.getId (), Long
  • test - это ссылка на сам инородный объект

Поскольку карта небезопасна, вы можете перезаписать Long, сохраненный первым в тесте. Оба значения просто считываются в одну и ту же запись карты. Изменяя два вхождения идентификатора для проверки, ссылка имеет собственную запись и больше не перезаписывает значение идентификатора

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...