I have a JPA project connected to a MySQL database where my entity object is mapped to a table with a constraint on 2 columns. That is:
@Entity
@Table(name = "my_entity")
class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@Column(name = "myField1")
private String myField1;
@Basic(optional = false)
@Column(name = "myField2")
private int myField2;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "myEntity")
private Set<OtherEntity> otherEntitySet;
}
In the database, the my_entity table has a unique constraint on (myField1, myField2). The issue is that if I remove an existing entity with EntityManager.remove(entity) and then add a new one with EntityManager.persist(entity), the database throws an error about a duplicate row.
For example:
entityManager.getTransaction().begin();
MyEntity entity1 = new MyEntity();
entity1.setMyField1("Foo");
entity1.setMyField2(500);
entityManager.persist(entity1);
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
entityManager.remove(entity1);
MyEntity entity2 = new MyEntity();
entity2.setMyField1("Foo");
entity2.setMyField2(500);
entityManager.persist(entity2);
entityManager.getTransaction().commit();
This gives me a MySQLIntegrityConstraintViolationException complaining about this being a duplicate entry. I imagine it's because it's trying to add the new entry before removing the old one. Is there any way to maintain that order? Or, is there a way to use JPA to prevent this situation? It's not exactly a common use case, but I'm concerned about a user who tries to delete an entity to get rid of all the associated data and start over, and then recreates the easier fields, then finding that the data was never removed.
The hashCode and equals implementations are as follows:
public int hashCode() {
int hash = 0;
hash += (getMyField1().hashCode() + getMyField2());
return hash;
}
public boolean equals(Object object) {
if (!(object instanceof MyEntity)) {
return false;
}
MyEntity other = (MyEntity) other;
return (getMyField2() == other.getMyField2()) &&
(getMyField1().equals(other.getMyField1()));
}