moretti.fabio
moretti.fabio

Reputation: 1138

JPA does not delete database row

I'm facing a delete problem with JPA, and this is my code:

public deleteLine(int idLine) {
  Line line = em.find(Line.class,idLine);
  Header header = line.getHeader();
  this.deleteLine(header,line);
}

public boolean deleteLine(Header header, Line line) {
    try {
      line.setIdArticle(null);
      line.setDetail(DELETED_TAG);
      line.setQuantity(0.0f);
      em.merge(line);
      header.getLineCollection().remove(line);
      em.remove(line);
      em.flush();
    }
    catch (Exception ex) {
      LOG.log(Level.SEVERE, null, ex);
    }
  return true;
}

When I call deleteLine(), I end with a database row with idArticle being null, details equal to DELETED_TAG constant and quantity equal to 0. But the row is still there, despite the em.remove.

I've tried to add a line.setHeader(null) before the removal, but I get a ConstraintViolationException because the header field cannot be null.

Obviously I'm doing something wrong, but I cannot figure out what.

There's entities code:

public class Header implements Serializable {
  [...]
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "header")
  private Collection<Line> lineCollection;
  [...]
}

public class Line implements Serializable {
  [...]
  @JoinColumn(name = "header", referencedColumnName = "header")
  @ManyToOne(optional = false)
  private Header header;
  [...]
}

I've done tests deleting the row via JPQL (DELETE FROM Linea WHERE idLinea=?), and it effectively deletes the row. But then, when JPA does the commit, the line reappears due to an INSERT done by JPA.

Is there a way to discover why? Obviously, there's an entity that generates the insert, but I'm removing the line form the header, so what can I do to figure out what is triggering the insert?

Upvotes: 4

Views: 1942

Answers (1)

moretti.fabio
moretti.fabio

Reputation: 1138

I figured out where the problem was: when the user deletes a row, I was doing this

  • call deleteLine
  • do some calculations and update the header with the results

Due to how jpa works, the modifications to the header fields force jpa to skip deleting the child (because of the cascade all) or reinserting it, because in fact, the entity still exists and hibernate "walks" and reconstructs the parent-childs tree.

For people facing the same problem, the correct way I've found if you want to delete a child and update the parent after the deletion is:

  • remove the child from the parent collection
  • update the header
  • delete the child

For me, doing thing in this exact order solved the problem.

Upvotes: 3

Related Questions