Java JPA如何在双向manytone中持久化父级
我有一个与账户双向多通相关的支付实体Java JPA如何在双向manytone中持久化父级,java,hibernate,jpa,Java,Hibernate,Jpa,我有一个与账户双向多通相关的支付实体 @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; @Ta
@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;
@表(name=“account”)
公共类帐户实现可序列化{
//双向多对一支付关联
@OneToMany(mappedBy=“account”,fetch=FetchType.EAGER)
私人清单付款;
@表(name=“付款”)
公共类支付实现可序列化{
//要考虑的双向多对一关联
@manytone(cascade={CascadeType.MERGE},fetch=FetchType.EAGER)
@JoinColumn(name=“idAcc”)
私人帐户;
帐户实体已持久化。我在浏览器和数据库中看到了有关该实体的信息:
账户[idAcc=475,账户=1234567890130,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();
}
}
公共类GenericDaoImpl实现GenericDao{
保护类类型;
受保护的EntityManagerFactory emf=null;
公共GenericDaoImpl(类类型,EntityManagerFactory emf){
this.emf=emf;
this.type=type;
}
@凌驾
public void create(T实体)引发异常{
EntityManager em=null;
试试{
em=getEntityManager();
em.getTransaction().begin();
em.persist(实体);
em.getTransaction().commit();
}
...
@凌驾
公共T findById(字符串id){
EntityManager em=getEntityManager();
试一试{
Query Query=em.createNamedQuery(type.getSimpleName()+“.findByName”);
query.setParameter(“id”,id);
return(T)query.getSingleResult();
}最后{
em.close();
}
}
及
daoPayments=new GenericDaoImpl(Payment.class,factory);
付款=空;
试一试{
付款=新付款();
付款。设置说明(“Pirasmani”商店);
付款总额(50.25);
Account Account=(Account)daoccount.findById(listcount.get(0.getIdAcc());
account.setRest(account.getRest()-payment.getSumm());
付款。设置账户(账户);
account.getPayments().add(付款);
daoPayments.create(付款);
//打印结果
Payment paymentMerged=(付款)daoPayments.read(付款);
out.println(paymentMerged.toString()+“
”;
然后我在浏览器中看到帐户rest已更改:
付款[idPmnt=91,说明=Pirasmani商店,总和=50.25,
account=account[idAcc=475,account=1234567890130,isLock=N,
剩余=9950.25]]
但在数据库中,帐户的剩余部分并没有变化。它是=10000.5。
我做错了什么?谢谢。您不应该在DAO方法中启动和停止事务。最后一节中的所有代码都应该在一个事务中,这样您就可以
- 处理附加的实体,并自动保留对帐户所做的所有更改
- 删除关联上不必要的
cascade={CascadeType.MERGE}
- 让数据库保持一致状态,而不是像现在那样,处于一种支付已经创建但剩余部分没有减少的状态(这就是为什么我们首先使用事务)
也就是说,您坚持支付。为什么这会导致对其帐户进行任何修改?您唯一的级联是合并,并且您没有在代码中进行任何合并。感谢您的快速响应。为什么我不应该在DAO方法中启动和停止事务?我在JPA示例中找到了DAO的标准代码。因此,我使用了一个通用DA所有实体的O.class。而且,据我所知,JPA注释使我能够使用这个通用DAO。我认为我的注释有问题。有没有其他方法可以在不更改DAO的情况下解决我的问题,或者我需要为每个实体编写特定的DAO?因为事务的全部要点是保证可用性(原子性、一致性、隔离性、持久性)。您希望数据保持一致性:要么创建付款,要么减少其余部分,要么这两个操作都不执行。这就是使用事务的原因。如果每个操作都在单个事务中执行,则数据库不会保持一致性状态(正如您刚才看到的).事务应该由服务层来划分,而不是DAO层。好的,谢谢,我理解,但是如果我将事务移动到服务层,我的老师不会很高兴。我非常清楚什么是ACID。我想如果我更改第一个实体和第二个实体(通过级联注释映射)这不是JPA的主要idia吗?我知道它很好用,例如,对于“OneToMany”如果您创建父级并添加其新子级,只需为父级设置persist。在这种情况下,无需编写代码,因为级联注释。所有这些都存储在单个事务中。Cascade.MERGE级联合并操作。您不调用MERGE。如果您的老师对此不满意,请选择另一位老师,因为他不知道什么是h如果在DAO层划分事务,您将如何处理更新付款、插入统计信息、删除债务和发送JMS消息的单个事务?您的整个业务逻辑不能通过级联注释实现。
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>");