Please find below the issue I have encountered during the migration from hibernate 5 to hibernante 6.1.7.
My sample project is using Lombok / Spring Data; its datamodel is composed of :
* Buckets having Lines {noformat}@Getter @Setter @Entity @Table(name = "BUCKET") @SequenceGenerator(name = "SEQ_BUCKET_ID", allocationSize = 10, sequenceName = "SEQ_BUCKET_ID") @IdClass(PkBucket.class) public class Bucket {
@Id @Column(name = "ID") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_BUCKET_ID") private Long id;
@OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "BUCKET_ID", referencedColumnName = "id", nullable = false) private List<Line> lines = new ArrayList<>(); }{noformat} * Items having Lines {noformat}@Getter @Setter @Entity @Table(name = "LINE") @SequenceGenerator(name = "SEQ_LINE_ID", allocationSize = 10, sequenceName = "SEQ_LINE_ID") @IdClass(PkLine.class) public class Line {
@Id @Column(name = "ID") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_LINE_ID") private Long id;
@ManyToOne(targetEntity = Item.class) @JoinColumn(name = "ITEM_ID", referencedColumnName = "id", nullable = false) private Item item; }{noformat} * The Line class {noformat}@Getter @Setter @Entity @Table(name = "ITEM") @SequenceGenerator(name = "SEQ_ITEM_ID", allocationSize = 10, sequenceName = "SEQ_ITEM_ID") @IdClass(PkItem.class) public class Item {
@Id @Column(name = "ID") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ITEM_ID") private Long id;
@OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true) private List<Line> lines = new ArrayList<>(); }{noformat} * The simplified Pk classes - they are all identical, as PkBucket here below {noformat}@Getter @Setter public class PkBucket implements Serializable { private Long id;
public PkBucket withId(Long id) { this.id = id; return this; } }{noformat}
My test is creating and updating some data :
{noformat} @Test @Transactional public void buckets_items_lines() { // create some data Session session = entityManager.unwrap(Session.class); session.createNativeQuery("insert into ITEM (id) values (100)").executeUpdate(); session.createNativeQuery("insert into ITEM (id) values (101)").executeUpdate(); session.createNativeQuery("insert into BUCKET (id) values (200)").executeUpdate(); session.createNativeQuery("insert into LINE (id, ITEM_ID, BUCKET_ID) values (300, 100, 200)").executeUpdate();
// move line from item to other item Item item100 = itemRepository.findById(new PkItem().withId(100L)).get(); final Item item101 = itemRepository.findById(new PkItem().withId(101L)).get(); item100.getLines().forEach(line -> line.setItem(item101)); }{noformat}
The issue below occurs when tying to hydrate Item.lines:
{noformat}Could not set value of type [java.lang.Long] : `com.example.demo.domain.issue2.PkBucket.id` (setter) org.hibernate.PropertyAccessException: Could not set value of type [java.lang.Long] : `com.example.demo.domain.issue2.PkBucket.id` (setter) at app//org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:81) at app//org.hibernate.metamodel.mapping.internal.AbstractEmbeddableMapping.setValues(AbstractEmbeddableMapping.java:103){noformat}
Few remarks:
* As you can see in the stack attached, the Line property id is accessed through PkBucket id instead of PkLine id. * If I remove {{nullable = false}} from Bucket lines JoinColums the result is OK * It I change the mapping to add and use a ManyToOne relationship in Line class to Bucket entity the result is also OK * If I use unique Pk class the issue persists : IllegalArgumentException: Can not set java.lang.Long field [com.example.demo.domain.issue2.Pk.id|http://com.example.demo.domain.issue2.Pk.id] to com.example.demo.domain.issue2.Line * If I force the Line class to extend the expected id class the result is OK but this is not nice 🙂 {noformat}... @IdClass(PkLine.class) public class Line extends PkBucket { ...{noformat}
I have attached the full log; if needed, I can also share my sample project. |
|