Тройные (и n-арные) отношения в Hibernate - PullRequest
6 голосов
/ 10 апреля 2010

Q 1) Как мы можем моделировать троичные отношения, используя Hibernate? Например, как мы можем смоделировать троичные отношения, представленные здесь , используя Hibernate (или JPA)?

ПРИМЕЧАНИЕ : я знаю, что в JPA 2 добавлены некоторые конструкции для построения троичных отношений с использованием карт. Однако этот вопрос предполагает использование JPA 1 или Hibernate 3.3.x, и я не люблю использовать карты для моделирования этого.

Модель ER http://db.grussell.org/co22001%20notes_files/image043.gif


Модель ER с заменой троичных связей http://db.grussell.org/co22001%20notes_files/image045.gif

В идеале я предпочитаю, чтобы моя модель была такой:

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Product product;
//...
}

Q 1.1)

Как мы можем смоделировать этот вариант, в котором каждый элемент продажи может иметь много продуктов?

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Set<Product> products;
//...
}

Q 2) В общем, как мы можем моделировать n-арные, n> = 3 отношения с Hibernate?

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

Ответы [ 2 ]

11 голосов
/ 11 апреля 2010

Q1. Как мы можем моделировать троичные отношения, используя Hibernate? Например, как мы можем смоделировать троичные отношения, представленные здесь, используя Hibernate (или JPA)? (...)

Я бы изменил ассоциацию с промежуточным классом сущностей (и это рекомендуемый способ для Hibernate). Применительно к вашему примеру:

@Entity
public class Sale {
    @Embeddable
    public static class Pk implements Serializable {
        @Column(nullable = false, updatable = false)
        private Long soldById;

        @Column(nullable = false, updatable = false)
        private Long buyerId;

        @Column(nullable = false, updatable = false)
        private Long productId;

        public Pk() {}

        public Pk(Long soldById, Long buyerId, Long productId) { ... }

        // getters, setters, equals, hashCode
    }

    @EmbeddedId
    private Pk pk;

    @ManyToOne
    @JoinColumn(name = "SOLDBYID", insertable = false, updatable = false)
    private SaleAssistant soldBy;
    @ManyToOne
    @JoinColumn(name = "BUYERID", insertable = false, updatable = false)
    private Customer buyer;
    @ManyToOne
    @JoinColumn(name = "PRODUCTID", insertable = false, updatable = false)
    private Product product;

    // getters, setters, equals, hashCode
}

В1.1. Как мы можем смоделировать этот вариант, в котором каждый элемент продажи может иметь много продуктов?

Я бы здесь не использовал составной первичный ключ и не вводил PK для сущности Sale.

Q2. В общем, как мы можем моделировать n-арные, n> = 3 отношения с Hibernate?

Я думаю, что мой ответ на вопрос 1. покрывает это. Если нет, уточните.


Обновление: Ответы на комментарии с ОП

(...) поля pk не заполняются, и в результате я не могу сохранить элементы продажи в БД. Должен ли я использовать сеттеры, подобные этому, для класса Sale? public void setBuyer (Customer cust) {this.buyer = cust; this.pk.buyerId = cust.getId (); }

Вам нужно создать новый Pk (я удалил конструкторы из своего исходного ответа для краткости) и установить его для элемента Sale. Я бы сделал что-то вроде этого:

Sale sale = new Sale();
Pk pk = new Pk(saleAssistant.getId(), customer.getId(), product.getId());
sale.setPk(pk);
sale.setSoldBy(saleAssistant);
sale.setBuyer(customer);
sale.setProduct(product);
...

А затем сохраните sale.

Кроме того, в аннотациях JoinColumn к какому столбцу относятся поля «name»? Pks целевых отношений или собственные имена столбцов таблицы продаж?

Для столбцов для атрибутов составного Pk (т.е. имена столбцов таблицы продаж), мы хотим, чтобы они получили ограничения PK и FK .

0 голосов
/ 18 апреля 2010

Используете ли вы сгенерированные базой данных первичные ключи для Customer, Product и SalesAssistant? Это может вызвать проблему, поскольку похоже, что вы пытаетесь использовать действительные идентификаторы БД, а не позволяете Hibernate разрешать ссылки на объекты во время фактического сохранения.

Встроенный PK выше выглядит странно для меня лично, но у меня не было возможности опробовать его. Кажется, что столбцы перекрывают друг друга и перекрывают друг друга.

Я думаю, достаточно просто иметь ссылки на ManyToOne.

Также включите отладку операторов SQL и посмотрите, что отправляется в БД.

...