Dear board users,
I have an entity model that uses the @UniqueConstraint annotation to define restrictions on the persisted data. Now I am running into the problem that I have to manipulate data to have one of these constraints satisfied. But its hard to explain just with words so I will give you a code snippet:
1. Reader entity
Code:
@Table(name = "Reader", uniqueConstraints = @UniqueConstraint(columnNames = { Reader.PROPERTY_BUS_ADDRESS, Reader.PROPERTY_HARDWARE_INTERFACE }))
@Audited
public class Reader extends AuthComponent
{
   public static final String PROPERTY_HARDWARE_INTERFACE = "hardwareInterface";
   public static final String PROPERTY_BUS_ADDRESS = "busAddress";
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = PROPERTY_HARDWARE_INTERFACE, nullable = false)
   private HardwareInterface hardwareInterface;
   @Column(name = PROPERTY_BUS_ADDRESS, nullable = false)
   @Range(min = -1, max = 3)
   private Integer busAddress = 0;
   // Getters, setters and some more properties
}
As you can see this entity has a relation to another one called HardwareInterface and a plain integer called busAddress. Besides that there is a unique constraint one these two columns.
Now I have a constellation that I have four of those 'readers' with busAddresses 0, 1, 2, 3. The user changes the busAddress of one of these four to a value that is already assigned to another one. So this would result in a unique constraint violation. Now I thought of first assigning a dummy address (-1) to the conflicting entity, setting the desired value and then setting the conflicting entity's address to the original one.
Example:
Code:
READER
id    hardwareInterface    busAddress
1     1                    0
2     1                    1
3     1                    2
4     1                    3
Exchange addresses of reader 3 and 4:
1. Reader [id=3].busAddress = -1 => session.saveOrUpdate()
2. Reader [id=4].busAddress =  2 => session.saveOrUpdate()
3. Reader [id=3].busAddress =  3 => session.saveOrUpdate()
All this happens within the same transaction. For some reason hibernate first issues the update for the reader [id=4] although it is the second update caused in the code sequence below:
Code:
protected void resolveAddressConflict() throws NestedException
   {
      Reader conflicting = readerService.findByInterfaceAddress(reader);
      if (conflicting != null)
      {
         final int dummyAddress = -1;
         Reader currentOldState = readerService.auditFindByIdVersion(reader.getId(), reader.getVersion());
         if (currentOldState != null)
         {
            conflicting.setBusAddress(dummyAddress);
            readerService.save(conflicting);
            readerService.save(reader);
            conflicting.setBusAddress(currentOldState.getBusAddress());
            readerService.save(conflicting);
            addGuiMessage("autoResolvedAddressConflict", conflicting.getName(), conflicting.getBusAddress());
         }
         else
         {
            addGuiError("errorResolvedAddressConflict", conflicting.getName());
         }
      }
   }
This results in the exception: 
Quote:
com.microsoft.sqlserver.jdbc.SQLServerException: Violation of UNIQUE KEY constraint 'UQ__Reader__4394C9994BCC3ABA'. Cannot insert duplicate key in object 'dbo.Reader'.
Which is quite logical.
Can anyone assist?
Greets Sebastian