2013-05-02 2 views
2

В одном из моих классов, скажем, Location, у меня есть что-то вроде этого:Условный/композитный JoinColumn В JPA/Hibernate

private List<Magician> magicians; 

... 

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL) 
@JoinColumn(name="location_id") 
public List<Magician> getMagicians() { 
    return magicians; 
} 

public void setMagicians(List<Magician> magicians) { 
    this.magicians = magicians; 
} 

где Magician имеет переменные

private Integer id; 
private Integer location_id; 
private Boolean active; 

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

Как я могу это достичь?

Спасибо за внимание.

+0

ОК, спасибо JB и Кевину за ответы. Мотивация моего вопроса в том, что бывают ситуации, когда я могу ограничить набор данных, к которым обращается приложение, без введения каких-либо новых методов в код. Поэтому я бы быстро подготовил данные, установив active в true с помощью db-запроса. –

ответ

0

В Hibernate мой вопрос может быть решен с помощью фильтра, как описано здесь: https://stackoverflow.com/a/6920847/1966869. Версия xml, которую я только что проверила и выглядит довольно практично, описана здесь: http://www.mkyong.com/hibernate/hibernate-data-filter-example-xml-and-annotation/. Могут быть другие решения, использующие @Where (How to use @Where in Hibernate) или @JoinFormula (@JoinFormula and @OneToMany definition - poor documentation), но я их не тестировал.

2

Прежде всего, у Мага не должно быть поля location_id. Он должен иметь поле типа Location. Это сделало бы двунаправленную связь между двумя объектами:

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "location") 
public List<Magician> getMagicians() { 
    return magicians; 
} 

... 

@ManyToOne 
@JoinColumn(name = "location_id") 
public Location getLocation() { 
    return this.location; 
} 

Тогда, чтобы ответить на ваш вопрос, государство и объединение сущности не используются для реализации speciic сценария использования или запроса. Они использовали для моделирования того, что содержит база данных. Для того, чтобы получить активные волхв в данном месте, вы должны просто использовать запрос:

select m from Magician m where m.active = true and m.location = :location 
+0

Спасибо за ваш ответ. Что касается однонаправленной или двунаправленной точки, я бы согласился с комментарием axtavt (http://stackoverflow.com/a/5361587/1966869) «что« навигационный доступ не всегда хорош, особенно для «один-к-очень-многим» »и« отношения многие-очень-многие ». Я не думаю, что нужно использовать двунаправленную информацию, если это необходимо, особенно в приложении, где« один-очень-много »является вездесущим, как и я. подумайте, что это очень актуальная проблема, и любые дальнейшие комментарии, которые у вас могут быть, приветствуются и будут оценены. –

+0

Если это очень-очень-много, тогда может быть веская причина, чтобы моделировать его как однонаправленную ассоциацию ManyToOne. вы моделируете его как однонаправленный OneToMany, и у вас есть идентификатор местоположения в любом случае у вашего Мага (что делает неверным отображение, так как этот столбец отображается дважды), так почему бы вместо этого не использовать lazy-загруженное местоположение? –

+0

Потому что Расположение - большой объект, который мне обычно не нужен (или у меня уже есть), когда Я работаю с волшебником, тогда как мне обычно нужно просто location_id. Поэтому я держу только идентификатор location_id. Что касается вашего наблюдения, что он отображается дважды, насколько я понимаю, он будет отображаться дважды, если бы отношение было двунаправленным, т. Е. Если я последую вашему совету (что я ценю, поэтому, пожалуйста, поправьте меня, если я ошибаюсь). –

1

Я не выполнил бы эту работу на уровне предприятия, вместо этого я бы выполнить его с помощью EntityManager создать запрос. Как упоминает JB, вам нужно добавить местоположение как составной объект вместо Integer.

// В методе

List<Magician> magicians = 
    em.createQuery("select m from Location l join Magician m where m.active = true and 
    l.[specify id here] = :locationId", Magician.class).setParameter("locationId", 
    1).getResultList(); 
Смежные вопросы