Announcement Announcement Module
Collapse
No announcement yet.
NonUniqueObjectException Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • NonUniqueObjectException

    I have mapped about 20 domain objects or so in my application, and I am getting a problem with one object in particular when I try to persist updates to the object. I load the object in a formBackingObject() call. In onSubmit, I then call saveOrUpdate. I get a NonUniqueObjectException. What puzzles me is that I have done nothing that appears to be significantly different in this particular class, and I have not seen this behavior with any of my other classes.

    My class is called PromotionOccurrence. It has a many-to-one with class Promotion, and a many-to-many association with a Reseller class. Judging from the attached stack trace, it looks like hibernate is checking cascade rules, but I'm not familiar enough with the SessionImpl to know what types of things I could have screwed up in my hibernate and/or spring configuration.

    net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 17, of class: com.galt.viper.common.dto.service.PromotionOccurre nc
    e
    at net.sf.hibernate.impl.SessionImpl.checkUniqueness( SessionImpl.java:1677)
    at net.sf.hibernate.impl.SessionImpl.doUpdateMutable( SessionImpl.java:1443)
    at net.sf.hibernate.impl.SessionImpl.doUpdate(Session Impl.java:1470)
    at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(Ses sionImpl.java:1393)
    at net.sf.hibernate.engine.Cascades$4.cascade(Cascade s.java:114)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:436)
    at net.sf.hibernate.engine.Cascades.cascadeCollection (Cascades.java:526)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:452)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:503)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:482)
    at net.sf.hibernate.impl.SessionImpl.doUpdate(Session Impl.java:1475)
    at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(Ses sionImpl.java:1393)
    at net.sf.hibernate.engine.Cascades$4.cascade(Cascade s.java:114)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:436)
    at net.sf.hibernate.engine.Cascades.cascadeCollection (Cascades.java:526)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:452)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:503)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:482)
    at net.sf.hibernate.impl.SessionImpl.doUpdate(Session Impl.java:1475)
    at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(Ses sionImpl.java:1393)
    at org.springframework.orm.hibernate.HibernateTemplat e$13.doInHibernate(HibernateTemplate.java:344)
    at org.springframework.orm.hibernate.HibernateTemplat e.execute(HibernateTemplate.java:200)
    at org.springframework.orm.hibernate.HibernateTemplat e.saveOrUpdate(HibernateTemplate.java:341)
    at com.galt.viper.data.service.HibernatePromotionDaoI mpl.savePromotionOccurrence(HibernatePromotionDaoI mpl.java:34)


    Here is the snippet from my hibernate configuration for PromotionOccurrence:

    <set
    name="retailers"
    table="RESELLER_PROMOTIONS"
    lazy="false"
    inverse="false"
    cascade="save-update"
    sort="unsorted"
    >

    <key
    column="PROMOTION_OCCURRENCE_ID"
    >
    </key>

    <many-to-many
    class="com.galt.viper.common.dto.reseller.Reseller "
    column="RESELLER_USERNAME"
    outer-join="auto"
    />

    </set>

    <many-to-one
    name="promotion"
    class="com.galt.viper.common.dto.service.Promotion "
    cascade="none"
    outer-join="auto"
    update="true"
    insert="true"
    access="property"
    column="PROMOTION_ID"
    not-null="true"
    />

    FWIW, I'm managing transactions through a service tier class that starts a new transaction, and I have two dao's called by that service class that join existing transactions.

    I tried switching to saveOrUpdateCopy, and the error goes away, but the new changes are not saved. Any help that can point me in the right direction will be greatly appreciated as I've been spinning wheels on this for quite a while and may just be missing something really simple.

  • #2
    net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 17, of class: com.galt.viper.common.dto.service.PromotionOccurre nce
    I already meet this exception and, AFAIK, it has nothing to do with classes mapping. You are, more likely, binding two instances with the same identifier to the same HibernateSession.
    Could you show how you use your object in your FormController?

    Comment


    • #3
      Certainly.

      public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception
      {
      PromotionOccurrence occurrence = (PromotionOccurrence)command;

      promotionService.savePromotionOccurrence(occurrenc e);
      if (StringUtils.isNotEmpty(redirectLocation)) { //redirect to appropriate page, appending a param that will let that page know which promotion to default to
      response.sendRedirect(redirectLocation + "?" + lookupHelper.getRequestParameterName() + "=" + occurrence.getPromotion().getPromotionId());
      return null;
      }
      return new ModelAndView(getSuccessView());
      }

      This calls a service that delegates to a dao, and that dao calls saveOrUpdate() on getHibernateTemplate().


      Here are two other methods, but AFAIK, they aren't called during the same request as onSubmit, so I don't see how they'd be using the same hibernate session:

      protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) {
      lookupHelper.resetBooleans(request, (BaseDto)command);
      }

      protected Object formBackingObject(HttpServletRequest request) throws ServletException {
      String idString = request.getParameter("typeId");
      if (StringUtils.isNotEmpty(idString))
      return promotionService.findPromotionOccurrence(Integer.v alueOf(idString));

      PromotionOccurrence occurrence = new PromotionOccurrence();

      occurrence.setEnteredBy(ViperServletUtil.getUser(r equest.getSession()));
      String promotionIdString = request.getParameter("promotionId");
      if (StringUtils.isNotEmpty(promotionIdString)) {
      Promotion promo = (Promotion)dtoService.findDtoById(Promotion.class, Integer.valueOf(promotionIdString));
      occurrence.setPromotion(promo);
      }

      return occurrence;
      }

      Thanks for any guidance you can provide me.

      Comment


      • #4
        I just noted something new on this problem. If I don't have any items in the retailers set, I can update any other fields that I want and I don't get an errorr when persisting.

        Comment


        • #5
          I just switched the cascade from save-update to none. I understand why I don't need cascades in this case, but I don't know that I understand why this would fix my error.

          Comment

          Working...
          X