WrongClassException in Single-Table Inheritance

Description

A WrongClassException "loaded object was of wrong class" is randomly encountered in the following situation:

Parent with single-table inheritance A
B extends A
C extends A

Parent with single-table inheritance X
Y extends X
Z extends X

B has field 'x' of type Y
C has field 'x' of type X

During initialization:

  • The AbstractEntityPersister for class A is loaded and createLoaders() is called

  • JoinWalker.walkEntityTree is invoked for class A

  • The persister.getSubclassPropertyType iteration will encounter both fields 'x' from B and C

  • If C.x is encountered first, then the base type X is walked and everything works without issues

  • If B.x is encountered first, then the subtype Y is walked.

  • When C.x is subsequently encountered, JoinWalker.isDuplicateAssociation will return true for the field and the base type X is not added as an association for A.

  • Later an attempt is made to query for C and a result C.x=Z is returned. A WrongClassException is thrown because Z != expected type Y

This behavior is non-deterministic. The ordering that getSubclassPropertyType iterates is determined by hashtable values and are therefore pseudo-random.

Known workaround:

  • Specify (targetEntity=X.class) on B.x

  • Alternately avoid duplicate field names on subtypes of a single-table entity hierarchy.

Activity

Show:

Christian Beikov March 3, 2017 at 2:52 PM

Not sure about earlier versions, but it works in 5.2. See the test here https://github.com/hibernate/hibernate-orm/pull/1823

Steve Ebersole October 28, 2015 at 3:25 AM

As part of verifying that this issue affects 5.0, please just set the "Affects version". Leave the "verify-affects-5.0" label and leave the issue in "Awaiting Response" status; these are critical for us to be able to track these verifications and triage them. Thanks.

Steve Ebersole October 27, 2015 at 7:15 PM

This bug report does not indicate that the reported issue affects version 5.x. Versions prior to 5.x are no longer maintained. It would be a great help to the Hibernate team and community for someone to verify that the reported issue still affects version 5.x. If so, please add the 5.x version that you verified with to the list of affected-versions and attach the (preferably SSCCE) test case you used to do the verification to the report; from there the issues will be looked at during our triage meetings.

For details, see http://in.relation.to/2015/10/27/great-jira-cleanup-2015/

Ivan Bodrov June 16, 2014 at 7:25 AM

Hi, i am not the reporter of this bug, but i've encountered it several times, last in 4.2.13.Final.
The problem is as stated above. No association is added for a subclass because of isDuplicateAssociation( lhsTable, lhsColumns, associationType ) returns true.

In the next example retrieving TaskEntity with spring data findOne fails if owner is of type NHT (and though has RegionNHTEnity field), but goes fine if owner is of type HT (and though has RegionHTEnity field). Debugger shows that persister is present only for RegionHTEntity.
Also everything is fine if using fetch = lazy for owner field.

@Entity
@Table(name = "pos_task")
public class TaskEntity implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@ManyToOne(optional = false, cascade = CascadeType.ALL) //, fetch = FetchType.LAZY) // fetch lazy to avoid hibernate bug
@JoinColumn(name = "owner_id", referencedColumnName = "id")
private UserEntity owner;

}

@Entity
@Table(name = "pos_user")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
public abstract class UserEntity implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

}

@Entity
@DiscriminatorValue("NHT")
public class UserNHTEntity extends UserEntity {

@ManyToOne(optional = true)
@JoinColumn(name = "region_id")
private RegionNHTEntity regionNHT;

}

@Entity
@DiscriminatorValue("HT")
public class UserHTEntity extends UserEntity {

@ManyToOne(optional = true)
@JoinColumn(name = "region_id")
private RegionHTEntity regionHT;

}

@Entity
@Table(name = "pos_regions")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
public abstract class RegionEntity implements Serializable {
}

@Entity
@DiscriminatorValue("HT")
public class RegionHTEntity extends RegionEntity {
}

@Entity
@DiscriminatorValue("NHT")
public class RegionNHTEntity extends RegionEntity {
}

Brett Meyer April 7, 2014 at 5:48 PM

In an effort to clean up, in bulk, tickets that are most likely out of date, we're transitioning all ORM 3 tickets to an "Awaiting Test Case" state. Please see http://in.relation.to/Bloggers/HibernateORMJIRAPoliciesAndCleanUpTactics for more information.

If this is still a legitimate bug in ORM 4, please provide either a test case that reproduces it or enough detail (entities, mappings, snippets, etc.) to show that it still fails on 4. If nothing is received within 3 months or so, we'll be automatically closing them.

Thank you!

Cannot Reproduce

Details

Assignee

Reporter

Labels

Components

Affects versions

Priority

Created February 23, 2011 at 2:25 AM
Updated March 3, 2017 at 3:08 PM
Resolved March 3, 2017 at 3:08 PM