2011-06-10 4 views
3

Мне нужно связать объект с двумя списками других объектов - оба списка, содержащие объекты того же типа. Это выглядит примерно так:Hibernate: несколько ассоциаций с тем же классом

@Entity 
public class Course { 
    private List<Test> preTests; 
    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getPreTests() { 
     return preTests; 
    } 

    public void setPreTests(List<Test> preTests) { 
     this. preTests = preTests; 
    } 

    private List<Test> postTests; 
    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getPostTests() { 
     return postTests; 
    } 

    public void setPostTests(List<Test> postTests) { 
     this. postTests = postTests; 
    } 
} 

Теперь я даже не потрудился, чтобы попробовать этот само по себе потому, что кажется очевидным, что Hibernate не будет иметь никакого способа отличить которые Tests идти в preTests и который в postTests. Исправьте меня, если я ошибаюсь, но единственной информацией, с которой он должен работать, являются внешние ключи в таблице Test, указывающие на запись Course, и как предварительные, так и послетестовые тесты указывают на то же Course. Моя следующая мысль была создать явные PreTest и PostTest подклассов Test, и имеет один List<PreTest> и один List<PostTest>, но это приводит к печально известным «mappedBy ссылаться на неизвестное свойстве целевого объекта: конечно» проблема, которую человек на Hibernate претензии - для причины, которые кажутся мне суетливыми, - это по дизайну и, следовательно, вряд ли исчезнет.

Моя текущая мысль состоит в том, чтобы использовать отдельные таблицы соединений для хранения двух ассоциаций. Я не вижу причин, почему это не должно работать. Это также удовлетворяет мое желание оставить все явные SQL (или даже HQL) из определений сущностей и противостоять принуждению, чтобы создать странные составные ключи или иначе написать код, который отражает только причуды моей структуры сохранения, а не мой дизайн объекта.

Тем не менее, прежде чем я посвящу себя этому курсу, я спрашиваю, есть ли у кого-то из вас более чистое решение или какие-то недостатки в моих рассуждениях здесь.

Заранее спасибо.

Майкл

ответ

1

Я не знаю, если это действительно хорошая идея или нет, но вы могли бы включать в себя

@org.hibernate.annotations.Where 

аннотацию на вашем картографирования ассоциации и использовать столбец дискриминатора на тестовой таблице, так что вы можете сообщить тест Pre из теста Post при загрузке экземпляров Test.

+0

Я дал вам upvote, потому что это, безусловно, разумный ответ, но она попадает под мое желание сохранить фактический SQL/HQL из вещей, поэтому я предпочитаю мое решение, даже за счет дополнительно несколько таблиц и менее эффективные запросы. – Michael

0

Один из вариантов - метод наследования наследования Table per class hierarchy, который звучит так, как будто вы начали делать, но не прошли весь путь.

Другим вариантом является, как упоминалось, использование @Where annotation.

Третий вариант, который я часто использую для подобных случаев, состоит в том, чтобы сопоставить одну коллекцию для всех тестов, связанных с курсом, а затем добавить вспомогательные методы для возврата только желаемых подмножеств, когда вы хотите работать с pre или post тесты. Пример кода:

@Entity 
    public class Course { 

    private List<Text> tests; 

    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getTests() { 
     return tests; 
    } 

    public List<Test> getPreTests() { 
     List<Test> preTests = new ArrayList<Test>(); 
     for (Test test : preTests) { 
      if (test.isPreTest()) { 
       preTests.add(test); 
      } 
     } 
     return preTests; 
    } 


    public List<Test> getPostTests() { 
     List<Test> postTests = new ArrayList<Test>(); 
     for (Test test : postTests) { 
      if (test.isPostTest()) { 
       postTests.add(test); 
      } 
     } 
     return postTests; 
    } 
+0

Спасибо, Стеви, но я не уверен, где я упал методом «Таблица для каждого класса» - вот как я наложил наследование вверх, но у меня все еще есть ошибка «неизвестного свойства объекта-объекта». Если, возможно, вы не предполагаете, что я либо переместил поле «курс» вниз в дочерние классы, либо иным образом столкнулся с иерархией классов, чтобы подделать Hibernate? Два других предложения являются разумными, но неэлегантными - ИМО немного менее изящными, чем тот, который я предложил. – Michael

+0

Я не уверен, основываясь на том, что я вижу в вашем вопросе, почему вы получите «неизвестную целевую структуру объекта», поэтому я не могу с этим поговорить. Я добавил пример кода для третьего варианта. Нет, это не самые элегантные решения, но я склонен быть довольно прагматичным в своем подходе к работе с Hibernate. –

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