Hibernate查询@JoinColumn和mappedBy

时间:2014-08-19 09:50:21

标签: java hibernate jpa

我试图理解在使用@JoinColumn时生成的DML查询与Hibernate中@OneToMany映射的mappedBy属性相比的差异。

如果我将我的java类定义为:

@Entity
public class Product {
  @Id
  String serialNumber;
  @OneToMany
  @JoinColumn(name = "PRODUCT_ID")
  Set<Part> parts = new HashSet<Part>();
}

@Entity
public class Part {
    @Id
    @GeneratedValue
    int id;
    String partName;
}

然后id我保存了一个产品和零件,然后hibernate生成插入并更新查询:

Hibernate: insert into Product (serialNumber) values (?)
Hibernate: insert into Part (partName, id) values (?, ?)
Hibernate: update Part set PRODUCT_ID=? where id=?

现在,如果我将我的java类定义为:

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private Integer id;
    @OneToMany(mappedBy = "customer")
    private List<Order> orders;
}

@Entity
@Table(name="TBL_ORDER")
public class Order {
    @Id
    @GeneratedValue
    private Integer id;
    private int orderNumber;
    @ManyToOne
    private Customer customer;

    @Override
    public String toString() {
        return id.toString();
    }
}

然后Hibernate只生成没有任何更新的插入查询:

Hibernate: insert into Customer (id) values (?)
Hibernate: insert into TBL_ORDER (customer_id, orderNumber, id) values (?, ?, ?)

如果我的实体之间的关系只有一对多,那么为什么hibernate需要插入&amp;第一种情况的更新,只在第二种情况下插入查询?请解释一下。

1 个答案:

答案 0 :(得分:1)

在使用@JoinColumn的第一个版本中,您需要先在Part之前保留Product,例如:

Part part1 = new Part()
Part part2 = new Part()
em.persist(part1)
em.persist(part2)
Product product = new Product()
product.parts.add(part1)
product.parts.add(part2)
em.persist(product)

当持久化part1part2时,Hibernate会为Part生成插入SQL。 Hibernate不知道id的{​​{1}}是什么,所以Product列将为空。

当持久化PRODUCT_ID时,Hibernate会为product生成插入SQL。现在Hibernate知道Product生成的id是什么。然后,Hibernate通过为Product列设置适当的值来发布更新SQL以更新Part的现有记录。

在使用PRODUCT_ID的第二个版本中,您可以像以下一样坚持:

mappedBy

不同之处在于,当您持续Customer customer = new Customer() em.persist(customer) Order order1 = new Order() // using `Order` as entity name is not always valid because `Order` it is often confused with SQL clause order1.setCustomer(customer) em.persist(order1) Order order2 = new Order() order2.setCustomer(customer) em.persist(order2) order1时,您告诉Hibernate order2的{​​{1}}是什么。相关客户的ID保存在每个订单中。

如果您希望使用Customer的第一个版本,但没有额外的更新SQL,则可以使用Order,例如:

@JoinColumn

上面的映射将生成一个额外的关系表,例如@ElementCollection