2010-10-01 9 views
1

У меня есть мешок, структура которого выглядит следующим образом:Hibernate мешок с несколькими элементами

<bag name="foo" fetch="select" table="table_of_foos"> 
    <key column="foo_ids"/> 
    <many-to-many class="Bar" column="bar_ids"/> 
</bag> 

Мой «table_of_foos» таблица имеет два столбца: «foo_ids» и «bar_ids», ни один из которых является уникальным. Я хочу добавить еще одну колонку в эту таблицу, которая содержит некоторую информацию о соотношении foos к барам, так что моя таблица будет содержать три столбца. Затем я хочу иметь доступ к этой информации в моем webapp.

К сожалению, мне кажется, что я не могу добавить свойство или элемент в сумку. Что я хочу сделать, это примерно так:

<bag name="foo" fetch="select" table="table_of_foos"> 
    <key column="foo_ids"/> 
    <many-to-many class="Bar" column="bar_ids"/> 
    <element column="still_valid" type="integer"/> 
</bag> 

Каков наилучший способ для этого?

ответ

3

Если вашему объединенному Столу нужен дополнительный столбец, отличный от его основного (основного) ключа, , вы должны реализовать дополнительный объединенный класс.

public class Foo { 

    Collection<FooBar> bar = new ArrayList<FooBar>(); 

} 

public class Bar { 

    Collection<FooBar> foo = new ArrayList<FooBar>(); 

} 

соединяемых класс (который необходим составной первичный ключ - реализован как статический внутренний класс) описывается следующим образом

public class FooBar { 

    private FooBarId fooBarId; 

    private String additionalProperty; 

    public static class FooBarId implements Serializable { 

     private Integer fooId; 
     private Integer barId; 

     private Foo foo; 
     private Bar bar; 

     // getter's and setter's 

     public FooBarId() {} 
     public FooBarId(Integer fooId, Integer barId) { 
      this.fooId = fooId; 
      this.barId = barId; 
     } 

     public boolean equals(Object o) { 
      if(!(o instanceof FooBarId)) 
       return false; 

      FooBarId other = (FooBarId) o; 
      return new EqualsBuilder() 
         .append(getFooId(), other.getFooId()) 
         .append(getBarId(), other.getBarId()) 
         .isEquals(); 
     } 

     public int hashCode() { 
      return new HashCodeBuilder() 
         .append(getFooId()) 
         .append(getBarId()) 
         .hashCode(); 
     } 

    } 

} 

повторно написать отображение в

/* Foo.class */ 

<bag name="bar" table="table_of_foos"> 
    <key column="BAR_ID" insert="false" update="false"/> 
    <one-to-many class="FooBar" table="table_of_foos"/> 
</bag> 

/* Bar.class */ 

<bag name="foo" table="table_of_foos"> 
    <key column="FOO_ID" insert="false" update="false"/> 
    <one-to-many class="FooBar" table="table_of_foos"/> 
</bag> 

И FooBar

<class name="FooBar"> 
    <composite-id name="fooBarId" class="FooBar$FooBarId"> 
     <key-property name="fooId" column="FOO_ID"/> 
     <key-property name="barId" column="BAR_ID"/> 
    </composite-id> 
    <property name="additionalProperty" type="string"/> 
    <many-to-one name="foo" column="FOO_ID" class="Foo" insert="false" update="false"/> 
    <many-to-one name="bar" column="BAR_ID" class="Bar" insert="false" update="false"/> 
</class> 

Если вы хотите, вы можете также сопоставить составной элемент вместо объединенного класса (компоненту компонента не нужен (составной) первичный ключ, а имеет свой жизненный цикл, связанный с его собственным экземпляром Entity. Имейте это в виду)

Создать вас составной элемент (теперь без идентификатора)

public class FooBar { 

    private String additionalProperty; 

    private Foo foo; 
    private Bar bar; 

} 

и определить следующее отображение

/* Foo.class */ 

<bag name="bar" table="table_of_foos"> 
    <key column="BAR_ID"/> 
    <composite-element class="FooBar"> 
     <property name="additionalProperty" type="string"/> 
     <many-to-one name="foo" column="FOO_ID" class="Foo" insert="false" update="false"/> 
     <many-to-one name="bar" column="BAR_ID" class="Bar"/> 
    </composite-element> 
</bag> 

/* Bar.class */ 

<bag name="foo" table="table_of_foos"> 
    <key column="FOO_ID"/> 
    <composite-element class="FooBar"> 
     <property name="additionalProperty" type="string"/> 
     <many-to-one name="foo" column="FOO_ID" class="Foo" insert="false" update="false"/> 
     <many-to-one name="bar" column="BAR_ID" class="Bar"/> 
    </composite-element> 
</bag> 
+0

Спасибо, это было очень полезно! – denaje

+1

+1 для этого приятного и подробного ответа –

0

я не смог получить эти отображения, чтобы работать, как написано по Arthur Ronald F D Garcia. Этот код не работает и приводит к ошибке MappingException.

Invalid Покушение

<set name="StoreDepartments" table="`ou_store_org_unit`"> 
    <key column="`ou_id`" /> 
    <composite-element class="NHibernate.Map.OrganizationUnit+StoreDepartment+Relation, CentralDataLayer"> 
     <property name="Id" column="`ou_store_id`" type="Int32" /> 
     <many-to-one name="OrganizationUnit" column="`ou_id`" class="NHibernate.Map.OrganizationUnit, CentralDataLayer" /> 
     <many-to-one name="StoreDepartment" column="`store_ou_id`" class="NHibernate.Map.OrganizationUnit+StoreDepartment, CentralDataLayer" /> 
    </composite-element> 
</set> 

Resulting Error: Repeated column in mapping for collection: 
NHibernate.Map.OrganizationUnit.StoreDepartments column: ou_id 

Я был в состоянии заставить его работать со следующим.

Действительно Покушение

<set name="StoreDepartments" table="`ou_store_org_unit`"> 
    <key column="`ou_id`" /> 
    <composite-element class="NHibernate.Map.OrganizationUnit+StoreDepartment+Relation"> 
     <parent name="OrganizationUnit" /> 
     <property name="Id" column="`ou_store_id`" type="Int32" /> 
     <many-to-one name="StoreDepartment" column="`store_ou_id`" class="NHibernate.Map.OrganizationUnit+StoreDepartment" /> 
    </composite-element> 
</set> 

Дополнительно:

Если NHibernate пытается обновить свой сет, даже если вы не изменить его, попробуйте опрокинув GetHasCode и Equals методы. Подробнее information here.

Смежные вопросы