Hibernate - Как сопоставить новый класс с двумя существующими таблицами - PullRequest
1 голос
/ 06 сентября 2010

У меня есть две сущности: классы Транспортного средства и Оружия.Они сопоставлены соответственно с Vehicle.hbm.xml и Weapon.hbm.xml.Оба имеют свои соответствующие DAO.Все работают нормально.

Вот моя идея.Я хочу создать класс VehicleWeapon, который имеет все свойства сущностей Vehicle и Weapon.Я хочу объявить файл отображения Hibernate: VehicleWeapon.hbm.xml.Я хочу, чтобы свойства в файле сопоставления совпадали со свойствами сущностей Оружие и Автомобиль.

Чтобы при добавлении, удалении или сохранении сущности VehicleWeapon соответствующие изменения отражались на вспомогательной машине и оружии.столы.(Я мог бы, вероятно, выполнить запрос HQL, но сначала я хочу узнать, выполнима ли идея, которую я задаю).

Возможно ли это?Если да, можете ли вы показать мне пример?(Конечно, классы «Автомобиль» и «Оружие» - это гипотетические классы. У меня есть реальный сценарий, в котором мне нужно реализовать эту идею).

Или какие есть лучшие варианты?Можете ли вы предоставить прямую ссылку или конкретный пример?Большое спасибо.

Ответы [ 4 ]

1 голос
/ 06 сентября 2010

Я нашел рабочее решение.Как я упоминал ранее, мне не разрешено изменять сущности Транспортное средство и Оружие и соответствующие файлы сопоставления.Ни одна аннотация не допускается.

Я нашел этот ответ по предложению Googling Ben выше, что привело меня к следующим статьям: http://www.mkyong.com/hibernate/hibernate-one-to-one-relationship-example/ и http://www.vaannila.com/hibernate/hibernate-example/hibernate-mapping-one-to-one-1.html

Предложение от mkyong хорошо, но мне не понравилосьидея сохранения и назначения первичных ключей в обоих направлениях, так как у меня нет возможности редактировать файлы сопоставления из классов Vehicle и Weapon.См. Комментарий «главная трудность отношения один-к-одному заключается в том, что обоим назначен один и тот же первичный ключ»

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

Сначала я объявил свой VehicleWeapon.hbm.xml следующим образом:

<hibernate-mapping package="com.armory">

    <id name="id" type="long" >
        <column name="id"  />
        <generator class="native" />
    </id>

    <many-to-one name="vehicle" class="Vehicle" 
            column="vehicle_column"  cascade="all" unique="true" />

    <many-to-one name="weapon" class="Weapon" 
            column="weapon_column"  cascade="all" unique="true" />

Затем я объявил свой стандартный класс POWO для VehicleWeapon.И соответствующая реализация DAO.

Я запускаю пару тестов Junit / Spring.Я смог сохранить, удалить, восстановить без проблем.Все действия каскадируются с соответствующими таблицами оружия и транспортных средств.

Единственным недостатком этого метода является то, что Hibernate создаст третью таблицу vehicle_weapon, которая содержит идентификатор для таблиц транспортных средств и оружия соответственно в качестве ссылки.

Хорошо, что я не редактировал существующие сущности или файлы сопоставления.Я создал новый и создаю новый объект из двух таблиц.

Мне все еще нравится иметь возможность сопоставлять непосредственно со свойствами Оружия и Транспортного средства вместо отображения непосредственно в сущности Оружия и Транспортного средства.Но сейчас я думаю, что это приемлемо.

1 голос
/ 07 сентября 2010

Hibernate обеспечивает поддержку для сохранения одного класса сущностей в нескольких таблицах с использованием элемента <join> (или аннотации @SecondaryTable при использовании аннотаций).Из документации:

5.1.20.Объединение

Используя элемент <join>, можно отобразить свойства одного класса на несколько таблиц, имеющих отношение один к одному.Например:

<join
        table="tablename"                        (1)
        schema="owner"                           (2)
        catalog="catalog"                        (3)
        fetch="join|select"                      (4)
        inverse="true|false"                     (5)
        optional="true|false">                   (6)

        <key ... />

        <property ... />
        ...
</join>
  1. table: имя объединенной таблицы.
  2. schema (необязательно): переопределяет имя схемы, указанное корневым элементом.
  3. catalog (необязательно): переопределяет имя каталога, указанное корневым элементом <hibernate-mapping>.
  4. fetch (необязательно - по умолчанию join): если установлено соединение,по умолчанию Hibernate будет использовать внутреннее соединение для получения <join>, определенного классом или его суперклассами.Он будет использовать внешнее соединение для определенного подклассом.Если установлено значение select, то Hibernate будет использовать последовательный выбор для <join>, определенного для подкласса.Это будет выдано, только если строка представляет экземпляр подкласса.Внутренние объединения будут по-прежнему использоваться для получения <join>, определенного классом и его суперклассами.
  5. inverse (необязательно - по умолчанию false): если включено, Hibernate не будет вставлять или обновлять свойстваопределяется этим соединением.
  6. optional (необязательно - по умолчанию false): если включено, Hibernate вставит строку, только если свойства, определенные этим объединением, не равны NULL.Он всегда будет использовать внешнее объединение для извлечения свойств.

Например, адресную информацию для человека можно сопоставить с отдельной таблицей, сохранив семантику типа значения для всех свойств:

<class name="Person"
    table="PERSON">

    <id name="id" column="PERSON_ID">...</id>

    <join table="ADDRESS">
        <key column="ADDRESS_ID"/>
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </join>
    ...

Эта функция часто полезна только для устаревших моделей данных.Мы рекомендуем меньше таблиц, чем классов, и детальную модель предметной области.Тем не менее, это полезно для переключения между стратегиями отображения наследования в одной иерархии, как будет объяснено позже.

Использование композиции, как вы это сделали, является еще одним вариантом, но, очевидно, представит другую таблицу (для «агрегирования»)лицо).

0 голосов
/ 15 декабря 2011

используйте аннотации joincolumn и inverseJoincolumn для объединения двух таблиц (Vehicle и Weapon) и помещайте их в таблицу транзакций (VehicleWeapon). используйте любое сопоставление (onetoone, onetomany и т. д.) для сопоставления таблиц транспортных средств и ваадонов с помощью ondeletecascade и fetch.

0 голосов
/ 06 сентября 2010

Не уверен, что это ответ, но Hibernate допускает «составные» отношения, при которых вы встраиваете один класс в другой, и это отображается.

Например, здесь мы создаем «встраиваемый»class (Vehicle), а затем «внедрить» его в VehicleWeapon:

import javax.persistence.Embeddable;

@Embeddable
public class Vehicle
{
    ...
}

Embedded here:

@Entity
public class VehicleWeapon
{
  private long id;  
  private String name;
  private Vehicle vehicle;

  ...

    @Embedded
    public Vehicle getVehicle()
    {
      return vehicle;
    }

    public void setVehicle(Vehicle vehicle)
    {
        this.vehicle = vehicle;
    }

    ...
}

Это поможет в вашем сценарии?

...