【问题标题】:Hibernate queries for @JoinColumn and mappedBy@JoinColumn 和 mappedBy 的休眠查询
【发布时间】:2014-08-19 18:51:57
【问题描述】:

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

如果我的 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;
}

然后我保存一个产品和零件然后休眠生成插入并更新查询:

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 (?, ?, ?)

如果我的实体之间的关系只是一对多,那么为什么休眠需要在第一种情况下插入和更新,而只在第二种情况下插入查询?请解释一下。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    在第一个使用@JoinColumn的版本中,需要在Product之前先持久化Part,例如:

    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 不知道 Productid 是什么,所以 PRODUCT_ID 列将为空。

    当持久化product 时,Hibernate 会为Product 生成插入 SQL。现在 Hibernate 知道为Product 生成的id 是什么。然后 Hibernate 发出更新 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)
    

    不同之处在于,当您坚持 order1order2 时,您是在告诉 Hibernate 那个 OrderCustomer 是什么。相关客户的 id 保存在每个订单中。

    如果你想拥有类似第一个版本的@JoinColumn,但没有额外更新SQL,你可以使用@ElementCollection,例如:

    @Entity
    public class Product {
      @Id @GeneratedValue
      String serialNumber;
    
      @ElementCollection
      Set<Part> parts = new HashSet<Part>();
    }
    
    @Entity
    public class Part {
        @Id @GeneratedValue
        int id;
    
        String partName;
    }
    

    上面的映射会生成一个额外的关系表,比如product_part

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-13
      • 2018-09-20
      • 2017-02-13
      • 2012-08-09
      • 2015-12-03
      • 1970-01-01
      • 2016-01-13
      相关资源
      最近更新 更多