JPA ManyToMany Join Table имеет все атрибуты как PK - PullRequest
3 голосов
/ 23 марта 2012

Я использую Hibernate 3.3.1 и продолжаю моделировать этот пример структуры таблицы , но у меня возникают проблемы при создании таблицы соединения с дополнительными атрибутами.

Это соотношение «многие ко многим» между таблицами Order и Product.Таблица соединения - это таблица Order Detail.Я следовал подходу, упомянутому здесь .

Теперь у меня есть сущности

@Entity
@Table(name = "Orders")
public class Order {
    @OneToMany(mappedBy="order")
    private List<OrderDetail> orderItems;
}

и

@Entity
@Table(name="PRODUCTS")
public class Product {
    @OneToMany(mappedBy="product")
    private List<OrderDetail> orderItems;
}

и

@Entity
@IdClass(OrderDetail.class)
@Table(name = "ORDER_DETAIL")
public class OrderDetail implements Serializable {
    @Id
    @Column(name="ORDER_ID")
    private Long orderId;
    @Id
    @Column(name="PRODUCT_ID")
    private Long productId;

    @Column(name = "PRICE")
    private double price;

    @Column(name = "LAST_UPDATED_TIME")
    private Date lastUpdatedTime;

    @ManyToOne
    @JoinColumn(name = "ORDER_ID")
    private Order order;

    @ManyToOne
    @JoinColumn(name = "PRODUCT_ID")
    private Product product;
}

и

public class OrderDetailId implements Serializable {
    private Long orderId;
    private Long productId;
}

Я использовал Apache Derby для выполнения теста, но у меня возникли проблемы со сгенерированной структурой таблицы.

CREATE TABLE ORDER_DETAIL (
        PRODUCT_ID BIGINT NOT NULL,
        ORDER_ID BIGINT NOT NULL,
        LAST_UPDATED_TIME TIMESTAMP NOT NULL,
        PRICE DOUBLE NOT NULL
    );

CREATE INDEX SQL120323142938020 ON ORDER_DETAIL (PRODUCT_ID ASC);

CREATE UNIQUE INDEX SQL120323142937810 ON ORDER_DETAIL (PRODUCT_ID ASC, ORDER_ID ASC, LAST_UPDATED_TIME ASC, PRICE ASC);

ALTER TABLE ORDER_DETAIL ADD CONSTRAINT SQL120323142937810 PRIMARY KEY (PRODUCT_ID, ORDER_ID, LAST_UPDATED_TIME, PRICE);

ALTER TABLE ORDER_DETAIL ADD CONSTRAINT FK4A94AA82CC6D989A FOREIGN KEY (PRODUCT_ID)
    REFERENCES PRODUCTS (PROD_ID);

Кажется, он создал всеиз моих столбцов в качестве первичного ключа.Почему это так?

Ответы [ 2 ]

7 голосов
/ 23 марта 2012

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

Найдите что-то вроде кода ниже. Я не могу гарантировать, что он работает в такой старой версии Hibernate, но работает точно никогда. Стоит попробовать в любом случае. Обновление до версии 3.5.X (а точнее даже более новой) не помешает, если вы хотите использовать функции JPA 2.0. Конструкторы / равные и т. Д. Убираются для экономии места.

@Entity
@Table(name = "Orders")
public class Order {
    @Id Long id;
    @OneToMany(mappedBy="order")
    private List<OrderDetail> orderItems;
}

@Entity
@Table(name="PRODUCTS")
public class Product {
    @Id Long id;
    @OneToMany(mappedBy="product")
    private List<OrderDetail> orderItems;
}

@Entity
@IdClass(OrderDetailId.class)
@Table(name = "ORDER_DETAIL")
public class OrderDetail implements Serializable {
    @Id @ManyToOne @JoinColumn(name = "ORDER_ID")
    private Order order;

    @Id @ManyToOne @JoinColumn(name = "PRODUCT_ID")
    private Product product;

    @Column(name = "PRICE") private double price;
    //Maybe you also want to use @TemporalType here
    @Column(name = "LAST_UPDATED_TIME") private Date lastUpdatedTime;
}

public class OrderDetailId implements Serializable {
    private Long order;
    private Long product;
}

ОБНОВЛЕНИЕ 15/08/2017 В JPA 2.1 и выше вам не нужно добавлять класс для составного идентификатора, и вы можете сделать это следующим образом:

@Entity
@Table(name = "ORDER_DETAIL")
public class OrderDetail implements Serializable {
    @Id @ManyToOne @JoinColumn(name = "ORDER_ID")
    private Order order;

    @Id @ManyToOne @JoinColumn(name = "PRODUCT_ID")
    private Product product;

    @Column(name = "PRICE") private double price;
    //Maybe you also want to use @TemporalType here
    @Column(name = "LAST_UPDATED_TIME") private Date lastUpdatedTime;
}
5 голосов
/ 23 марта 2012

Кажется, что приведенный ниже код генерирует таблицы по желанию, я тестировал его на MySQL (только создание таблиц, а не CRUD):

@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "orderDetailId.order")
    private List<OrderDetail> orderItems;

    //get set …..

}

@Entity
@Table(name="products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "orderDetailId.product")
    private List<OrderDetail> orderItems;   

    //get set ……
}

@Entity
@Table(name = "order_detail")
public class OrderDetail {

    @Id
    private OrderDetailId orderDetailId;

    private double price;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdatedTime;

    //get set ….            
}

@Embeddable
public class OrderDetailId implements Serializable{

    private Order order;

    private Product product;

    @ManyToOne(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    //hash code equals override 
}

подробности отладки Hibernate, как показано ниже

DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - create table order_detail (lastUpdatedTime datetime, price double precision not null, product_id bigint, order_id bigint, primary key (order_id, product_id)) ENGINE=InnoDB
DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - create table orders (id bigint not null auto_increment, primary key (id)) ENGINE=InnoDB
DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - create table products (id bigint not null auto_increment, primary key (id)) ENGINE=InnoDB
DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - alter table order_detail add index FK23AE5A622128CF91 (order_id), add constraint FK23AE5A622128CF91 foreign key (order_id) references orders (id)
DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - alter table order_detail add index FK23AE5A62EB201631 (product_id), add constraint FK23AE5A62EB201631 foreign key (product_id) references products (id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...