We're updating the issue view to help you get more done. 

Inverse OneToMany with a CompositeKey fails

Description

The error I am receiving is the following:

1 2 3 4 5 6 7 Caused by: org.hibernate.MappingException: Unable to read the mapped by attribute for cover in c.f.a.d.e.CompanyCover! at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.getMappedBy(CollectionMetadataGenerator.java:589) at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addOneToManyAttached(CollectionMetadataGenerator.java:179) at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addCollection(CollectionMetadataGenerator.java:161) at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValueInSecondPass(AuditMetadataGenerator.java:223) at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValue(AuditMetadataGenerator.java:245) at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addProperties(AuditMetadataGenerator.java:258)

I understand from the error there seems to be a problem with the mapping I have. This is the code I have:

Company.java

1 2 3 4 5 6 7 8 9 @Audited @Entity(name = "Company") @Table(name = "Company") public class Company{ ... @OneToMany(fetch = FetchType.LAZY, mappedBy = "company") private List<CompanyCover> companyCovers; ... }

CompanyCover.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Audited @Entity(name = "CompanyCover") @Table(name = "CompanyCover") @IdClass(CompanyCover.CompanyCoverId.class) public class CompanyCover { ... @Id @ManyToOne(fetch = FetchType.EAGER, optional = false) @JoinColumn(name = "CompanyId", referencedColumnName = "Id", insertable = true, updatable = false, nullable = false) private Company company; @Id @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) @ManyToOne(fetch = FetchType.EAGER, optional = false) @JoinColumn(name = "CoverId", referencedColumnName = "Id", nullable = false, insertable = true, updatable = false) private Cover cover; ...

I've been debugging this issue, and found out the possible root of the problem is related to this method inside CollectionMetadataGenerator.

CollectionMetadataGenerator.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 .... private String searchMappedBy(PersistentClass referencedClass, Collection collectionValue) { Iterator<Property> assocClassProps = referencedClass.getPropertyIterator(); while (assocClassProps.hasNext()) { Property property = assocClassProps.next(); if (Tools.iteratorsContentEqual(property.getValue().getColumnIterator(), collectionValue.getKey().getColumnIterator())) { return property.getName(); } } return null; } ...

In this case, it seems to fail to find the correct mapping. In the specific comparison in Tools.iteratorsContentEqual() call, one of the params is an object representing the CompositeKey (Both columns as expressed by the IdClass), but in the other parameter is only the column related to the specific column that maps the Company object based on the inverse relation. So when comparing it fails and return null. I think that in this cases the comparison should look if the ColumnIterator returns a CompositeKey and in such case compare to find at least a column inside that matches the specific column return in the inverse relation.

P.S. I am trying to flag this in the 4.1.7 version but it seems it has not been created at the moment

Environment

None

Status

Assignee

Chris Cranford

Reporter

Angel Villalain

Fix versions

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

4.1.7
5.1.0
5.0.9
5.2.1

Priority

Major