Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA如何在双向manytone中持久化父级_Java_Hibernate_Jpa - Fatal编程技术网

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>");