添加Spring事务时保持三重关联

时间:2013-06-12 13:44:35

标签: jpa associations persistence eclipselink spring-transactions

我有一个使用JPA(EclipseLink)和Spring框架的Java EE应用程序。

在我的持久化类中,一切都运行正常,直到我添加了Spring事务管理。 我有以下实体(对应于数据库表):

  • 项目

    @Entity
    @Table(name="projet")
    public class Projet implements Serializable {
     private static final long serialVersionUID = 1L;
    
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     @Column(name="id_projet", unique=true, nullable=false)
     private Integer idProjet;
    
     @Column(name="nom_projet")
     private String nomProjet;
    
     /** The projet util droits. */
     @OneToMany(mappedBy="projet", cascade={CascadeType.ALL})
     private Set<ProjetUtilDroit> projetUtilDroits;
    
         public Projet() {
         }
    
        ...
    }
    
  • 用户

    @Entity
    @Table(name="utilisateur")
    public class Utilisateur implements Serializable {
    
         /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 1L;
    
     /** The id utilisateur. */
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     @Column(name="id_utilisateur", unique=true, nullable=false)
     private Integer idUtilisateur;
    
      /** The nom utilisateur. */
     @Column(name="nom_utilisateur", nullable=false, length=50)
     private String nomUtilisateur;
    
     //bi-directional many-to-one association to ProjetUtilDroit
     /** The projet util droits. */
     @OneToMany(mappedBy="utilisateur", cascade={CascadeType.REMOVE})
     private Set<ProjetUtilDroit> projetUtilDroits;
    
          ...
      }
    
  • @Entity
    @Table(name="droit")
    public class Droit implements Serializable {
    
      /** The Constant serialVersionUID. */
     private static final long serialVersionUID = 1L;
    
     /** The id droit. */
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     @Column(name="id_droit", unique=true, nullable=false)
     private Integer idDroit;
    
     /** The type droit. */
     @Column(name="type_droit", nullable=false, length=10)
     private String typeDroit;
    
         /**
          * Instantiates a new droit.
          */
         public Droit() {
         }
        ...
    }
    
  • 将用户链接到具有特定权利的项目的关联(ProjectUserRight)

    @Entity
    @Table(name="projet_util_droit")
    public class ProjetUtilDroit implements Serializable {
    
     /** The Constant serialVersionUID. */
     private static final long serialVersionUID = 1L;
    
     /** The id. */
     @EmbeddedId
     private ProjetUtilDroitPK id;
    
     //bi-directional many-to-one association to Droit
         /** The droit. */
     @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
     @JoinColumn(name="id_droit")
     private Droit droit;
    
     //bi-directional many-to-one association to Projet
     /** The projet. */
     @MapsId("idProjet")
         @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
         @JoinColumn(name="id_projet")
     private Projet projet;
    
     //bi-directional many-to-one association to Utilisateur
         /** The utilisateur. */
     @MapsId("idUtilisateur")
         @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
     @JoinColumn(name="id_utilisateur")
     private Utilisateur utilisateur;
    
        ...
        }
    
  • 关联的嵌入式ID:

    @Embeddable
    public class ProjetUtilDroitPK implements Serializable {
    
     //default serial version id, required for serializable classes.
     /** The Constant serialVersionUID. */
     private static final long serialVersionUID = 1L;
    
      /** The id projet. */
      @Column(name="id_projet", unique=true, nullable=false)
      private Integer idProjet;
    
      /** The id utilisateur. */
      @Column(name="id_utilisateur", unique=true, nullable=false)
      private Integer idUtilisateur;
    
       ...
    }
    

我的方法正确创建项目:

   public Projet createProject(String name, int idRight, int idUser) {
    Projet project = new Projet();
    project.setNomProjet(name);
    ProjetUtilDroit pud = new ProjetUtilDroit();
    Droit d = rightDao.findById(idRight);
    pud.setDroit(d);
    pud.setProjet(project);
    Utilisateur user = userDao.findById(idUser);
    pud.setUtilisateur(user);
    if(user.getProjetUtilDroits() == null)
        user.setProjetUtilDroits(new HashSet<ProjetUtilDroit>());
    user.getProjetUtilDroits().add(pud);
    Set<ProjetUtilDroit> pudSet = new HashSet<ProjetUtilDroit>();
    pudSet.add(pud);
    project.setProjetUtilDroits(pudSet);
    project = projectDao.create(project);
    return project;
}

它就像一个魅力(持久化项目和相关的用户权限),直到我在&#34; createProject&#34;之上添加注释@Transactionnal。方法...

现在我收到此错误: Avertissement:StandardWrapperValve [dispatcher]:PWC1406:Servlet调度程序的Servlet.service()抛出异常 java.lang.IllegalStateException:在同步期间,通过未标记为级联PERSIST的关系找到新对象: * **** 项目权 * *** 用户名:userName右:读。     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.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:433)     在org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)     在org.eclipse.persistence.internal.jpa.EJBQueryImpl.performPreQueryFlush(EJBQueryImpl.java:1298)     在org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:434)     在org.eclipse.persistence.internal.jpa.EJBQueryImpl.getResultList(EJBQueryImpl.java:742)     在com.dao.BasicDAO.findAll(BasicDAO.java:92)     在com.dao.BasicDAO.create(BasicDAO.java:103)     在com.services.ProjectService.createProject(ProjectService.java:48)     at com.services.ProjectService $$ FastClassByCGLIB $$ 67c85b9f.invoke()     在net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)     在org.springframework.aop.framework.Cglib2AopProxy $ CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)     在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)     在org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)     在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)     在org.springframework.aop.framework.Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)     at com.services.ProjectService $$ EnhancerByCGLIB $$ 398fa756.createProject()     在com.servlet.Test.handleCreateProject(Test.java:31)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:601)     在org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)     在org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)     在org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)     在org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)     在org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)     在org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)     在org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)     在org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)     在org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)     在org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:668)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:770)     在org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)     在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)     在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)     在org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)     在org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)     在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)     在org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)     在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)     在com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)     在com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)     在com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)     at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)     在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)     在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)     在com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)     at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)     在com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)     在com.sun.grizzly.ContextTask.run(ContextTask.java:71)     at com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:532)     在com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:513)     在java.lang.Thread.run(Thread.java:722)

我想到的唯一解决方案是在一个事务中创建项目并在另一个事务中单独保存其权限。这是唯一的解决方案还是有人有另一个建议?

1 个答案:

答案 0 :(得分:0)

哪个对象没有保留?包括完整的例外。

您需要将对象的关系标记为级联持久化,或者在持久化项目之前调用对象的持久性。