J'utilise Hibernate 5.1.2annotation Hibernate @Where ne fonctionne pas avec l'héritage
J'ai rencontré un problème inattendu que je ne peux pas sembler travailler autour. Voici le résumé de mon modèle de données:
dfip_project_version
est ma table de superclasse et dfip_appln_proj_version
est ma table de la sous-classe. dfip_application
contient une liste de dfip_appln_proj_version
s.
Je cartographié comme suit:
@Table(name = "DFIP_PROJECT_VERSION")
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractProjectVersion {
@Id @GeneratedValue
@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;
@Column(name = "PROJECT_VERSION_TYPE")
@Type(type = "project_version_type")
ProjectVersionType projectVersionType;
}
@Table(name = "DFIP_APPLN_PROJ_VERSION")
@Entity
class ApplicationProjectVersion extends AbstractProjectVersion {
@OneToOne
@JoinColumn(name = "APPLICATION_OID", nullable = false)
Application application;
public ApplicationProjectVersion() {
projectVersionType = ProjectVersionType.APPLICATION;
}
}
@Table(name = "DFIP_APPLICATION")
@Entity
class Application {
@Id @GeneratedValue
@Column(name = "APPLICATION_OID")
Long oid;
@OneToMany(mappedBy="application", orphanRemoval = true, fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
@Where(clause = "PROJ_VSN_EFF_TO_DTM is null")
List<ApplicationProjectVersion> applicationVersions = [];
}
J'utilise l'annotation @Where
de sorte que seul le ApplicationProjectVersion
courant est le Application
récupéré. Le problème avec ceci est que Hibernate suppose que la colonne que je référence est dans la table dfip_appl_proj_version
, quand elle est réellement sur la table de super-classe (dfip_project_version
).
Voici ce que j'ai essayé jusqu'à présent pour contourner cette limitation:
Tentative 1
J'ai essayé de mettre l'annotation @Where
sur la AbstractProjectVersion
super-classe, comme ceci:
@Table(name = "DFIP_PROJECT_VERSION")
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Where(clause = "PROJ_VSN_EFF_TO_DTM is null")
public abstract class AbstractProjectVersion {
...etc...
}
Cela n'a rien fait, car la clause WHERE ne semble pas être remarquée lors de la récupération du Application
.
Tentative 2
J'ai fait la liste applicationVersions
sur Application
LAZY, et a essayé de la carte latestVersion
manuellement comme ceci:
@Table(name = "DFIP_APPLICATION")
@Entity
class Application {
@Id @GeneratedValue
@Column(name = "APPLICATION_OID")
Long oid;
@OneToMany(mappedBy="application", orphanRemoval = true, fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
List<ApplicationProjectVersion> applicationVersions = [];
@ManyToOne
@JoinColumnsOrFormulas([
@JoinColumnOrFormula(formula = @JoinFormula(value = "(APPLICATION_OID)", referencedColumnName="APPLICATION_OID")),
@JoinColumnOrFormula(formula = @JoinFormula(value = "(select apv.PROJECT_VERSION_OID from DFIP_PROJECT_VERSION pv, DFIP_APPLN_PROJ_VERSION apv where apv.PROJECT_VERSION_OID = pv.PROJECT_VERSION_OID and apv.APPLICATION_OID = APPLICATION_OID and pv.PROJ_VSN_EFF_TO_DTM is null)", referencedColumnName="PROJECT_VERSION_OID")),
])
ApplicationProjectVersion latestVersion;
}
Cela a provoqué Hibernate pour générer le SQL (extrait suivant):
from DFIP_APPLICATION this_
left outer join DFIP_APPLN_PROJ_VERSION applicatio2_
on (this_.APPLICATION_OID)=applicatio2_.APPLICATION_OID and
(select apv.PROJECT_VERSION_OID from DFIP_PROJECT_VERSION pv, DFIP_APPLN_PROJ_VERSION apv
where apv.PROJECT_VERSION_OID = pv.PROJECT_VERSION_OID and apv.APPLICATION_OID = this_.APPLICATION_OID
and pv.PROJ_VSN_EFF_TO_DTM is null)=applicatio2_.PROJECT_VERSION_OID
qui a abouti à ORA-01799: a column may not be outer-joined to a subquery
.
Si je ne peux pas spécifier une sous-requête dans ma formule se joindre, alors je ne peux pas adhérer à la super-classe manuellement ...
Tentative 3
J'ai remarqué que l'utilisation de @JoinFormula
fait remarquer à Hibernate mon annotation @Where
sur la super-classe. J'ai donc essayé les éléments suivants:
@Table(name = "DFIP_PROJECT_VERSION")
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Where(clause = "PROJ_VSN_EFF_TO_DTM is null")
public abstract class AbstractProjectVersion {
...etc...
}
@Table(name = "DFIP_APPLICATION")
@Entity
class Application {
@Id @GeneratedValue
@Column(name = "APPLICATION_OID")
Long oid;
@OneToMany(mappedBy="application", orphanRemoval = true, fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
List<ApplicationProjectVersion> applicationVersions = [];
@ManyToOne
@JoinFormula(value = "(APPLICATION_OID)", referencedColumnName="APPLICATION_OID")
ApplicationProjectVersion latestVersion;
}
Cela a généré SQL (extrait) suivant:
from DFIP_APPLICATION this_
left outer join DFIP_APPLN_PROJ_VERSION applicatio2_
on (this_.APPLICATION_OID)=applicatio2_.APPLICATION_OID and (applicatio2_1_.PROJ_VSN_EFF_TO_DTM is null)
left outer join DFIP_PROJECT_VERSION applicatio2_1_ on applicatio2_.PROJECT_VERSION_OID=applicatio2_1_.PROJECT_VERSION_OID
C'est presque correct!Malheureusement, il n'est pas SQL valide, puisque applicatio2_1_
est utilisé avant qu'il ne soit déclaré sur la ligne suivante :(.
Maintenant, je suis d'idées, de sorte que toute aide serait appréciée. Est-il possible de spécifier un clause WHERE qui apportera seulement le ProjectVersion actuel, sans se débarrasser de ma structure d'héritage?
Related Hibernate issue ticket