JPA如何在双向ManyToOne中坚持父级

时间:2013-03-08 15:15:06

标签: java hibernate jpa

我的付款实体具有双向ManyToOne releshionship帐户。

@Table(name="account")
public class Account implements Serializable { 

    //bi-directional many-to-one association to Payment
    @OneToMany(mappedBy="account",fetch=FetchType.EAGER)
    private List<Payment> payments;

@Table(name="payment")
public class Payment implements Serializable { 

    //bi-directional many-to-one association to Account
    @ManyToOne(cascade={CascadeType.MERGE},fetch=FetchType.EAGER)
    @JoinColumn(name="idAcc")
    private Account account;

帐户实体已保留。我在浏览器和数据库中看到有关它的信息:

  

帐户[idAcc = 475,帐号= 12345678901230,isLock = N,休息= 10000.5]

然后我需要坚持孩子(支付实体)并同时更改账户实体(更改账户休息)。我使用这段代码。

    public class GenericDaoImpl<T> implements GenericDao<T> {

        protected Class<T> type; 
        protected EntityManagerFactory emf = null;

        public GenericDaoImpl(Class<T> type, EntityManagerFactory emf) { 
            this.emf = emf;
            this.type = type;       
        } 

        @Override
        public void create(T entity) throws Exception { 
            EntityManager em = null; 
            try { 
                em = getEntityManager();
                em.getTransaction().begin();  
                em.persist(entity); 
                em.getTransaction().commit(); 
            } 
...
@Override
    public T findById(String id) {
         EntityManager em = getEntityManager();
            try {
                Query query = em.createNamedQuery(type.getSimpleName()+".findByName");
                query.setParameter("id", id);
                return (T)query.getSingleResult();
            } finally {
                em.close();
            }
    }

daoPayments = new GenericDaoImpl(Payment.class,factory); 
            Payment payment = null;
                try {
                    payment = new Payment();
                    payment.setDescription("Shop 'Pirasmani'");
                    payment.setSumm(50.25);
                        Account account = (Account)daoAccount.findById(listAccount.get(0).getIdAcc());
                        account.setRest(account.getRest()-payment.getSumm());
                        payment.setAccount(account);
                        account.getPayments().add(payment);

                    daoPayments.create(payment);
                    //print result 
                    Payment paymentMerged = (Payment)daoPayments.read(payment);
                    out.println(paymentMerged.toString()+"<br>"); 

然后我在浏览器中看到帐户休息已更改:

  

付款[idPmnt = 91,说明=购买'Pirasmani',汇总= 50.25,   account = Account [idAcc = 475,account = 12345678901230,isLock = N,   其余= 9950.25]]

但在数据库中,帐户休息没有变化。它钢= 10000.5。 我究竟做错了什么?感谢。

1 个答案:

答案 0 :(得分:2)

您不应该在DAO方法中启动和停止事务。最后一节中的所有代码都应该在一个事务中,这将允许您

  • 处理附加实体,并自动保留帐户上的所有更改
  • 删除协会上不必要的cascade={CascadeType.MERGE}
  • 使数据库处于连贯状态,而不是像现在一样,处于已创建付款但其余部分未减少的状态(这就是我们首先使用交易的原因)。

那就是说,你坚持付款。为什么会导致其帐户的任何修改?您拥有的唯一级联是MERGE,并且您没有在代码中进行任何合并。