简体   繁体   English

JPA ManyToMany Join Table具有PK的所有属性

[英]JPA ManyToMany Join Table has all attributes as PK

I'm using Hibernate 3.3.1 and am following along in modelling this sample table structure , but I'm having trouble creating a join table with extra attributes. 我正在使用Hibernate 3.3.1并且正在建模这个示例表结构 ,但是我在创建具有额外属性的连接表时遇到了麻烦。

It's the many-to-many relationship between the Order and Product table. 它是OrderProduct表之间的多对多关系。 The join table is the Order Detail table. 连接表是Order Detail表。 I followed the approach mentioned here . 我按照这里提到的方法。

Now I have the entities 现在我有了实体

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

and

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

and

@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;
}

and

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

I used Apache Derby to do the test, but I'm having trouble with the generated table structure. 我使用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);

It seems that it has created all of my columns as the primary key. 它似乎已创建我的所有列作为主键。 Why is this so? 为什么会这样?

You use class of your entity as an argument to IdClass. 您使用实体的类作为IdClass的参数。 That is not correct. 这是不正确的。 Class of Id should be used. 应使用Id类。 Additionally separate fields for id in join entity are not needed. 另外,不需要在连接实体中用于id的单独字段。

Go for something like code below. 去寻找下面的代码。 I cannot guarantee that it works in such a old version of Hibernate, but works for sure in never ones. 我不能保证它可以在如此旧的Hibernate版本中运行,但绝对可以肯定。 Worth of trying anyway. 无论如何都值得尝试。 It would not hurt to update to at least 3.5.X version (or rather even fresher one) if you want to use JPA 2.0 features. 如果你想使用JPA 2.0功能,更新到至少3.5.X版本(或者更确切地说是更新版本)也不会有什么坏处。 Constructors/equals etc. are stripped away to save space. 为了节省空间,剥离了构造者/平等等。

@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;
}

UPDATE 15/08/2017 In JPA 2.1 and above you don't need to add a class for the composite Id and you can do it like this: 更新15/08/2017在JPA 2.1及更高版本中,您不需要为复合ID添加类,您可以这样做:

@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;
}

The code below seems to generate tables as desired, I have tested it on MySQL (just the table creation, not CRUD): 下面的代码似乎根据需要生成表,我在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 details as below Hibernate DEBUG详细信息如下

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM