Hallo Leute,
ich weiß mein Titel ist nicht äußerst sprechend, aber mir ist gerade nichts eingefallen wie ich mein Problem kurz Beschreiben kann.
Also hier mein Problem.
Ich baue meine Datenbankabfrage durch Criteria auf. Hierfür habe ich mehrere Methoden, die mir mein Criteria immer wieder erweitern und zurück geben.
Das ganze Funktioniert derzeit wunderbar, außer ich beschränke 2 bestimmte Felder zur gleichen Zeit. (Alle anderen Felder kann ich wahllos miteinander beschränken)
Kurz zum Aufbau.
Ich habe eine Filialtabelle.
Eine Filiale hat einen Ort (Land, Bundesland, Kreis) und einen Status.
Der Status ist unterteilt in einen “Hauptstatus” und einen dazugehörigen “Unterstatus”.
Eine Filiale kann mehrere Status haben und ein Stauts kann zu mehreren Filialen gehören.
Daher sieht meine Filial-Hibernateklasse folgendermaßen aus:
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "OrtID", insertable=true, updatable=true)
private Standort myOrt;
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST, mappedBy="myFiliale")
@OrderBy(value = "aktiv asc, erfasstam asc, erfasstum asc")
private Set <FilialStatus> filialstatus = new HashSet<FilialStatus>();
Standort sieht nun folgendermaßen aus:
@Column(name = "PLZ")
private String plz;
@Column(name = "BEZEICHNUNG",insertable=true, updatable=true)
private String ort;
@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name = "KREISID", insertable=true, updatable=true)
private Kreis myKreis;
@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name="BUNDESLANDID",insertable=true, updatable=true)
private Bundesland myBundesland;
@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name = "LANDID", insertable=true, updatable=true)
private Land myLand;
und Land folgendermaßen:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer id;
@Column(name = "BEZEICHNUNG", insertable=true, updatable=true)
private String bezeichnung;
@Column(name = "LANDKZ", insertable=true, updatable=true)
private String landkz;
@OneToMany
private Set <Standort> standort = new HashSet<Standort>();
Filialstatus hat folgenden Aufbau:
private FilialStatusPK pk = new FilialStatusPK();
@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
@JoinColumn(name = "UNTERSTATUSID", referencedColumnName="UNTERSTATUSID", insertable=false, updatable=false)
private Unterstatus myUnterStatus;
@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
@JoinColumn(name = "FILIALID", referencedColumnName="FILIALID", insertable=false, updatable=false)
private Filiale myFiliale;
@Column(name = "ERFASSTAM")
private Date erfasstam;
@Column(name = "ERFASSTUM")
private Time erfasstum;
@Column(name = "AKTIV")
private Integer aktiv;```
und Unterstatus sieht so aus:
```@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
@JoinColumn(name = "OBERSTATUSID", insertable=true, updatable=true)
private Status myStatus;
@Column(name="BEZEICHNUNG")
private String bezeichnung;```
Nun möchte ich wie erwähnt eine Abfrage machen, bei der ich Land und Status begrenzen möchte.
Hierzu habe ich wie erwähnt die Methoden, die meine Criteria erweitern:
```private Criteria searchKundeByStatus(Criteria crit, Object[] statuse) {
if (statuse != null && statuse.length > 0) {
Integer[] statids = new Integer[statuse.length];
Unterstatus stat = null;
for (int index = 0; index < statuse.length; index++) {
stat = (Unterstatus) statuse[index];
statids[index] = stat.getUnterstatusID();
}
crit.createAlias("filialstatus", "filstat")
.add(Restrictions.eq("filstat.aktiv", 1))
.add(Restrictions.in("filstat.myUnterStatus.unterstatusID", statids));
}
return crit;
}
private Criteria searchKundeByLand(Criteria crit, Object[] laender) {
if (laender != null && laender.length > 0) {
Integer[] laenderid = new Integer[laender.length];
for (int index = 0; index < laender.length; index++) {
laenderid[index] = ((Land) laender[index]).getID();
}
crit.createAlias("myOrt.myLand", "land")
.add(Restrictions.in("land.id", laenderid));
}
return crit;
}```
(analog dazu sind auch meine anderen Methoden zur Eingrenzung aufgebaut, die bei diesem Szenario aber keine Rolle spielen)
Habe ich nun mein Criteria zusammengebaut sieht es folgendermaßen aus (toString-Methode):
CriteriaImpl(de.Database.Filiale:this[Subcriteria(myOrt.myLand:land), Subcriteria(filialstatus:filstat)][land.id in (2), filstat.aktiv=1, filstat.myUnterStatus.unterstatusID in (1)])
Führe ich nun ```cirt.list()``` aus, erhalte ich die Exception:
org.hibernate.exception.SQLGrammarException: could not execute query
java.sql.SQLException: [SQL5001] Qualifikationsmerkmal für Spalte oder Tabelle LAND1_ nicht definiert.
schaue ich mir dann das SQL an, was durch Hibernate erzeugt wurde, ist auch an sich klar, warum dieser Fehler auftritt.
[SQL]Hibernate:
/* criteria query */ select
this_.FILIALID as FILIALID5_13_,
.....
filstat2_.FILIALID as FILIALID12_0_,
filstat2_.UNTERSTATUSID as UNTERSTA2_12_0_,
filstat2_.AKTIV as AKTIV12_0_,
filstat2_.ERFASSTAM as ERFASSTAM12_0_,
filstat2_.ERFASSTUM as ERFASSTUM12_0_,
.....
standort8_.ID as ID0_4_,
standort8_.BUNDESLANDID as BUNDESLA4_0_4_,
standort8_.KREISID as KREISID0_4_,
standort8_.LANDID as LANDID0_4_,
standort8_.BEZEICHNUNG as BEZEICHN2_0_4_,
standort8_.PLZ as PLZ0_4_,
bundesland9_.ID as ID2_5_,
bundesland9_.BEZEICHNUNG as BEZEICHN2_2_5_,
kreis10_.ID as ID1_6_,
kreis10_.BEZEICHNUNG as BEZEICHN2_1_6_,
land11_.ID as ID3_7_,
land11_.BEZEICHNUNG as BEZEICHN2_3_7_,
land11_.LANDKZ as LANDKZ3_7_,
.....
unterstatu16_.UNTERSTATUSID as UNTERSTA1_11_11_,
unterstatu16_.BEZEICHNUNG as BEZEICHN2_11_11_,
unterstatu16_.OBERSTATUSID as OBERSTAT3_11_11_,
status17_.ID as ID10_12_,
status17_.BEZEICHNUNG as BEZEICHN2_10_12_
from
FILIALE this_
inner join
FILIALSTATUS filstat2_
on this_.FILIALID=filstat2_.FILIALID
left outer join
FILIALE filiale5_
on filstat2_.FILIALID=filiale5_.FILIALID
left outer join
STANDORT standort8_
on filiale5_.OrtID=standort8_.ID
left outer join
BUNDESLAND bundesland9_
on standort8_.BUNDESLANDID=bundesland9_.ID
left outer join
KREIS kreis10_
on standort8_.KREISID=kreis10_.ID
left outer join
LAND land11_
on standort8_.LANDID=land11_.ID
left outer join
UNTERSTATUS unterstatu16_
on filstat2_.UNTERSTATUSID=unterstatu16_.UNTERSTATUSID
left outer join
STATUS status17_
on unterstatu16_.OBERSTATUSID=status17_.ID
where
land1_.ID in (
?
)
and filstat2_.AKTIV=?
and filstat2_.UNTERSTATUSID in (
?
)
[/SQL]
Es wird ein ALIAS für "LAND" namens "land11_" erstellt.
In der WHERE-Klausel wird aber mit "land1_" gearbeitet.
Hat hier jemand eine Ahnung, warum das der Fall ist?
Ich hoffe ich habe genug Code gepostet. Hab den Code etwas abgekürzt um den Post nicht komplett zu überladen.
Wie erwähnt, tritt der Fehler wirklich nur dann auf, wenn ich Filialstatus und Land zusammen beschränken will.
Nur Filialstatus mit irgendetwas anderem bzw. nur Land mit irgendetwas anderem funktioniert einwandfrei.
Danke schon mal