ayengin
ayengin

Reputation: 1596

JPA @manytomany unidirectional mapping

When I try remove ExternalDataStorage This query throw a constraint violation exception with constraint name null .ExternalDataStorage has no relation mapping on it.Query first check ExternalTasks whichs contain ExternalDataStorage(Which will be removed) in ExternalTask's externalsources List and remove from list, if list is empty remove externaltask and finally remove ExternalDataStorage entity(Target entity).

      public boolean deleteExternalDataStorage(Long sid) {
     EntityManager em = getEntityManager();
    EntityTransaction et = em.getTransaction();
    try {
        et.begin();
        ExternalDataStorage s = em.find(ExternalDataStorage.class, sid);
        List<ExternalTask> tasks = (List<ExternalTask>) em.createQuery("SELECT t FROM ExternalTask t ").getResultList();
        for (ExternalTask t : tasks) {
            if (t.getExternalSources().contains(s)) {
                t.getExternalSources().remove(s);
                if (t.getExternalSources().isEmpty()) {
                    em.remove(t);
                } else {
                    t = em.merge(t);
                }
            }
        }
        em.remove(s);
        et.commit();
        return true;
    } catch (Exception e) {
        e.printStackTrace();


    } finally {
        if (et.isActive()) {
            et.rollback();
        }
    }
    return false;
}

@Entity public class ExternalTask implements Serializable {

@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(name = "ExternalTask_ExternalSource", joinColumns = @JoinColumn(name = "TID"), inverseJoinColumns = @JoinColumn(name = "EXID"))
private  List<ExternalDataStorage> externalSources =new ArrayList<ExternalDataStorage>();


@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(name = "ExternalTask_Archive", joinColumns = @JoinColumn(name = "TID"), inverseJoinColumns = @JoinColumn(name = "AID"))
protected  List<Archive> archives=new ArrayList<Archive>();


@ManyToOne
private User  ownerUser;

_EDIT___________________

I change query a little for delete case but problem still there

  EntityManager em = getEntityManager();
        EntityTransaction et = em.getTransaction();
        try {
            et.begin();
            ExternalDataStorage s = em.find(ExternalDataStorage.class, sid);
            List<ExternalTask> tasks=(List<ExternalTask>) em.createQuery("SELECT t FROM ExternalTask t ").getResultList();
           for(ExternalTask t:tasks) {
              if(t.getExternalSources().contains(s)){
                 t.getExternalSources().remove(s);
                  t= em.merge(t);
                  if(t.getExternalSources().isEmpty()){
                      em.remove(t);
                  }
               }
           }                 
            em.remove(s);
            et.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();


        } finally {
            if (et.isActive()) {
                et.rollback();
            }
        }
        return false;
    }

This is exception

**377249 [http-8080-2] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: null
377249 [http-8080-2] ERROR org.hibernate.util.JDBCExceptionReporter  - Batch entry 0 delete from ExternalSource where EXID=6 was aborted.  Call getNextException to see the cause.
377249 [http-8080-2] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 23503
377249 [http-8080-2] ERROR org.hibernate.util.JDBCExceptionReporter  - ERROR: update or delete on table "externalsource" violates foreign key constraint "fk755287f526733b01" on table "externaltask_externalsource"
  Detail: Key (exid)=(6) is still referenced from table "externaltask_externalsource".
377250 [http-8080-2] ERROR org.hibernate.event.def.AbstractFlushingEventListener  - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
    at com.endersys.itap.ui.module.storage.StorageManager.deleteExternalDataStorage(StorageManager.java:351)
    at com.endersys.itap.ui.module.storage.ExternalDataStorageEditorBean.delete(ExternalDataStorageEditorBean.java:73)
    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 org.apache.el.parser.AstValue.invoke(AstValue.java:172)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
    at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
    at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:78)
    at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:57)
    at javax.faces.component.UICommand.broadcast(UICommand.java:127)
    at org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55)
    at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:329)
    at org.ajax4jsf.component.AjaxViewRoot.broadcastEventsForPhase(AjaxViewRoot.java:304)
    at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:261)
    at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:474)
    at org.apache.my**faces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:183)
    at org.apache.myfaces.webapp.MyFacesServlet.service(MyFacesServlet.java:103)
    at com.endersys.itap.ui.MyFacesServletWrapper.service(MyFacesServletWrapper.java:34)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:341)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206)
    at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
    at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.endersys.itap.ui.MenuFilter.doFilter(MenuFilter.java:169)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:636)

Caused by: java.sql.BatchUpdateException: Batch entry 0 delete from ExternalSource where EXID=6 was aborted. Call getNextException to see the cause. at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2537) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1328) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:351) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2674) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242) ... 55 more javax.persistence.RollbackException: Error while commiting the transaction at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71) at com.endersys.itap.ui.module.storage.StorageManager.deleteExternalDataStorage(StorageManager.java:351) at com.endersys.itap.ui.module.storage.ExternalDataStorageEditorBean.delete(ExternalDataStorageEditorBean.java:73) 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 org.apache.el.parser.AstValue.invoke(AstValue.java:172) at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276) at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68) at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:78) at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:57) at javax.faces.component.UICommand.broadcast(UICommand.java:127) at org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55) at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:329) at org.ajax4jsf.component.AjaxViewRoot.broadcastEventsForPhase(AjaxViewRoot.java:304) at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:261) at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:474) at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32) at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103) at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:183) at org.apache.myfaces.webapp.MyFacesServlet.service(MyFacesServlet.java:103) at com.endersys.itap.ui.MyFacesServletWrapper.service(MyFacesServletWrapper.java:34) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:341) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206) at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388) at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.endersys.itap.ui.MenuFilter.doFilter(MenuFilter.java:169) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:636) Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54) ... 47 more Caused by: java.sql.BatchUpdateException: Batch entry 0 delete from ExternalSource where EXID=6 was aborted. Call getNextException to see the cause. at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2537) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1328) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:351) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2674) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242) ... 55 more

And this is constraint on table



ALTER TABLE externaltask_externalsource
  ADD CONSTRAINT fk755287f526733b01 FOREIGN KEY (exid)
      REFERENCES externalsource (exid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION;

Upvotes: 1

Views: 3335

Answers (2)

ayengin
ayengin

Reputation: 1596

I add join fetch and problem solved.

public boolean deleteExternalDataStorage(Long sid) {
        EntityManager em = getEntityManager();
        EntityTransaction et = em.getTransaction();

        try {
            et.begin();
            ExternalDataStorage s = em.find(ExternalDataStorage.class, sid);            
            List<ExternalTask> tasks=(List<ExternalTask>) em.createQuery("SELECT t FROM ExternalTask t join fetch t.externalSources").getResultList();
           for(ExternalTask t:tasks) {
              if(t.getExternalSources().contains(s)){
                      t.getExternalSources().remove(s);
                  if(t.getExternalSources().isEmpty()){
                      em.remove(t);
                  }
               }
           }       
            em.remove(s);
            et.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
             if (et.isActive()) {
                et.rollback();
            }

        } finally {

        }
        return false;
    }

Upvotes: 0

OpenSource
OpenSource

Reputation: 2257

Find it little bit hard to understand the question. I'm assuming you are looking for the externalsources to be removed when you remove the externaltask entity. I think for that you need to include REMOVE in your cascade settings or basically cascade={CascadeType.ALL}

EDIT: Think I found the answer to your situation. When the many to many is wired the PP creates an integrity constraint on the db (I'm thinking you are doing an auto gen of the schema from the entities).

In this case SOURCE_TASK table where the relationship between source and task is held, has a foreign key relationship towards SOURCE table. So when you try to remove something from SOURCE table the underlying db gives a sql exception. I was able to reproduce your issue.

Solution: What I did was I removed the foreign key constraint and I was able to remove the source entity fine.

As I originally stated for the TASK to SOURCE removal If you remove the TASK entity with Cascade.ALL it should remove the entries everywhere.

Update: I'm thinking there is something in the way you are dealing with equality among your SOURCE objects. The List.contains(o) will be true if at least one object that is 'equal' is found. The List.remove(o) will remove the first occurrence of an object that 'equals' o. So I bet there are multiple occurrences of 'equal' objects inside the list.

Upvotes: 1

Related Questions