Sie erstellen die Gruppe verschachtelter Beans, die die hierarchische Datenstruktur der zurückzugebenden Daten definiert. Wenn Sie eine Annotation @JoinPoint für eine Bean-Eigenschaft angeben, die mit einer Spalte eines ResultSet-Objekts übereinstimmt, generiert pureQuery Runtime die entsprechende Implementierung. pureQuery Runtime analysiert die hierarchische Struktur der Bean der höchsten Ebene. Dies ist die Bean, die nach der Verarbeitung des ResultSet-Objekts und der verschachtelten Beans zurückgegeben wird. Es werden nur die Beans bzw. die Liste von Beans generiert und gefüllt, die durch eine Spalte eines ResultSet-Objekts aktualisiert wurden und die eine Annotation @JoinPoint haben. Beans bzw. Beanlisten, die nicht durch eine Spalte eines ResultSet-Objekts gefüllt werden oder die keine Annotation @JoinPoint haben, haben entweder den Wert Null oder den Initialisierungswert des Bean-Konstruktors.
Hier sehen Sie ein Beispiel mit zwei Beans. Die Bean der höchsten Ebene ist eine Department-Bean und die untergeordneten Beans sind eine Liste von Employee-Beans.
Select D.DEPTNO, D.DEPTNAME, D.MGRNO, D.ADMRDEPT, E.EMPNO, E.FIRSTNME, E.MIDINIT,
E.LASTNAME, E.JOB, E.SEX, E.BIRTHDATE, E.SALARY
from (DEPARTMENT AS D LEFT JOIN EMPLOYEE AS E ON D.DEPTNO=E.WORKDEPT)
WHERE D.DEPTNO=? ORDER BY D.DEPTNO, E.LASTNAME
@Select(sql = "Select D.DEPTNO, D.DEPTNAME, D.MGRNO, D.ADMRDEPT, E.EMPNO,
E.FIRSTNME, E.MIDINIT, E.LASTNAME, E.JOB, E.SEX, E.BIRTHDATE, E.SALARY
from (DEPARTMENT AS D LEFT JOIN EMPLOYEE AS E ON D.DEPTNO=E.WORKDEPT)
WHERE D.DEPTNO=? ORDER BY D.DEPTNO, E.LASTNAME")
public Department joinTest (String deptNo);
@Table(name = "DEPARTMENT")
public class Department
{
@Id
@GeneratedKey
public String deptNo; // this is the ID of the bean and its value is generated by the database
public String deptName;
public String mgrNo;
public String admrDept;
@JoinPoint(@JoinColumn(name = "EMPNO", table = "EMPLOYEE", propertyName = "empNo"))
public List<Employee> deptEmployees;
}
@Table(name = "EMPLOYEE")
public class Employee
{
@Id
@GeneratedKey
public String empNo; // this is the ID of the bean and its value is generated by the database
public String firstNme;
public String midInit;
public String lastName;
public String workDept;
public String job;
public String sex;
public java.sql.Date birthdate;
public String salary;
}
pureQuery Runtime generiert Implementierungscode für die Beans basierend auf der SQL-Abfrage und den Beans.
Die zurückgegebenen Java-Objekte sind eine Bean 'Department', die ein Objekt java.util.List mit 11 deptEmployees-Beans enthält.
dept admr mid
No deptName mgrNo Dept empNo firstNme Init lastName job sex birthdate salary
D11 MANUFACTURING SYSTEMS 000060 D01 000150 BRUCE ADAMSON DESIGNER M 1977-05-17 55280.00
000200 DAVID BROWN DESIGNER M 1971-05-29 57740.00
200220 REBA K JOHN DESIGNER F 1978-03-19 69840.00
000210 WILLIAM T JONES DESIGNER M 2003-02-23 68270.00
000220 JENNIFER K LUTZ DESIGNER F 1978-03-19 49840.00
000160 ELIZABETH R PIANKA DESIGNER F 1980-04-12 62250.00
000180 MARILYN S SCOUTTEN DESIGNER F 1979-02-21 51340.00
000060 IRVING F STERN MANAGER M 1975-07-07 72250.00
000190 JAMES H WALKER DESIGNER M 1982-06-25 50450.00
200170 KIYOSHI YAMAMOTO DESIGNER M 1981-01-05 64680.00
000170 MASATOSHI J YOSHIMURA DESIGNER M 1981-01-05 44680.00
Beim Generieren und Füllen einer Gruppe verschachtelter Beans verwendet pureQuery Runtime die Annotation @JoinPoint beim Verweis auf die Bean im übergeordneten Element der Bean oder in der Annotation @Id der Bean selbst. Die Annotationen definieren die Identitätsspalten, die die untergeordneten Beans mit der übergeordneten Bean verknüpfen. pureQuery Runtime nutzt Identitätsspalten beispielsweise, um zu ermitteln, wann eine Liste von Beans für eine übergeordnete Bean zu generieren ist.
Eine Tabelle EMPLOYEE könnte z. B. mehrere Spalten enthalten, die Identitätsspalten sein könnten. Spalten, die als Identitätsspalte definiert werden könnten, sind die Personalnummer oder die Sozialversicherungsnummer des Mitarbeiters. Die Identitätsspalte kann der Primärschlüssel der Tabelle sein; sie muss jedoch kein Tabellenschlüssel sein. Mehrere Spalten können zu einem Verbundschlüssel kombiniert werden, ein Verbundschlüssel kann aber auch für eine Datenbanktabelle erstellt werden. Der Name wäre eine schlechte Wahl für eine Identitätsspalte der Tabelle EMPLOYEE, da Mitarbeiter denselben Namen haben könnten.
pureQuery Runtime stellt sicher, dass die Beans mit der korrekten Datengruppe in der richtigen Reihenfolge gefüllt werden. Beispielsweise sind die ResultSet-Daten möglicherweise nicht so sortiert, dass sie sich genau der Struktur der verschachtelten Bean zuordnen lassen. pureQuery Runtime kann ResultSet-Daten verarbeiten, die zu Beans gehören, die früher in der Verarbeitung des ResultSet-Objekts erstellt wurden, und kann Beans mit den entsprechenden Daten in der richtigen Reihenfolge füllen.
Sie können eine Gruppe verschachtelter Beans erstellen, die Ergebnisse aus SQL-Anweisungen mit komplexen Joinvergleichselementen zurückgeben, indem Sie eine komplexere Verschachtelungsstruktur mit den korrekten Annotationen erstellen. Zur Erstellung einer Gruppe von Beans, die die korrekten Ergebnisse zurückgeben, müssen die folgenden Regeln beachtet werden. Möglicherweise sind Änderungen an der SQL-Abfrage oder an den Beans erforderlich, damit eine sinnvolle Gruppe von Beans erstellt werden kann.
Dieses Problem kann durch Angabe von Aliasnamen in der SQL-Abfrage behoben werden. In Beans, die mehrere Spalten enthalten, können auch @Column-, @Table- oder @JoinColumn-Annotationen mit dem Tabellennamen in den Eigenschaften angegeben werden.
Der Basiseigenschaftsname ist der Name einer Bean-Eigenschaft ohne Annotationen, die deren Zuordnung zum ResultSet-Objekt verändern. Bei einem Feld ist der Basiseigenschaftsname der Java-Variablenname. Bei einer get-, set- oder is-Methode ist dies der Methodenname ohne das Präfix get, set oder is und das erste Zeichen ist in Kleinbuchstaben geschrieben. Bei den folgenden Beispielen muss bei der ResultSet-Spaltenkennung WORKDEPT die Groß-/Kleinschreibung nicht beachtet werden.
@Column(name = "WORKDEPT") public String getWorkDepartment ();
Eine @JoinColumn-Annotation kann in einer @JoinPoint-Annotation in einer Bean oder einer Liste von Beans angegeben werden. In diesem Fall setzen die angegebenen Elemente name und table die Spaltenkennung und den optionalen Tabellennamen, die in den @Id-Annotationen der untergeordneten Bean definiert sind, sowie alle zugehörigen angegebenen @Column-Annotationen außer Kraft.
Eine untergeordnete Bean kann mehrere @Id-Annotationen enthalten. In diesem Fall sollte das erforderliche Element name der Annotation @JoinColumn dem Basiseigenschaftsnamen in der untergeordneten Bean entsprechen. Wenn die Namen nicht übereinstimmen, muss das optionale Element propertyName mit dem Namen der übereinstimmenden Basiseigenschaft in der untergeordneten Bean angegeben werden.
@JoinPoint(@JoinColumn(name = "EMPNO", table = "EMPLOYEE", propertyName = "empNo")) public List<Employee> deptEmployees;
@JoinPoint(@JoinColumn(name = "EMPNUM", table = "EMPLOYEE", propertyName = "empNo")) public List<Employee> deptEmployees;
@JoinPoint(@JoinColumn(name = "WORKDEPT", table = "EMPLOYEE", propertyName = "workDept")) public List<Employee> deptEmployees;
Eine untergeordnete Bean muss eine einzelne Bean oder eine Liste von Beans sein und die untergeordnete Bean muss die Annotation @JoinPoint enthalten. Die Annotation @JoinPoint muss sich in der Eigenschaft der übergeordneten Bean befinden, die die untergeordnete Bean bzw. Liste von Beans definiert.
Ein Beispiel für diese Zuordnung ist eine Tabelle DEPARTMENT, die eine Spalte DEPTNO enthält, die ein Primärschlüssel ist, und eine Tabelle PROJECT, die ebenfalls eine Spalte DEPTNO enthält. Die Spalte DEPTNO der Tabelle PROJECT ist ein Fremdschlüssel für die Tabelle DEPARTMENT. Der Abgleich zwischen Spalten im ResultSet-Objekt und in den Eigenschaften wird standardmäßig anhand der Spaltenkennung durchgeführt. In diesem Beispiel könnte ein Join der Tabellen DEPARTMENT und PROJECT zwei Spalten ergeben, die eine Spaltenkennung DEPTNO haben. Wenn die Struktur der über- und untergeordneten Beans erfordert, dass diese Spalten unterschiedliche Informationen enthalten, können Sie Annotationen zu den Beans hinzufügen. Die Annotationen können die Spalten durch Verwendung des Tabellennamens eindeutig machen. Sie können auch die SQL-Anweisungen ändern, indem Sie einen Aliasnamen hinzufügen, um eine eindeutige Spaltenkennung zu erzeugen. Es ist jedoch in SQL-Abfragen mit einem Join üblich, dass nur eine Spalte zurückgegeben wird, wenn mehrere Spalten identische Daten enthalten würden. In diesem Fall wäre es zulässig, dass eine Spalte mehrere Eigenschaften aktualisiert.
Mit der integrierten Darstellung erhalten Sie Warnungen, wenn mehrere Eigenschaften von derselben ResultSet-Spalte aktualisiert werden. Die Warnungen werden in der pureQuery Runtime-Protokolldatei protokolliert, sofern diese vorhanden ist, und die Tracestufe wird auf java.util.logging.Level.WARNING oder feiner gesetzt.
Alle untergeordneten Beans der ursprünglichen übergeordneten Bean werden verarbeitet, bevor untergeordnete Beans verarbeitet werden, um zu ermitteln, ob sie ihrerseits untergeordnete Beans enthalten.
pureQuery Runtime kann ermitteln, ob eine Klasse untergeordneter Beans zum ersten Mal verarbeitet wird oder ob es rekursive Verweise in den Beans gibt. Wenn das pureQuery Runtime-Parsing der verschachtelten Bean-Struktur eine Bean erkennt, die bereits geparst wurde, wird das Parsing dieser untergeordneten Bean gestoppt.
Rekursive Verweise auf eine Bean wirken sich auch darauf aus, wie pureQuery Runtime die Eigenschaften von untergeordneten Beans füllt. Nur die erste Instanz der Bean wird gefüllt. Spätere Verweise auf diese Bean werden ignoriert, es sei denn, der Verweis enthält eine Annotation @JoinColumn, für die ein anderes columnPrefix-Element definiert ist. Da die Verarbeitungsreihenfolge von Eigenschaften in einer einzigen Bean nicht deterministisch ist, werden auch die untergeordneten Beans in nicht deterministischer Reihenfolge verarbeitet. Die untergeordneten Beans werden jedoch in der Reihenfolge der Verschachtelungsebene verarbeitet. Beispielsweise wird eine Bean, die direkt unter der übergeordneten Bean angeordnet ist, vor einer Bean auf der nächsten Verschachtelungsebene verarbeitet.
Informationen zum Element columnPrefix finden Sie in der Dokumentation zur Annotation @JoinPoint.