JPA ManyToOne关系:外键不存储在多方面的表中

时间:2016-06-13 17:39:23

标签: jpa save many-to-one

OneToMany关系的下属方:

@Entity
@Table(name="xxx_customer")
@XmlRootElement(name="Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer implements Serializable {

   @OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
   private List<CreditCard> creditCards;


   public void addCreditCart(CreditCard creditCard) {

       creditCards.add(creditCard);
   }

}

ManyToOne关系的拥有方:

@Entity
@Table(name="xxx_credit_card")
@XmlRootElement(name="CreditCard")
@XmlAccessorType(XmlAccessType.FIELD)
public class CreditCard implements Serializable {

    @ManyToOne(optional=false)
    @JoinColumn(name="customer_id", referencedColumnName="id")
    private Customer customer;
}

从OrderManager调用以创建Customer和CreditCard记录:

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class OrderManager {

    @Inject
    @UserDatabase
    private EntityManager em;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void placeOrder(ShoppingCart cart) {

        try
        {
            Customer customer = cart.getCustomer();
            customer.addCreditCart(cart.getCreditCard());
            em.persist(customer);
        }
        catch(Exception ex)
        {
            ctx.setRollbackOnly();

            MessageUtil.addMessage(FacesMessage.SEVERITY_ERROR, 
                    "Place Order", "Error placing order!");

            ex.printStackTrace();
        }
    }

}

在两个表中都创建了数据,但CreditCard表的customer_id字段为空。它没有按预期包含Customer记录的id。

1 个答案:

答案 0 :(得分:1)

为了获得双向关系,您必须确保一方的更新也会更新另一方。它可以通过&#34;添加&#34;来解决。或者&#34;设置&#34;像这样的方法:

您可以修改Customer类(建议的解决方案,因为您在经理代码中使用了add方法):

@Entity
@Table(name="xxx_customer")
@XmlRootElement(name="Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer implements Serializable {

   @OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
   private List<CreditCard> creditCards;


   public void addCreditCart(CreditCard creditCard) {
       if(creditCard.getCustomer()!=this) creditCard.setCustomer(this);
       creditCards.add(creditCard);
   }

}  

或修改CreditCard类,如下所示:

@Entity
@Table(name="xxx_credit_card")
@XmlRootElement(name="CreditCard")
@XmlAccessorType(XmlAccessType.FIELD)
public class CreditCard implements Serializable {

    @ManyToOne(optional=false)
    @JoinColumn(name="customer_id", referencedColumnName="id")
    private Customer customer;

    public setCustomer(Customer customer){
       if(!customer.getCreditCards().contains(this)) customer.getCreditCards().add(this);
       this.customer=customer;
    }
}

现在每次更新CreditCard实例中的客户字段时,您都会在另一方更新信用卡列表,反之亦然。 您可以修改这两个类,但必须确保不会获得无限循环。