Thilina Sandaruwan
Thilina Sandaruwan

Reputation: 337

java.sql.SQLIntegrityConstraintViolationException Doesn't reach catch clause

I'm working with a JAVAEE application which is using hibernate ORM. In that application i made an api endpoint to delete an entity. That entity has foreign key constraint. Then entity should not delete and throws an exception. I wrote a code to return error when reach the catch clause. But the question is when i hit the endpoint it throes the exception. But it doesn't reach the catch clause. it return success state. How I resolve this?

rest/InsuranceProviderAPI.java

@Stateless
@Path("/v1/insuranceProviderAPI")
public class InsuranceProviderAPI {
    @EJB
    GenericCrudDAOIF genericCrudDAO;
    
        @DELETE
    @Path("/providers/{id:[0-9][0-9]*}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response delete(@PathParam("id") Integer id, @Context UriInfo uriInfo) {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> returnObject = new HashMap<>();
        Map<String, Object> parameters = new HashMap<>();
        InsuranceProvider provider;

        try {
            parameters.put("id", id);
            provider = (InsuranceProvider) genericCrudDAO
                    .createSingleResultQuery("SELECT i FROM InsuranceProvider i WHERE i.id=:id", parameters, 0, 1);
            provider.setActive(false);
            provider = genericCrudDAO.update(provider);
            OperationLogAPI.log(uriInfo.getQueryParameters().getFirst("i"), uriInfo.getQueryParameters().getFirst("n"), "delete", provider, genericCrudDAO);
            returnObject.put("status", "Success");
            return Response.status(Response.Status.OK).entity(objectMapper.writeValueAsString(returnObject)).build();
        } catch (Exception e) {
            Utility.printStackTrace(e);
        }
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Unexpected Error. Please contact support")
                .build();
    }
}

entity/InsuranceProvider.java

@Entity
@Table(name="insurance_provider")
@JsonIgnoreProperties(ignoreUnknown = true)
public class InsuranceProvider implements java.io.Serializable{

    private Integer id;
    private String name;
    private Boolean active;
    private InsuranceProviderType insuranceProviderType;
    private String fieldNameMapping;

    public InsuranceProvider() {
    }

    public InsuranceProvider(Integer id, String name, Boolean active, InsuranceProviderType insuranceProviderType) {
        this.id = id;
        this.name = name;
        this.active = active;
        this.insuranceProviderType = insuranceProviderType;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "active")
    public Boolean getActive() {
        return active;
    }

    public void setActive(Boolean active) {
        this.active = active;
    }

    @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "insurance_provider_type_id")
    public InsuranceProviderType getInsuranceProviderType() {
        return insuranceProviderType;
    }

    public void setInsuranceProviderType(InsuranceProviderType insuranceProviderType) {
        this.insuranceProviderType = insuranceProviderType;
    }

    @Column(name = "field_name_mapping")
    public String getFieldNameMapping() {
        return fieldNameMapping;
    }

    public void setFieldNameMapping(String fieldNameMapping) {
        this.fieldNameMapping = fieldNameMapping;
    }
}

common/DataAccessException

public class DataAccessException extends Exception {

    public static final int CONCURRENT_MODIFICATION = 1;

    private String id = null;

    private int rootState = 0;

    public DataAccessException() {
        super();
    }
    
    
    public DataAccessException(String id, String message) {
        super(message);
        this.id = id;
    }
    
    public DataAccessException(String id, String message, Throwable rootCause) {
        super(message + " Root Cause: " + rootCause.getMessage());
        this.id = id;
    }

    public DataAccessException(String id, String message, Throwable rootCause,
            int rootState) {
        this(id, message, rootCause);
        this.rootState = rootState;
        this.id = id;
    }
    
    public int getRootState() {
        return rootState;
    }
    
    public String getId() {
        return id;
    }
}

common/GenericCrudDAOIF.java

public interface GenericCrudDAOIF {
    
    void delete(Object t, Object id) throws DataAccessException;
    
    public EntityManager getEntityManager();
}

common/GenericCrudDAOImpl.java

@Stateless
@Local(GenericCrudDAOIF.class)
public class GenericCrudDAOImpl implements GenericCrudDAOIF {

    private static final Logger logger = (Logger) LoggerFactory.getLogger(GenericCrudDAOImpl.class);

    @PersistenceContext(unitName = "SwissCRMDS")

    public EntityManager em;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void delete(Object t, Object id) throws DataAccessException {
        if (logger.isDebugEnabled()) {
            logger.debug("in method delete [" + t + "]");
        }
        Object ref = this.em.getReference(t.getClass(), id);
        this.em.remove(ref);
    }

    public EntityManager getEntityManager() {
        return em;
        
    }

}

Here is the error shows in the terminal

20:45:16,581 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-1) SQL Error: 1451, SQLState: 23000
20:45:16,581 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-1) Cannot delete or update a parent row: a foreign key constraint fails (`crm`.`product`, CONSTRAINT `fk_product_category` FOREIGN KEY (`insurance_category_id`) REFERENCES `insurance_category` (`id`))
20:45:16,582 INFO  [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (default task-1) HHH000010: On release of batch it still contained JDBC statements
20:45:16,585 ERROR [org.jboss.as.ejb3.invocation] (default task-1) WFLYEJB0034: EJB Invocation failed on component GenericCrudDAOImpl for method public abstract java.lang.Object com.swiss.crm.common.GenericCrudDAOIF.create(java.lang.Object) throws com.swiss.crm.common.DataAccessException: javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.ConstraintViolationException: could not execute statement
        at [email protected]//org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:217)
        at [email protected]//org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:390)
        at [email protected]//org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:158)

...
...
...
Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`crm`.`product`, CONSTRAINT `fk_product_category` FOREIGN KEY (`insurance_category_id`) REFERENCES `insurance_category` (`id`))
        at [email protected]//com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
        at [email protected]//org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
        at [email protected]//org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)

Upvotes: 0

Views: 297

Answers (1)

Christian Beikov
Christian Beikov

Reputation: 16420

Add em.flush(); to force Hibernate to actually flush pending operations to the database.

Upvotes: 1

Related Questions