Home > front end >  How to continue processing after a constraint violation exception?
How to continue processing after a constraint violation exception?

Time:08-19

We have a Kafka consumer in a Java - Spring Boot service that has multiple instances in multiple clusters (all with same consumer group id). The consumer saves data to the database (SQL Server).

The code checks if a record exists in the ItemSet table before saving to the database. The actual data in the payload gets saved in a child table ItemValue and not the parent, ItemSet. The relational data table hierarchy is one to many in this order ItemSet -> ItemName -> ItemValue. ItemSet table has a unique constraint for department id, season combination to prevent multiple duplicate adds.

I need to do some processing after catching this exception to ensure that the incoming data still gets saved under the existing ItemSet and doesn't get lost. I am using Spring Data JPA and as soon as I catch the exception and try to retrieve the existing record I end up getting:

org.hibernate.AssertionFailure: null id in ItemSet entry (don't flush the Session after an exception occurs).

The getItemSet() in the catch block blows up.

What is the best way to overcome these race conditions?

ItemSet savedItemSet = null;
try
{
    String seasonName = itemSet.getSeasonName();
    Long seasonYear = itemSet.getSeasonYear();
    Long departmentId = itemSet.getDepartment().getId();
    List<ItemSet> itemSets = attributeSetRepository.findBySeasonNameAndSeasonYearAndDepartmentId(
            seasonName, seasonYear, departmentId);
    LOGGER.info("Found {} item sets corresponding to season name : {}, season year : {}, "
              "department id : {}", itemSets.size(), seasonName, seasonYear, departmentId);
    if(CollectionUtils.isEmpty(itemSets)) {
        savedItemSet = itemSetRepository.save(itemSet);
    }
    else {
        return new CreatedItemSet(itemSets.get(0).getId());
    }
}
catch(PersistenceException | DataIntegrityViolationException e) 
{
    LOGGER.error("An exception occurred while saving itemSet set", e);

    if (e.getCause() instanceof ConstraintViolationException) 
    {
        String seasonName = itemSet.getSeasonName();
        Long seasonYear = itemSet.getSeasonYear();
        Long deptId = itemSet.getDepartment().getId();
        LOGGER.info("A duplicate item set found in the database corresponding "
                  "to season name : {}, season year : {} and department : {}",
                seasonName, seasonYear, deptId);
        
        ExistingItemSet existingItemSet = getItemSet(seasonName, 
                seasonYear, deptId);
        if(existingItemSet == null) {
            LOGGER.info("No item set found");
            return null;
        }
        return new CreatedItemSet(existingItemSet.getId());
    }
}

CodePudding user response:

You can't "continue". A transaction is marked for rollback and the persistence context is unusable after a constraint violation happens.

You can either try to avoid the constraint violation, by checking if the DB contains an entry before persisting/updating, or you run the rest of your code in a separate transaction if a constraint violation happens.

  • Related