许多关系不要坚持

时间:2012-08-05 12:49:19

标签: foreign-keys jpa-2.0

当我尝试持久化父实体时,它仍然存在,但是当我尝试子实体时,它会返回错误。

这是父实体

@Entity(name="Parent_Detail")
public class Parent implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "Parent_ID", nullable = false)
    private Integer parent_id;

    public Integer getParent_id() {
        return parent_id;
    }

    public void setParent_id(Integer parent_id) {
        this.parent_id = parent_id;
    }


}

这是儿童实体

@Entity
public class Child implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "Child_ID", nullable = false)
    private Integer child_id;

    @ManyToOne
    private Parent parent;

    public Integer getChild_id() {
        return child_id;
    }

    public void setChild_id(Integer child_id) {
        this.child_id = child_id;
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }






}

这是孩子的会话bean

@Stateless
@LocalBean
public class ChildSessionBean {
    @PersistenceContext(unitName = "WebApplication4PU")
    private EntityManager em;

    public void persist(Object object) {
        em.persist(object);
    }





}

这是父母的Sesion Bean(它工作正常)

@Stateless
@LocalBean
public class ParentSessionBean {
    @PersistenceContext(unitName = "WebApplication4PU")
    private EntityManager em;

    public void persist(Object object) {
        em.persist(object);
    }



}

这是孩子的托管Bean

public class ChildManagedBean {
    @EJB
    private ChildSessionBean childSessionBean;
    private Child child = new Child(); 

    public ChildManagedBean() {
    }

    public Child getChild() {
        return child;
    }

    public void setChild(Child child) {
        this.child = child;
    }
    public void save(){
        child.setParent(new Parent());
        childSessionBean.persist(child);
    }
}

这是父级的managedBean

public class ParentManagedBean {
    @EJB
    private ParentSessionBean parentSessionBean;
    private Parent parent = new Parent();


    public ParentManagedBean() {
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }
    public void save(){
        parentSessionBean.persist(parent);
    }
}

这是Child JSF页面:我保持简单,没有下拉列表。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            Child ID :<h:inputText value="#{childManagedBean.child.child_id}" /><br/>
            Parent ID :<h:inputText value="#{childManagedBean.child.parent}" /><br/>
            <h:commandButton action="#{childManagedBean.save()}"  immediate="true"/>
        </h:form>
    </h:body>
</html>

这是错误页面

javax.faces.el.EvaluationException: javax.ejb.EJBException: Transaction aborted
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:935)
    at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:636)
Caused by: javax.ejb.EJBException: Transaction aborted
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5142)
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
    at $Proxy402.persist(Unknown Source)
    at SessionBean.__EJB31_Generated__ChildSessionBean__Intf____Bean__.persist(Unknown Source)
    at managedBean.ChildManagedBean.save(ChildManagedBean.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:779)
    at javax.el.BeanELResolver.invoke(BeanELResolver.java:528)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:257)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:248)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 32 more
Caused by: javax.transaction.RollbackException: Transaction marked for rollback.
    at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:473)
    at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:855)
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5136)
    ... 53 more
Caused by: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: bean.Parent@13d247e.
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:304)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:702)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1490)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3143)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:346)
    at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:157)
    at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68)
    at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:435)
    ... 55 more

1 个答案:

答案 0 :(得分:1)

异常消息说明了一切:

During synchronization a new object was found through a relationship that was not marked cascade PERSIST: bean.Parent@13d247e

你想要坚持一个孩子。孩子的父母是新的父母。父不是持久的。因此,你试图坚持一个没有持久性的父母的孩子。它无法运作。

您想要的是为现有父级保存新子级,然后您必须将此现有父级附加到子级:

Parent existingParent = em.getReference(Parent.class, existingParentId);
Child child = new Child();
child.setParent(existingParent);
em.persist(child);

或者你想一次性保存一个新父母的新孩子,你必须坚持父母,然后是孩子:

Parent parent = new Parent();
Child child = new Child();
child.setParent(existingParent);
em.persist(parent);
em.persist(child);

或者您希望一次性使用新父级保存新子项,并且当子项被持久化时让JPA自动保留父项,然后您必须使持久化级联

@ManyToOne(cascade = CascadeType.PERSIST)
private Parent parent;

...

Parent parent = new Parent();
Child child = new Child();
child.setParent(existingParent);
em.persist(child);