[JIRA] (HHH-16363) OneToMany object properties not set when EmbeddedId and it holds an OneToOne relationship to itself
by Alina Ricciuti (JIRA)
Alina Ricciuti ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=61fb92a... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMDBmMzA2ODQx... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16363?atlOrigin=eyJpIjoiMDBmMz... ) HHH-16363 ( https://hibernate.atlassian.net/browse/HHH-16363?atlOrigin=eyJpIjoiMDBmMz... ) OneToMany object properties not set when EmbeddedId and it holds an OneToOne relationship to itself ( https://hibernate.atlassian.net/browse/HHH-16363?atlOrigin=eyJpIjoiMDBmMz... )
Issue Type: Bug Affects Versions: 6.2.0.CR4 Assignee: Unassigned Created: 23/Mar/2023 04:55 AM Environment: Hibernate: 6.2.0.CR4
Postgresql: 11
Spring Data JPA: 3.0.3
Spring Boot: 3.0.4
JDK: Oracle OpenJDK 17.0.2
OS: Windows 11 Priority: Major Reporter: Alina Ricciuti ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=61fb92a... )
I have a migration issue from hibernate 5.4.32 to hibernate 6: the properties of one of my entities are not properly set. Please find below a simplified model that reproduces this issue.
So, I have Elements and Tags, as presented in the attached diagram:
* Elements have Tags in a relationship ManyToOne , fetch EAGER
* Tags have composite identifiers
* Tag may have a OneToOne relationship “linkedTag”
My sample project is using Lombok / Spring Data :
* Element:
@Entity
@Getter
@Setter
public class Element {
@EmbeddedId
private PkComposite id;
@Column(name = "NAME")
private String name;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "ID_TAG")
private Tag tag;
}
* Tag:
@Entity
@Getter
@Setter
public class Tag {
@EmbeddedId
private PkComposite id;
private String name;
@OneToMany(mappedBy = "tag", fetch = FetchType.EAGER)
private List<Element> elements;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ID_TAG_LINKED")
private Tag linkedTag;
}
* The composite key:
@Getter
@Setter
public class PkComposite implements Serializable {
@Column(name = "ID")
private Long id;
public PkComposite withId(Long id) {
this.id = id;
return this;
}
}
* The test class:
@Test
@Transactional
public void issue3_name_not_filled() {
// create some data
Session session = entityManager.unwrap(Session.class);
session.createNativeQuery("insert into TAG (id, NAME) values (100, 'NAME for TAG 100')").executeUpdate();
session.createNativeQuery("insert into ELEMENT (id, NAME, ID_TAG) values (200, 'NAME for ELEMENT 200', 100)").executeUpdate();
// move line to other item
Element element200 = elementRepository.findById(new PkComposite().withId(200L)).orElse(null);
Assertions.assertNotNull(element200);
Assertions.assertNotNull(element200.getTag());
Assertions.assertNotNull(element200.getTag().getName(), "Tag name is null !");
}
The test fails since the name property is not set on Element’s Tag. None of tag’s properties is set, except for its identifier.
Few remarks:
* the issue is reproduced whether the Element identifier is composite or simple (may be Long as example)
* The OneToMany relationship to Element in Tag class may also be lazy - in my project it is actually LAZY with LazyCollection(LazyCollectionOption.FALSE)
* If I remove the “linkedTag” the issue in no longer reproduced
But if I set the “linkedTag“:
@Test
@Transactional
public void issue3_tag_not_properly_set() {
// create some data
Session session = entityManager.unwrap(Session.class);
session.createNativeQuery("insert into TAG (id, NAME) values (101, 'NAME for LINKED TAG 101')").executeUpdate();
session.createNativeQuery("insert into TAG (id, NAME, ID_TAG_LINKED) values (100, 'NAME for TAG 100', 101)").executeUpdate();
session.createNativeQuery("insert into ELEMENT (id, NAME, ID_TAG) values (200, 'NAME for ELEMENT 200', 100)").executeUpdate();
// move line to other item
Element element200 = elementRepository.findById(new PkComposite().withId(200L)).orElse(null);
Assertions.assertNotNull(element200);
Assertions.assertNotNull(element200.getTag());
Assertions.assertNotNull(element200.getTag().getId());
Assertions.assertEquals(100L, element200.getTag().getId().getId(), "Tag is not the good one !");
Assertions.assertEquals("NAME for TAG 100", element200.getTag().getName(), "Tag properties are not good !");
}
The Element’s Tag’s properties are set, but with wrong values, those of the linked Tag.
I have attached the tests logs and if needed, I can also share my sample project.
( https://hibernate.atlassian.net/browse/HHH-16363#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16363#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#100219- sha1:0c2c9f2 )
3 years
[JIRA] (HHH-16360) On Postgresql with hbm2ddl.auto=update, timestamp columns are updated even when correct
by ClementC (JIRA)
ClementC ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiYTdmMGMzYTE4... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16360?atlOrigin=eyJpIjoiYTdmMG... ) HHH-16360 ( https://hibernate.atlassian.net/browse/HHH-16360?atlOrigin=eyJpIjoiYTdmMG... ) On Postgresql with hbm2ddl.auto=update, timestamp columns are updated even when correct ( https://hibernate.atlassian.net/browse/HHH-16360?atlOrigin=eyJpIjoiYTdmMG... )
Issue Type: Bug Affects Versions: 6.2.0.CR4 Assignee: Unassigned Components: hibernate-jpamodelgen Created: 23/Mar/2023 03:52 AM Environment: Postgresql 14 Priority: Major Reporter: ClementC ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
With hbm2ddl.auto=update on Postgresql, columns for properties persisted as timestamps (like Instant, OffsetDateTime, LocalDateTime, …) are updated on every startup, even if the alter statement does not perform any actual change.
hbm2ddl.auto=validate does not detect any problem.
This did not happen on 6.1.7 (because it did not have the capability to update existing columns anyway).
*Sample*
My entity:
@Entity
@Getter
@Setter
public class Test {
@Id
private String id;
private Instant instant;
private OffsetDateTime offsetDateTime;
private ZonedDateTime zonedDateTime;
private LocalDateTime localDateTime;
private Date date;
}
Startup logs (even when columns already exist with the right type):
[Hibernate] alter table if exists auth0.test alter column date set data type timestamp(6)
[Hibernate] alter table if exists auth0.test alter column instant set data type timestamp(6) with time zone
[Hibernate] alter table if exists auth0.test alter column local_date_time set data type timestamp(6)
[Hibernate] alter table if exists auth0.test alter column offset_date_time set data type timestamp(6) with time zone
[Hibernate] alter table if exists auth0.test alter column zoned_date_time set data type timestamp(6) with time zone
*Quick analysis (using 6.2.0.CR4)*
With hbm2ddl.auto=update: StandardTableMigrator#sqlAlterStrings checks both type and length
//StandardTableMigrator line 88
if ( !ColumnDefinitions.hasMatchingType( column, columnInformation, metadata, dialect )
|| !ColumnDefinitions.hasMatchingLength( column, columnInformation, metadata, dialect ) )
With hbm2ddl.auto=validate: AbstractSchemaValidator#validateColumnType only checks the type (which matches)
//AbstractSchemaValidator line 163
if ( !ColumnDefinitions.hasMatchingType( column, columnInformation, metadata, dialect ) ) {
So the problem is in ColumnDefinitions.hasMatchingLength :
final int actualSize = columnInformation.getColumnSize();
if ( actualSize == 0 ) {
return true ;
}
else {
final Size size = column.getColumnSize( dialect, metadata );
final Long requiredLength = size.getLength();
final Integer requiredPrecision = size.getPrecision();
return requiredLength != null && requiredLength == actualSize
|| requiredPrecision != null && requiredPrecision == actualSize
|| requiredPrecision == null && requiredLength == null ;
}
For a timestamp with zone column:
* actualSize = 35 (no idea why)
* requiredLength is null
* requiredPrecision = 6
* ==> requiredPrecision != null && requiredPrecision == actualSize is false
( https://hibernate.atlassian.net/browse/HHH-16360#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16360#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#100219- sha1:0c2c9f2 )
3 years