EntityExistsException on merge of new entity

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

EntityExistsException on merge of new entity

atomic_mass
We are experiencing an intermittent error on one of our Java 7 services. The error occurs when we merge a new entity to the persistence context. The exception we get is an org.apache.openjpa.persistence.EntityExistsException. The entity is defined with an ID which is generated by the database (GenerationType.IDENTITY), and the value of the ID is null at the point the merge function is called. Directly after the merge we execute the flush function in order to have the ID generated on the DB and returned to the object as we require it afterwards. This works without a problem most of the time, however on certain occasions OpenJPA tries to insert an explicit value for the ID column and causes an error on the database.
The entity called Fund and inherits from a mapped superclass called AbstractFund:

@MappedSuperclass
public abstract class AbstractFund implements Serializable
{
//fields relating to all funds
}
@Entity
public class Fund extends AbstractFund implements Serializable
{

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "fundId")
  protected Long id;
   // other fund related fields
}

The code that calls the merge method is placed in a stateless localbean EJB. Which calls the entity manager merge method, followed by the flush method:
public class FundDao
{
    @PersistenceContext(name = "puOpenJPA_Core", type = PersistenceContextType.TRANSACTION)
    private EntityManager dao;

  public Fund save(Fund fund)
  {
   
      fund = dao.merge(fund);
      dao.flush();

      return fund;
    }
}

We have debugged the code and up to the point that the merge method is called the fund object has a null ID. This flow works fine, however after a certain amount of time the flush statement starts to throw this exception:

Caused by: <openjpa-2.3.0-r422266:1540826 fatal store error> org.apache.openjpa.persistence.EntityExistsException: Cannot insert explicit value for identity column in table 'Fund' when IDENTITY_INSERT is set to OFF. {prepstmnt 544738977 INSERT INTO Fund (fundId, accrueInterestDaily, advisoryFeesAllowed, advisoryFeesPercentage, afrikaansNameClass, allowAutomaticReinvestment, allowCertificationOfUnits, asisaMandateSubmitted, auditFees, auditStatus, authorised, automaticAuthorise, backDateTransaction, benchmark, capped, cappedFundAmount, cappedFundUnits, certificateTax, cgtBaseCost, clawback, clawbackPeriodMonths, commissionTax, compliance, createBy, createDate, cutOffTime, defaultClass, deviationPercentage, dwtExemptionsForm, effectiveDate, endDate, externalReference, financialYearEnd, firstDistributionDate, firstIncomeDistributiondate, fundCode, fundFactSheet, fundGroupFamily, fundName, fundNumber, fundShortId, fundStatus, hasSeriesAccounting, incomeDistributionActive, initialFeesBroker, initialFeesDistribution, initialFeesDistributionChannel, initialFeesManco, initialFeesMancoExDif, initialFeesTotal, integrationId, interfaceIndicator, investmentManager, isLeadSeries, isinCode, jseCode, lastIncomeDistributionDate, lastIncomePaymentDate, launchDate, maxLumpSumInvestment, maxScorePercentage, mergeDate, mergeIndicator, merged, minLumpSumInvestment, minMonthlyInvestment, nextIncomeDistributionDate, nonPermissableIncomeApplied, offsetInitialFeeOnSwitches, overrideProcessDate, processOnNonWorkingDays, processOnPublicHolidays, rebateContract, rebatePercentage, regulation28, ringFenceDate, ringFenceIndicator, ringFenced, scriptAccountNumber, sedolNumber, seriesMonth, serviceFeesAssetManager, serviceFeesBroker, serviceFeesDistribution, serviceFeesManco, shortName, sourceInDetailId, sourceUUID, stampDuty, startingPrice, taxReferenceNumber, totalServiceFees, unexorAccountNumber, updateBy, valueDateProcessing, assetAllocationId, assetSegmentationId, benchmarkCategoryId, categoryId, countryId, curoPricingId, currencyId, fsbStatusId, fundAccountGroupId, fundBankPurposeTypeId, fundClassId, companyId, fundTypeId, incomeDistributionFrequencyId, investmentOptionId, leadFundId, mancoId, mergedFundId, mergedSourceFundId, portfolioBankAccountId, pricingHouseId, pricingModeId, pricingTimeId, pricingTypeId, productOwnerId, ringFenceSourceFundId, ringFenceTargetFundId, riskManagerId, segregatedMandateId, trusteeId, adminFeeSetupId, performanceFeeSetupId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)} [code=544, state=23000]
FailedObject: za.co.sci.core.entities.Fund@6c754a0d
                at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4959) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4934) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:134) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:76) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:144) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:357) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flushGraph(ConstraintUpdateManager.java:349) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:97) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:732) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.datacache.DataCacheStoreManager.flush(DataCacheStoreManager.java:661) [openjpa-all-2.3.0.jar:2.3.0]
                at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131) [openjpa-all-2.3.0.jar:2.3.0]
                ... 197 more

This doesn’t happen all the time, but it does happen given the exact same input as a successful call.

What is causing OpenJPA to sometimes try and insert an explicit value for the fund ID and at other times allow the database to supply the value.

We have upgraded to OpenJPA 2.4.1 and are running on wildfly-8.1.0.Final. We connect to a SQL Server 2012 database.