2015-04-25 5 views
1

У меня есть простые отношения с родителями и детьми с @OneToMany и @ManyToOne аннотации.Hibernate. Обращайтесь к последнему ребенку

@Entity 
public class Parent { 
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY) 
     private List<Child> children = new ArrayList<>(); 

} 

public class Child { 
     @ManyToOne(fetch = FetchType.LAZY, optional = false) 
     @JoinColumn(name = "parent_id") 
     @ForeignKey(name = "fk_child_parent") 
     private Parent parent; 

} 

Но я также хочу, чтобы сохранить ссылку на текущий (последний) ребенок внутри Parent лица.

Как это сделать в правильном направлении? Должен ли я ввести новое ненаправленное отношение @OneToOne в Parent? Например:

@OneToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinColumn(name = "current_child_id", nullable = false) 
    @ForeignKey(name = "FK_parent_child") 
    private Child currentChild; 

ответ

0

Поскольку у вас есть Список, вы можете просто взглянуть на последний элемент списка.

Вы хотите Hibernate поддерживать порядок списка путем добавления @OrderColumn (имя = «INDEX_COL») ниже @OneToMany

1

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

Добавьте созданную (или обновленную) временную метку к вашему дочернему классу, вы можете сами определить, как вы хотите обрабатывать инициализацию этого поля (т. Е. С использованием по умолчанию столбцов или триггеров и т. Д.). Теперь необходимая информация должна быть доступна вам в вашем коде, просто добавьте метод «compareTo» к вашему ребенку (для сортировки) и добавьте следующий метод getMostRecentChild в ваш родительский класс.

@Entity 
public class Parent { 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY) 
    public List<Child> children = new ArrayList<>(); 

    public Child getMostRecentChild() { 
     if(children == null || children.isEmpty()) { 
      return null; 
     } 
     return Collections.sort(children).get(0); 
    } 
} 

public class Child { 
    @ManyToOne(fetch = FetchType.LAZY, optional = false) 
    @JoinColumn(name = "parent_id") 
    @ForeignKey(name = "fk_child_parent") 
    public Parent parent; 

    @Column(name = "created_ts") 
    public createdTs; 

    public int compareTo(Child other) { 
     return created_ts.compareTo(other); 
    } 

} 

Сведения о реализации, как вы находите currentChild, неактуальны. Вы также можете использовать TreeSet или просто цикл, чтобы найти currentChild.

EDIT: Аргумент, почему это лучше, чем столбец currentChild.

Если вам не нравится выше ответ рассмотреть следующие

  1. Добавление поля currentChild предоставляет две ссылки на тот же объект. Поэтому он не нормируется, тогда как добавление метки времени добавляет нормализованный столбец в вашу схему, из которой требуемая информация (и многое другое) может быть легко выведена таким образом, который непосредственно связан с логикой, которую вы пытаетесь инкапсулировать в свою текущую форму колонка.
  2. Чтобы гарантировать, что ваш currentChild не будет несовместим с его предполагаемым значением, вы должны инкапсулировать его логику либо в объект Hibernate, который затем можно переопределить на уровне базы данных, либо с помощью триггеров на уровне базы данных, что может быть уродливым и трудным для отслеживания (тогда как значение по умолчанию и поле «ON UPDATE» для created_ts довольно распространенное место)
+0

Не могли бы вы объяснить, почему я должен публиковать поля или перемещать аннотации к геттерам/сеттерам? Что не так, если держать их на частных полях? – MyTitle

+0

Вам нужен геттер/сеттер, чтобы получить доступ к полям в вашем коде в любом случае, я помню, что в последнее время я использовал Hibernate, добавляя аннотации на getter's, однако на втором взгляде кажется, что вы можете также добавить аннотации в частное поле и hibernate будет использовать отражение для установки полей. – Brendan

+0

Отредактировано, чтобы предоставить лучшее объяснение этим выборам. – Brendan

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