0
@Embeddable
class Y {
    protected Y(){}
    @Column(nullable = false)
    int i;
    @Column(nullable = false)
    int j;
}
@Entity
class X {
    protected X(){}
    @Id
    @Column(name = "id")
    int id;

    @ElementCollection(fetch = FetchType.EAGER)
    Set<Y> s = new HashSet<>();
}

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
X a = new X();
a.s.add(new Y());

session.save(a);
transaction.commit();
session.close();

Hibernate map the table x_s contain 3 column which is id of x, i and j. However, if make a detached object to persisted again by update like:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
X x = session.get(X.class, 0);
transaction.commit();
session.close();

Session session1 = sessionFactory.openSession();
Transaction transaction1 = session1.beginTransaction();
session1.saveOrUpdate(x); // and select or update should execute
transaction1.commit();
session1.close();

The strange thing is, except the select, hibernate will do delete and insert, the above code will generate:

Hibernate: select x0_.id as id1_0_0_, s1_.X_id as X_id1_1_1_, s1_.s_i as s_i2_1_1_, s1_.s_j as s_j3_1_1_ from X x0_ left outer join X_s s1_ on x0_.id=s1_.X_id where x0_.id=?
Hibernate: delete from X_s where X_id=? and s_i=? and s_j=?
Hibernate: insert into X_s (X_id, s_i, s_j) values (?, ?, ?)
Hibernate: select x_.id from X x_ where x_.id=?
Hibernate: delete from X_s where X_id=? and s_i=? and s_j=?
Hibernate: insert into X_s (X_id, s_i, s_j) values (?, ?, ?)

According to this answer, it says the reason is table x_s has no pk. But the table x_s generated by hibernate use all 3 column as a combined pk already.

It seems the only way to eliminate those insert and delete commands is change Set<Y> to List<Y>, hibernate will automatically add a column order and combine order and x_id as pk. But from db schema view, it is no material difference

P.S I use hibernate 5.3

Mikhail Kholodkov
  • 23,642
  • 17
  • 61
  • 78
jean
  • 2,825
  • 2
  • 35
  • 72

1 Answers1

0

Clearly the JPA sees that the objects are not equal are clears and re-inserts. Please try overriding the equals() and hashcode() for the Embeddable object. With default implementation, object is considered equal by reference alone, which would have not been in your case.

Karthik R
  • 5,523
  • 2
  • 18
  • 30