解决方法/摆脱 OneToMany 和 ManyToOne 关系中的多个可写映射?

Posted

技术标签:

【中文标题】解决方法/摆脱 OneToMany 和 ManyToOne 关系中的多个可写映射?【英文标题】:workaround/get rid of multiple writable mappings in OneToMany and ManyToOne relationship? 【发布时间】:2011-06-28 18:42:09 【问题描述】:

我一直在尝试解决一个问题,但现在卡住了。 我有 2 个实体类/表 Order 和 OrderItem。 OrderItem 有 1 个 Order,Order 有 1..* OrderItems。

我的 EJB 工作正常,它添加订单、获取其 id 并添加订单项目

Order1 order = addOrder(project, name);
em.flush();
int orderId = order.getOrder();
addOrderItem(orderId, cart);

所以一切正常,订单ID也根据需要插入到订单项目行中。

但现在我想使用许多映射实体执行 JPQL,包括 Order 和 OrderItem。据我所知,要执行查询,我需要先映射我的实体,所以问题出在我的映射中。 这是映射

public class Order1 implements Serializable 

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "order_")
    private Integer order;
... 
    @OneToMany(mappedBy="orders",targetEntity=OrderItem.class, 
    fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private List<OrderItem> orderItems;
...


public class OrderItem implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "order_item")
    private Integer orderItem;
    @Column(name = "order_" /*, insertable=false, updatable=false*/)
    private BigInteger order;
...
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="order_")
    private Order1 orders;
...

通过这种映射,我在编译时遇到异常

Exception Description: Multiple writable mappings exist for the field [order_item.order_]. Only one may be defined as writable, all others must be specified read-only.

我用谷歌搜索并发现我必须使 OrderItem 中的订单列不可写。正如您在代码中看到的那样,我已经完成并编译,但是当我在我的应用程序中下订单时,订单 ID 不会插入到 order_item 的订单列中并且为 NULL。但是我不能这样,order_item中必须有订单参考。

我的 JPQL 查询是 createQuery("SELECT o.order FROM OrderItem oi JOIN oi.orders o"); 当我使 order_item 表中的 order 列不可插入时,它可以工作,但不能这样。有什么建议?我的映射有什么问题,为什么我不能在 order_item 中插入 order_?


更新关于@toto的回答:

我的实体是由 Netbeans 向导生成的。如果我不在OrderItem 中定义BigInteger order,那么我无法将order id 插入到我的order_item 表中。

我的 EJB 方法如下:

public Order1 addOrder(BigInteger project, BigInteger name) 

    Order1 order = new Order1();
...
    em.persist(order);
    return order;


private void addOrderItem(int orderId, ProjectCart cart) 

    // convert orderId int to BigInteger
    BigInteger oId = new BigInteger(String.valueOf(orderId));
    OrderItem orderItem = new OrderItem();
    orderItem.setOrder(oId);
....
    em.persist(orderItem);

所以这意味着如果我离开OrderItem

@Column(name = "order_")
private BigInteger order1;

我在OrderItem 中的order1 的getter 和setter 将不起作用,我不能在addOrderItem() 方法中使用orderItem.setOrder(oId) 只是因为我的order1 没有在OrderItem 中定义。另一件事是我的数据模型中没有外键,但我认为这不是问题,因为在映射中我设置了连接列。

【问题讨论】:

【参考方案1】:

您不得在 OrderItem 内定义名称为 order 的列 BigInteger order。它将由 JPA 自动(在后台)完成。编译器会报错,因为您正在创建一个已由 JPA 创建的列。

【讨论】:

嗨,我已经在我的帖子中进行了更新。我不能在OrderItem 中忽略order,因为我不能用我的setter 方法设置到order_item 表中。 @Skyzer 我认为你不应该有 setter 方法,只需将新项目添加到订单的映射列表中:order1.orderItems.add(...)。看起来您正在将 ORM 与手工数据库管理混合在一起,这只会给您带来一些冲突。尝试坚持纯 ORM。

以上是关于解决方法/摆脱 OneToMany 和 ManyToOne 关系中的多个可写映射?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate @OneToMany 与 mappedBy(父子)关系和缓存问题

级联保存不适用于 Hibernate 4 和 @OneToMany

破电脑终于摆脱虚拟机了,虽然我并不知道为什么

摆脱插入触发器

Doctrine 不会在我的 OneToMany 关联中保存数据

非冗余休眠列表映射 (OneToMany)