You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Andrew Thompson <at...@columbia.edu> on 2009/05/25 20:49:55 UTC

Trouble with TableGenerated @Id's the first time an object type is loaded.

Hello Folks,

I've been banging my head on this for a few days and not coming up with
much.   Tips on where to look / debug would be much appreciated.

Problem Summary:
For entity beans using @TableGenerator and @GeneratedValue to generate
primary key values, we consistently get a duplicate key row error when
invoking save for the first time on an object of a given type.  By that
I mean, it only seems to fail when a request to the TableGenerator is
required.  Subsequent GeneratedValue invocations work fine, presumably
because the next value to be used for that primary key is in memory?

Environment: 
Database: We use sybase 12.5.  Note, we extended an sybase dictionary to
do some things like trim strings.   
JDBC Driver:  we use the jconnect2 jdbc
com.sybase.jdbc2.jdbc.SybConnectionPoolDataSource driver managed by dbcp
pooledconnection.   
Servlet Container: Tomcat.
Spring:  we use spring's localcontainerentitymanager and inject pretty
much everything through spring.   configuration/datasource etc... 
Openjpa Configuration: 
<entry key="openjpa.jdbc.DBDictionary"
value="org.apache.openjpa.jdbc.sql.ExtendedSybaseDictionary(schemaCase=preserve,createIdentityColumn=false,setStringRightTruncationOn=false)"
/>
<entry key="openjpa.DataCache" value="true(EvictionSchedule='30 22 * *
1')"/> 
<entry key="openjpa.QueryCache" value="CacheSize=1000,
SoftReferenceSize=100"/>
<entrykey="openjpa.RemoteCommitProvider" value="sjvm"/>
<entry key="openjpa.jdbc.TransactionIsolation"
value="read-uncommitted"/> 
<entry key="openjpa.InverseManager" value="true"/> 
<entry key="openjpa.jdbc.SchemaFactory"
value="native(ForeignKeys=true)"/>   


Sample Code below:

package edu.columbia.rascal.domain;

import org.apache.commons.lang.builder.ToStringBuilder;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;


/**
 * Question entity.
 *
 * @author   $author$
 * @version  $Revision$, $Date$
 */
@Entity @Table(
    name = "Question",
    uniqueConstraints =
        @UniqueConstraint(columnNames = { "questionNumber",
"ProtocolHeaderPer_oid" })
)
@TableGenerator(
    name = "generateQuestionPrimaryKey",
    table = "OBJECT_NUMERATORS",
    pkColumnName = "ObjectName",
    valueColumnName = "LastId",
    pkColumnValue = "Question"
)
public class Question implements java.io.Serializable {

    //~ Static fields/initializers
-----------------------------------------------------------------

    /** Use serialVersionUID for interoperability. */
    private static final long serialVersionUID = -8831312774834280328L;

    //~ Instance fields
----------------------------------------------------------------------------

    private String answerRequired;
    private String answerText;
    private ProtocolHeader ProtocolHeader;
    private Date meetingDate;

    // Fields

    private Long oid;
    private String questionNumber;

    //~ Constructors
-------------------------------------------------------------------------------

    /** Constructors * default constructor. */
    public Question() { }

    /**
     * minimal constructor.
     *
     * @param  oid                  TODO: DOCUMENT ME!
     * @param  protocolHeader  TODO: DOCUMENT ME!
     */
    public Question(Long oid, ProtocolHeader protocolHeader) {
        this.oid = oid;
        this.ProtocolHeader = ProtocolHeader;
    }

    /**
     * full constructor.
     *
     * @param  oid                  TODO: DOCUMENT ME!
     * @param  ProtocolHeader  TODO: DOCUMENT ME!
     * @param  answerRequired       TODO: DOCUMENT ME!
     * @param  answerText           TODO: DOCUMENT ME!
     * @param  questionNumber       TODO: DOCUMENT ME!
     * @param  meetingDate          TODO: DOCUMENT ME!
     */
    public Question(Long oid, ProtocolHeader ProtocolHeader, String
answerRequired,
        String answerText, String questionNumber, Date meetingDate
        ) {
        this.oid = oid;
        this.ProtocolHeader = ProtocolHeader;
        this.answerRequired = answerRequired;
        this.answerText = answerText;
        this.questionNumber = questionNumber;
        this.meetingDate = meetingDate;
    }

    //~ Methods
------------------------------------------------------------------------------------

    /**
     * TODO: DOCUMENT ME!
     *
     * @return  TODO: DOCUMENT ME!
     */
    @Column(
        insertable = true,
        updatable = true,
        name = "answerRequired",
        length = 1
    )
    public String getAnswerRequired() {
        return this.answerRequired;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @return  TODO: DOCUMENT ME!
     */
    @Column(
        insertable = true,
        updatable = true,
        name = "answerText"
    )
    public String getAnswerText() {
        return this.answerText;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @return  TODO: DOCUMENT ME!
     */
    @JoinColumn(
        name = "ProtocolHeaderPer_oid",
        nullable = false
    )
    @ManyToOne(fetch = FetchType.LAZY)
    public ProtocolHeader getProtocolHeader() {
        return this.ProtocolHeader;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @return  TODO: DOCUMENT ME!
     */
    @Column(
        insertable = true,
        updatable = true,
        name = "meetingDate",
        length = 23
    )
    @Temporal(TemporalType.TIMESTAMP)
    public Date getMeetingDate() {
        return this.meetingDate;
    }

    /**
     * Property accessors.
     *
     * @return  TODO: DOCUMENT ME!
     */
    @Column(
        insertable = true,
        updatable = true,
        name = "oid",
        unique = true,
        nullable = false,
        precision = 26,
        scale = 0
    )
    @GeneratedValue(
        strategy = GenerationType.TABLE,
        generator = "generateQuestionPrimaryKey"
    )
    @Id public Long getOid() {
        return this.oid;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @return  TODO: DOCUMENT ME!
     */
    @Column(
        insertable = true,
        updatable = true,
        name = "questionNumber",
        length = 4
    )
    public String getQuestionNumber() {
        return this.questionNumber;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  answerRequired  TODO: DOCUMENT ME!
     */
    public void setAnswerRequired(String answerRequired) {
        this.answerRequired = answerRequired;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  answerText  TODO: DOCUMENT ME!
     */
    public void setAnswerText(String answerText) {
        this.answerText = answerText;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  ProtocolHeader  TODO: DOCUMENT ME!
     */
    public void setProtocolHeader(ProtocolHeader ProtocolHeader) {
        this.ProtocolHeader = ProtocolHeader;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  meetingDate  TODO: DOCUMENT ME!
     */
    public void setMeetingDate(Date meetingDate) {
        this.meetingDate = meetingDate;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  oid  TODO: DOCUMENT ME!
     */
    public void setOid(Long oid) {
        this.oid = oid;
    }

    /**
     * TODO: DOCUMENT ME!
     *
     * @param  questionNumber  TODO: DOCUMENT ME!
     */
    public void setQuestionNumber(String questionNumber) {
        this.questionNumber = questionNumber;
    }

    /** @see  java.lang.Object#toString() */
    @Override public String toString() {
        return new ToStringBuilder(this).append("oid", oid).append(
                "answerRequired", answerRequired
                ).append("answerText",
answerText).append("questionNumber",
                questionNumber
                ).append("meetingDate", meetingDate).toString();
    }

}




______________________________________________
StackTrace:
Caused by:
<openjpa-1.2.1-r752877:753278 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException: Attempt to insert
duplicate key row in object 'Question' wit
h unique index 'Question_18534058221'
 {prepstmnt 1238649300 INSERT INTO dbo.Question (oid, answerRequired,
answerText, questionNumber, ProtocolHeaderPer_oid, meetingDate) VALUES
(?, ?, ?, ?, ?, ?) [p
arams=(long) 18444, (String) Y, (String) q1, (String) q1, (long) 17739,
(null) null]} [code=2601, state=23000]
FailedObject: edu.columbia.rascal.domain.Question@689d689d
        at
org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4232)
        at
org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4197)
        at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
        at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:72)
        at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:131)
        at
org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:82)
        at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:89)
        at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:72)
        at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:543)
        at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:105)
        at
org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
        at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:89)
        at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:72)
        at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:717)
        at
org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
        at
org.apache.openjpa.datacache.DataCacheStoreManager.flush(DataCacheStoreManager.java:562)
        at
org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
        ... 54 more
Caused by:
org.apache.openjpa.lib.jdbc.ReportingSQLException: Attempt to insert
duplicate key row in object 'Question' with unique index
'Quest_18534058221'
 {prepstmnt 1238649300 INSERT INTO dbo.Question (oid, answerRequired,
answerText, questionNumber, ProtocolHeaderPer_oid, meetingDate) VALUES
(?, ?, ?, ?, ?, ?) [p
arams=(long) 18444, (String) Y, (String) q1, (String) q1, (long) 17739,
(null) null]} [code=2601, state=23000]
        at
org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:192)
        at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.access
$700(LoggingConnectionDecorator.java:57)
        at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator
$LoggingConnection
$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:866)
        at
org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:269)
        at org.apache.openjpa.jdbc.kernel.JDBCStoreManager
$CancelPreparedStatement.executeUpdate(JDBCStoreManager.java:1586)
        at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.executeUpdate(PreparedStatementManagerImpl.java:151)
        at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:120)
        ... 66 more