Reputation: 337
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
Reputation: 16420
Add em.flush();
to force Hibernate to actually flush pending operations to the database.
Upvotes: 1