Как выполнить отображение OneToMany Hibernate, когда обратная ссылка - это просто атрибут id, а не полная ссылка - PullRequest
1 голос
/ 13 июля 2011

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

У меня есть класс с именем Bucket, который отображает серию меток.Класс Bucket имеет атрибут id.У класса Label нет ссылки на Bucket, вместо этого у него есть поле bucketId, которое содержит идентификатор владельца.Это было необходимо, чтобы избежать циклических ссылок (Bucket to Label и back Label to Bucket), чтобы позволить объектам Bucket преобразовываться в нотацию JSON.

Мой класс Bucket выглядит следующим образом:

@Entity(name="Bucket")
@Table(name = "BUCKETS")
public class Bucket implements Serializable {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "BUCKET_ID")
    protected long id;

    /*
     * Map of labels indexed by the label name. I'm not sure this mapping is correct!
     */
    @ElementCollection
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @MapKeyColumn(name="LABEL_NAME")
    private Map<String, Label> labels = new HashMap<String, Label>();

    ...

}

и класс Label выглядит следующим образом:

@Entity(name="Label")
@Table(name = "LABELS")
public class Label implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "LABEL_ID")
    protected long id;

    /*
     * How do I map this? It should point to the id of the Bucket instance that has
     * this label in its "labels" map
     */
    protected long bucketId;


    @Column(name = "LABEL_NAME", length=250, nullable=false)
    private String name;

    ...

}

Если бы у меня могла быть ссылка Bucket в метке, я бы отобразил ее как @OneToMany, а затем в классе Buckets я отобразил бы как @ManyToOne (mappedBy = "bucket"), но у меня нет этой ссылки, только идентификатор, указывающий назад.

Кто-нибудь знает, как мне отобразить это?

Спасибо!Эдуардо

Ответы [ 2 ]

2 голосов
/ 13 июля 2011
@ElementCollection
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@MapKeyColumn(name="LABEL_NAME")
private Map<String, Label> labels = new HashMap<String, Label>();

Во-первых, приведенное выше отображение не может быть правильным.Либо используйте @ElementCollection ИЛИ @OneToMany, а не оба.

Что касается сопоставления поля buckedId, я бы просто отобразил его как обычное поле Long в таблице Labels.Вы можете инициализировать поле с правильным bucketId при добавлении метки в ведро.Примерно так (в классе Bucket):

public void addLabel(Label label) {
    labels.put(label.getName(), label);
    label.setBucketId(this.getId());
}

Однако убедитесь, что поле bucketId в классе Labels не может быть установлено в неправильное значение.Например, вы можете уменьшить видимость установщика для поля bucketId.

1 голос
/ 13 июля 2011

По какой-то причине я не могу комментировать ниже ответ Джорджа, поэтому я отвечаю на ваш второй вопрос здесь:

Чтобы установить bucketId в метке после того, как Bucket был создан, вам нужно зарегистрировать EventListener, например, для выполнения того, что вы хотите (это необязательно рабочий код).

    public class LabelPostInsertListener implements PostInsertListener {

        public void onPostInsert(PostInsertEvent event)
                throws HibernateException {
            Bucket bucket = (Bucket)event.getEntity();
            for (Label l : bucket.getLabels().values()) {
                l.setBucketId(bucket.getId());
            }

        }
    }

Google Hibernate EventListener для получения подробной информации о конфигурации и тому подобном, существует много различных типов, хотя PostInsertListener должен подходить для этой ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...