glassfish
  1. glassfish
  2. GLASSFISH-699

Incorrect handling of EntityManager.remove()

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 9.0pe
    • Fix Version/s: not determined
    • Component/s: entity-persistence
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      699
    • Status Whiteboard:
      Hide

      MEDIUM

      Show
      MEDIUM

      Description

      I have been doing some experiments building JPA entity classes for tables in an
      existing database, rather than letting JPA build the schema for me.
      (Specifically, I am using the TRAVEL database that comes with Java Studio
      Creator 2 Update 1). For the purposes of this discussion, the important aspects
      are a master-detail relationship between the PERSON and TRIP tables, which is
      represented by a PERSONID column in the TRIP table that has a foreign key
      relationship with the PERSON table. This column is also NOT NULL, which is key
      to reproducing the problem issue.

      Next, I created entity classes for these tables using NetBeans 5.5 Beta. The
      relevant parts of the two classes are as follows:

      @Entity
      public class Person implements Serializable {
      ...
      @OneToMany(mappedBy="person")
      private List<Trip> trips;
      public List<Trip> getTrips()

      { return this.trips; }

      public void setTrips(List<Trip> trips)

      { this.trips = trips; }

      ...
      public void addTrip(Trip trip) {
      if ((trip == null) || (trips == null))

      { return; }
      if (!trips.contains(trip)) { trip.setPerson(this); trips.add(trip); }
      }
      public void removeTrip(Trip trip) {
      if ((trip == null) || (trips == null)) { return; }

      if (trips.contains(trip))

      { trips.remove(trip); trip.setPerson(null); }

      }
      ...
      }

      @Entity
      public class Trip implements Serializable

      { ... @JoinColumn(name="personid") @ManyToOne private Person person; ... }

      The addTrip() and removeTrip() logic was modelled after the NetBeans 5.5
      persistence example, allowing the developer to deal with the relationship solely
      through normal Java manipulations – and also to obey the JPA Spec requirement
      that the application is responsible for maintaining the validity of relationship
      variables.

      Now, in my application, I attempt to delete a Trip:

      utx.begin();
      Trip trip = ...; // The trip to be deleted
      trip = em.merge(trip); // (it was previously detached)
      trip.getPerson().removeTrip(trip);
      em.remove(trip);
      utx.commit();

      However, this causes an exception (from the commit). The underlying cause
      reported by the persistence engine is an attempt to execute the following statement:

      UPDATE TRIP SET PERSONID = NULL WHERE TRIPID = 123

      to reflect the fact that the Person property was set to null in the Trip entity.
      However, because PERSONID is a NOT NULL column in the database schema, this
      update fails. Removing the "trip.setPerson(null)" statement from the
      removeTrip() method makes the operation succeed, but appears to violate the
      requirements of Section 2.1.7 of the Persistence spec, which says:

      Note that it is the application that bears responsibility
      for maintaining the consistency of runtime relatinships –
      for example, for ensuring that the "one" and "many" sides of
      a bidirectional relationship are consistent with one another
      when the application updates the relationship.

      I believe that the updates should be skipped when it is known that the row is
      going to be deleted anyway.

      NOTE: There is a separate, but pretty bad, usability problem in how an
      application is notified of an error like this, and it seems to be common to all
      cases where the underlying SQL statement execution fails. The exception
      remported back to the application, from the utx.commit() call, is "Rollback
      Exception: Transaction has been marked for rollback" with no clue to what
      caused the problem. You have to dig in to the server log to get a handle on the
      actual problem (fortunately, the exception that is logged there is very detailed
      and helpful). But the actual problem exception should really be visible somehow
      in the exception that is returned to the application.

        Activity

        No work has yet been logged on this issue.

          People

          • Assignee:
            mf125085
            Reporter:
            craig_mcc
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: