Usage of the {{@Where}} annotation on a collection that contains entities that make use of {{JOINED}} inheritance strategy results in incorrect SQL.
Hibernate is assuming that the column specified in the {{@Where}} annotation will always be on the table that belongs to the entity in the collection, instead of also checking the super-class tables.
For example, consider the following data model and mapping code:
! attached-image Application_ER . gif png !
{code:title=AbstractProjectVersion.java|borderStyle=solid} @Table(name = "DFIP_PROJECT_VERSION") @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class AbstractProjectVersion {
@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "PROJECT_VERSION_OID") Long oid; @Column(name = "PROJ_VSN_EFF_FROM_DTM") Timestamp effFromDtm; @Column(name = "PROJ_VSN_EFF_TO_DTM") Timestamp effToDtm; public void makeCurrent() { setEffFromDtm( new Timestamp(System.currentTimeMillis()) ); }
public void expire(){ setEffToDtm( new Timestamp(System.currentTimeMillis()) ); }
} {code}
{code:title=ApplicationProjectVersion.java|borderStyle=solid} @Table(name = "DFIP_APPLN_PROJ_VERSION") @Entity public class ApplicationProjectVersion extends AbstractProjectVersion {
@ManyToOne @JoinColumn(name = "APPLICATION_OID", nullable = false) Application application;
@Column(name = "APPLICATION_VERSION_NUM", nullable = false) Integer versionNumber = 1; public ApplicationProjectVersion() { makeCurrent(); }
public ApplicationProjectVersion(Application application) { this(); this.application = application; } } {code}
{code:title=Application.java|borderStyle=solid} @Table(name = "DFIP_APPLICATION") @Entity public class Application { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "APPLICATION_OID") Long oid; // This collection consists of entities that are mapped with InheritanceType.JOINED strategy. // This is where the problem is. // @OneToMany(mappedBy="application", orphanRemoval = true, fetch = FetchType.EAGER) @Cascade({SAVE_UPDATE, DELETE, MERGE}) @Fetch(FetchMode.SELECT) @Where(clause = "PROJ_VSN_EFF_TO_DTM is null") // <= THIS IS THE PROBLEM List<ApplicationProjectVersion> applicationVersions = new ArrayList<>(); public void addApplicationProjectVersion(ApplicationProjectVersion apv) { apv.setApplication(this); if ( !applicationVersions.isEmpty() ) { apv.setVersionNumber(applicationVersions.get(applicationVersions.size() - 1).getVersionNumber() + 1); } applicationVersions.add(apv); } } {code}
Loading {{Application}} will issue incorrect SQL, where {{PROJ_VSN_EFF_TO_DTM}} is being referenced on the {{DFIP_APPLN_PROJ_VERSION}} table, rather than its super-class ({{DFIP_PROJECT_VERSION}}). |
|