0
我有支付实体双向ManyToOne releshionship帐户。JPA如何坚持双向ManyToOne父母
@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,帐户= 123456789,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',SUMM = 50.25, account = Account [idAcc = 475,account = 123456789,isLock = N, rest = 9950.25]]
但是在数据库中账户休息没有变化。钢= 10000.5。 我在做什么错?谢谢。
感谢您的快速响应。为什么我不应该在DAO方法中启动和停止事务?我在JPA的例子中发现了DAO的标准代码。所以我为所有实体使用一个通用的DAO.class。而且,据我所知,JPA注释使用这个通用的DAO为我打了个洞。我认为我的注释有问题。有没有其他方式如何解决我的问题,而无需更改DAO或我需要为每个实体编写特定的DAO? – Foontik 2013-03-08 16:03:17
因为交易的重点是保证ACIDity(原子性,连贯性,隔离性,耐久性)。您希望您的数据保持一致:或者创建了付款,其余的数据都减少了,或者这两个操作都没有完成。这就是交易被使用的原因。如果每个操作都是在单个事务中完成的,那么您的数据库不会保持一致状态(正如您刚刚看到的那样)。事务应该由服务层划分,而不是由DAO层划分。 – 2013-03-08 16:06:56
好的,谢谢,我明白了,但如果我在服务层中移动了交易,我的老师不会很高兴。我知道什么是ACID。我曾经想过,如果我改变第一个实体和第二个实体(由Cascade注释映射)比坚持第一个实体,所以这会自动改变其他实体的单个事务。这不是JPA的主要特性吗?而且我知道它的效果很好,例如,如果您创建父项并添加他的新子项,那么对于“OneToMany”,只需坚持父项。在这种情况下,不需要编码Cascade注释。全部存储在单个事务中。 – Foontik 2013-03-08 17:12:39