glassfish
  1. glassfish
  2. GLASSFISH-3218

Ignored sequence mapping in MappedSuperclass with postgres

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 9.1pe
    • Fix Version/s: 9.1pe
    • Component/s: entity-persistence
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      3,218
    • Status Whiteboard:
      Hide

      HIGH

      Show
      HIGH

      Description

      OS: WinXP
      JDK: 1.6.0_01
      JEE5: glassfish v2 b33e and b41d
      Postgres: 8.2 with postgresql-8.2-505.jdbc4.jar

      I'm trying to develop a JPA-mapping for an inherited database schema (see
      example below) in a Postgresql database. The abstract class vehicle takes the id
      attribute which is layed out as a serial field with a sequence called
      "vehicle_id_seq". This sequence needs to be reused for all entities inherited
      from vehicle. I tried versus mappings, even a transfer of attribute "id" to the
      inherited classes each with individual @SequenceGenerator and @GeneratedValue
      annotations (which cannot be a real solution from design view), but without
      luck. Obiously toplink constructs an automatic sequence name for the id-field in
      the subclass ignoring the mapping given in vehicle. I found similar reports in
      the forum:

      http://forums.java.net/jive/thread.jspa?messageID=220631

      and this bug seems close to an answer:

      https://glassfish.dev.java.net/issues/show_bug.cgi?id=283

      Here is some code which should help rebuild the problem:

      // Database Schema ///////////////////////////////////////////////
      CREATE TABLE vehicle
      (
      id serial NOT NULL,
      color character varying,
      CONSTRAINT vehicle_pkey PRIMARY KEY (id)
      )

      CREATE TABLE car
      (
      – Vererbt: id integer NOT NULL DEFAULT nextval('vehicle_id_seq'::regclass),
      – Vererbt: color character varying,
      num_wheels integer,
      CONSTRAINT "Car_pkey" PRIMARY KEY (id)
      ) INHERITS (vehicle)

      // Entity Mapping /////////////////////////////////////////////////
      @MappedSuperclass
      @SequenceGenerator(name="VEHICLE_SEQUENCE", sequenceName="vehicle_id_seq")
      public abstract class Vehicle implements Serializable {

      @Id
      @Column(name = "id", nullable = false)
      @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="VEHICLE_SEQUENCE")
      private Integer id;

      @Column(name = "color")
      private String color;

      public Vehicle() {
      }

      public String getColor()

      { return color; }

      public void setColor(String color)

      { this.color = color; }

      }

      @Entity
      @Table(name = "car")
      @SequenceGenerator(name="VEHICLE_SEQUENCE", sequenceName="vehicle_id_seq")
      public class Car extends Vehicle implements Serializable {

      @Column(name = "num_wheels")
      private Integer numWheels;

      public Car() {
      }

      public Integer getNumWheels()

      { return numWheels; }

      public void setNumWheels(Integer numWheels)

      { this.numWheels = numWheels; }

      }

      // Main application ///////////////////////////////////////////////
      public class Main {
      public Main()

      { EntityManagerFactory emf = Persistence.createEntityManagerFactory("MappedSuperclassBugPU"); EntityManager em = emf.createEntityManager(); Car myCar = new Car(); myCar.setColor("Rot"); myCar.setNumWheels(new Integer(4)); em.getTransaction().begin(); em.persist(myCar); em.getTransaction().commit(); }

      public static void main(String[] args)

      { new Main(); }

      }
      // Stderr ////////////////////////////////////////////////////////////////

      [TopLink Warning]: 2007.06.19 03:53:08.483-ClientSession(16382237)-Exception
      [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build 060830)):
      oracle.toplink.essentials.exceptions.DatabaseException
      Internal Exception: org.postgresql.util.PSQLException: ERROR: relation
      "car_id_seq" does not existError Code: 0
      Call:select currval('car_id_seq')
      Query:ValueReadQuery()
      Exception in thread "main" javax.persistence.RollbackException: Exception
      [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build 060830)):
      oracle.toplink.essentials.exceptions.DatabaseException
      Internal Exception: org.postgresql.util.PSQLException: ERROR: relation
      "car_id_seq" does not existError Code: 0
      Call:select currval('car_id_seq')
      Query:ValueReadQuery()
      at
      oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:109)
      at
      oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:45)
      at mappedsuperclassbug.Main.<init>(Main.java:19)
      at mappedsuperclassbug.Main.main(Main.java:23)
      Caused by: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build
      060830)): oracle.toplink.essentials.exceptions.DatabaseException
      Internal Exception: org.postgresql.util.PSQLException: ERROR: relation
      "car_id_seq" does not existError Code: 0
      Call:select currval('car_id_seq')
      Query:ValueReadQuery()
      at
      oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:303)
      at
      oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:551)
      at
      oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:437)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:675)
      at
      oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:213)
      at
      oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:199)
      at
      oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:270)
      at
      oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:252)
      at
      oracle.toplink.essentials.queryframework.DirectReadQuery.executeNonCursor(DirectReadQuery.java:110)
      at
      oracle.toplink.essentials.queryframework.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:97)
      at
      oracle.toplink.essentials.queryframework.ValueReadQuery.executeDatabaseQuery(ValueReadQuery.java:73)
      at
      oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:1815)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
      at
      oracle.toplink.essentials.sequencing.QuerySequence.select(QuerySequence.java:299)
      at
      oracle.toplink.essentials.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:245)
      at
      oracle.toplink.essentials.sequencing.StandardSequence.getGeneratedValue(StandardSequence.java:71)
      at
      oracle.toplink.essentials.sequencing.Sequence.getGeneratedValue(Sequence.java:234)
      at
      oracle.toplink.essentials.internal.sequencing.SequencingManager$NoPreallocation_State.getNextValue(SequencingManager.java:548)
      at
      oracle.toplink.essentials.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:832)
      at
      oracle.toplink.essentials.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:95)
      at
      oracle.toplink.essentials.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:225)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.updateObjectAndRowWithSequenceNumber(DatabaseQueryMechanism.java:977)
      at
      oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:336)
      at
      oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:176)
      at
      oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:190)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:457)
      at
      oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(InsertObjectQuery.java:74)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedWrite(DatabaseQueryMechanism.java:635)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedInsert(DatabaseQueryMechanism.java:599)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:495)
      at
      oracle.toplink.essentials.queryframework.WriteObjectQuery.executeCommitWithChangeSet(WriteObjectQuery.java:130)
      at
      oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:283)
      at
      oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:67)
      at
      oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
      at
      oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:536)
      at
      oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:123)
      at
      oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:95)
      at
      oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
      at
      oracle.toplink.essentials.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:254)
      at
      oracle.toplink.essentials.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:175)
      at
      oracle.toplink.essentials.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:2638)
      at
      oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1030)
      at
      oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:357)
      at
      oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1112)
      at
      oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:82)
      at
      oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:842)
      at
      oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:90)
      ... 3 more
      Caused by: org.postgresql.util.PSQLException: ERROR: relation "car_id_seq" does
      not exist
      at
      org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
      at
      org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
      at
      org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
      at
      org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
      at
      org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
      at
      org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:255)
      at
      oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:711)
      at
      oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:486)
      ... 52 more
      Java Result: 1

        Activity

        Hide
        ailitche added a comment -

        CORRECTION to the example, it should read:
        "Suppose that the previous call to select nextval returned 50.
        In that case our call returns 100"

        Show
        ailitche added a comment - CORRECTION to the example, it should read: "Suppose that the previous call to select nextval returned 50. In that case our call returns 100"
        Hide
        ailitche added a comment -

        CORRECTION 2:
        "Otherwise, with for instance INCREMENT BY = 1,
        select nextval in the example above would return 51, and TopLink will use
        2, ..., 51 likely causing unique constraint violation - which is I believe
        your case."

        Show
        ailitche added a comment - CORRECTION 2: "Otherwise, with for instance INCREMENT BY = 1, select nextval in the example above would return 51, and TopLink will use 2, ..., 51 likely causing unique constraint violation - which is I believe your case."
        Hide
        oliverwalczak added a comment -

        Thank you for the explanation. So how can I modify the default allocation size
        of 50 to 1? Where is it defined? Currently I would prefer to allocate each
        single nextval with each insert instead of changing the sequence mapping of each
        entity accepting the consequenses like performance loss etc. with this single
        adjustment, as any sequence I've got is defaulted to an allocation size of one.

        Show
        oliverwalczak added a comment - Thank you for the explanation. So how can I modify the default allocation size of 50 to 1? Where is it defined? Currently I would prefer to allocate each single nextval with each insert instead of changing the sequence mapping of each entity accepting the consequenses like performance loss etc. with this single adjustment, as any sequence I've got is defaulted to an allocation size of one.
        Hide
        ailitche added a comment -

        The default allocationSize is defined in the spec. (9.1.37) and can't be
        changed.
        You need to change all your SequenceGenerator annotations adding
        allocationSize=1

        Show
        ailitche added a comment - The default allocationSize is defined in the spec. (9.1.37) and can't be changed. You need to change all your SequenceGenerator annotations adding allocationSize=1
        Hide
        ailitche added a comment -

        The issue 2021 has been fixed, therefore the workaround described here is no
        longer required.

        Show
        ailitche added a comment - The issue 2021 has been fixed, therefore the workaround described here is no longer required.

          People

          • Assignee:
            tware
            Reporter:
            oliverwalczak
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: