[JIRA] (HHH-16215) Composite primary key @IdClass attribute mapping is borrowed from the first OneToMany backref and cannot be set
by Alina Ricciuti (JIRA)
Alina Ricciuti ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=61fb92a... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiODkwYjVjYzRk... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16215?atlOrigin=eyJpIjoiODkwYj... ) HHH-16215 ( https://hibernate.atlassian.net/browse/HHH-16215?atlOrigin=eyJpIjoiODkwYj... ) Composite primary key @IdClass attribute mapping is borrowed from the first OneToMany backref and cannot be set ( https://hibernate.atlassian.net/browse/HHH-16215?atlOrigin=eyJpIjoiODkwYj... )
Change By: Alina Ricciuti ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=61fb92a... )
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.
( https://hibernate.atlassian.net/browse/HHH-16215#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16215#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100216- sha1:64a4cf6 )
1 year, 10 months