dinsdag 28 mei 2013

ADF BC: JBO-25014: Another user has changed the row with primary key

Challenge

You receive the error mentioned in the title, but you are quite sure this is not the case and nothing has changed in the database due to triggers or pl/sql-code.

Context

Jdeveloper: 11gR1

Solution

There are already quite a few blogs on this error within ADF.  They all talk about the fact that something has changed in the database, without BC knowing about it.  This can be done through another user, a batch-script, a trigger or any other pl/sql-code.
But what if you are 100% sure this is not the case, then read on.

There is also another reason why this happen: the comparison of the different attributes didn't go well.  Although the documentation clearly state that the oracle.jbo.domain-classes should solve this issue, we still have found ourselves multiple times in this situation and mostly due to Date-attributes.
There are 2 ways to handle this:
  1. You can identify an attribute in your entity as a “Change Indicator”.  Once you have identified such an attribute in your entity, the BC-code will no longer compare all attributes, instead it will only compare those with the “Change Indicator” activated.

    To set this indicator on an attribute, just open the editor of the attribute to see the “Change Indicator” property.
  2. You can remove the attribute that is causing the problem from the comparison.  This is easier said than done, because you need to know which attribute is causing the problem.

    To find this out, just activate the JBO-diagnostic logging, you can do this by adding the following “-Djbo.debugoutput=console” to the Java-options of your run-configuration.
    Now run the application again and simulate the problem.  You should find something like this:
    <EntityImpl><compare> [508] Entity compare failed for attribute HireDate
    <EntityImpl><compare> [509] Original value :19-06-1987
    <EntityImpl><compare> [510] Target value :19-06-1987
    
    Now you know it is the HireDate-Attribute.  Now add the following code to the Impl-class of your entity:
    @Override
    protected boolean compare(SparseArray sparseArray) {
       // Removing the HIREDATE attribute from the array
       if (sparseArray != null && !sparseArray.isEmpty()) {
           for (int i=0; i<sparseArray.length(); i++) {
               Object value = sparseArray.get(i);
               if (value != null) {
                   if (i == HIREDATE) sparseArray.clear(i);
               }
           }
       }
       // Calling the standard compare method
       return super.compare(sparseArray);
    }
    
    You can do this for as many attributes as you need, just add them to the 3th if-statement.

Geen opmerkingen:

Een reactie plaatsen