The Field-Name Class Pattern
The Field-Name Class pattern is is the primary use pattern for Inductor. In general, a field-name class is implemented for each persistence-capable class that is to be queried using Inductor. (To be accurate, a field-name class is implemented for each view of a persistence-capable class, but that draws in features best left for subsequent discussion.)
A field-name class serves as a working reference object for Inductor queries. Using a well defined structure, a field-name class enables simple, type-safe, implicit field-level reference to the persistence capable fields as literal components of the IQL. The defined class structure also includes a field set reference, which greatly simplifies the specification of QBE queries. Other field-name structures enable a set of field-name classes to fully parallel the inheritance structure of their corresponding set of persistence-capable classes. Specifying IQL queries against field-name classes is no more complicated than is required by the inheritance relations of the underlying persistence-capable classes being queried.
A Persistence-Capable class enhanced to support IQL Access
Standard Persistence Capable Class (with Inductor Mods):
public class Employee {
// field-name references
public static final String SALUTATION = "salutation");
public static final String FIRSTNAME = "firstname");
public static final String LASTNAME = "lastname");
public static final String TITLE = "title");
public static final String EMPLOYER = "employer");
public static final String EMPLOYEENUMBER = "employeeNumber");
public static final String ADDRESS1 = "address1");
public static final String ADDRESS2 = "address2");
public static final String CITY = "city");
public static final String STATE = "state");
public static final String ZIP = "zip");
// the persistence-capable fields
private String salutation;
private String firstname;
private String lastname;
private String title;
private String employer;
private Integer employeeNumber;
private String address1;
private String address2;
private String city;
private String state;
private String zip;
// constructors/getters/setters
...
}
Notes:
- Any standard persistence-capable class implemented according to the dictates of the particular persistence manager package used.
- The Field name references: a simple set of string constants used as keys for associating Inductor Field class instances with the persistence capable fields encapsulated by this class. The only requirement is that the value of these constants literally match the names of the persistence capable fields. Any names may be used, though a parallel naming convention is recommended.
This set of constants represents the only new structural feature required by Inductor. These constants need not actually be in the persistence-capable class. They could be put in an interface, enum, or any other class, including the Field-Name class itself. The preference for putting the constants here is simply to minimize any desired maintenance.
- Any standard set of persistence capable fields.
- Any standard set of bean accessors as may be desired for use by the persistence manager.
Standard Structured Field-Name Class
Field-Name Class:
public class Emplextends AbstractFieldClass {
// persistence record reference
public Class record = Employee.class; // field-name Fields
public Field sal = new Field(record, Employee.SALUTATION); public Field fname = new Field(record, Employee.FIRSTNAME); public Field lname = new Field(record, Employee.LASTNAME); public Field title = new Field(record, Employee.TITLE); public Field employer = new Field(record, Employee.EMPLOYER); public Field employeeNum = new Field(record, Employee.EMPLOYEENUMBER); public Field addr1 = new Field(record, Employee.ADDRESS1); public Field addr2 = new Field(record, Employee.ADDRESS2); public Field city = new Field(record, Employee.CITY); public Field state = new Field(record, Employee.STATE); public Field zip = new Field(record, Employee.ZIP); // the QBE view reference Field
public Field qbe = new Field(record); // Field reference array
public Field[] fields = { sal, firstname, lastname, title, employer, employeeNum, addr1, addr2, city, state, zip, qbe }; // Field-Name Class internal reference
public String var = "empl2005"; }
Notes:
- Field-Name Class name: any proper class name will do.
- Extends AbstractFieldClass: Required. The AbstractFieldClass implements the machinery needed for field-name class initialization and inheritance support. Extension directly or by inheritance through any sequence of Field-Name Classes is required.
- The persistence-capable class record reference: Required. A Class variable, specifically named 'record', must identify the persistence capable class that corresponds to this field-name class. Effectively binds this field-name class to the identified persistence-capable class.
- The field-name Fields: Required. A set of Field class instances that define the field-level names available for use in Inductor queries. Each Field is bound to the record class and an individual persistence-capable field. Not all persistence-capable fields need be represented by a Field instance. The only limitation is if a persistence-capable field is not represented by a Field instance, then that persistence field cannot be used in defining query criteria.
- The Field qbe view reference: Optional, though recommended. The QBE view-name field is a required variable if this field-name class will be used as the root Field for a QBE constraint. The 'qbe' name is recommended, but not required; the variable name will be the field-level name used is specifying IQL QBE criteria. Even though the view-field is a Field bound generically against the persistence class, this field-reference will be recognized by Inductor as corresponding to whatever set of field-name Fields defined in this field-name class.
- The Field[] fields reference array: Required. a required array variable (must be named 'fields') listing the Fields within this field-name class (order is not significant).
- The String var value: Optional. If specified, the variable name must be 'var'. The assigned value will be used in overriding an automatically generated value used internally to identify this field-name class. Only visible or significant in debugging the generated SQL output. If specified, the value must be globally unique among all field-name classes in the project; automatically generated values are prevented from colliding with any user specified value. In general, use is discouraged.
Use the Field-Name Class
Standard Form IQL Query:
public Collection findPerson(String reqFirstName,String reqLastName, String reqTitle) { Query q = new Query(new JDODriver()
);
Empl empl = new Empl();
q.from(empl);
q.where(empl.fname.startsWith(reqFirstName),
empl.lname.eq(reqLastName), empl.title.eq(reqTitle) ); q.orderBy(empl.employer.asc(), empl.lname.asc());
return q.execute();
}
Notes:
- For convenience, the IQL query is encapsulated in a simple method.
- JDODriver(): For now, either JDODriver() or HIBDriver(). The driver encapsulates all persistence manager specific details. In general, to change the persistence manager package, simply change the driver. Of course, there is no free transparent persistence lunch: incomplete, asymmetric persistence manager implementations will limit the true transportability of IQL queries.
- Construct a query. By default, the query will return a detached Collection, subject to optimistic locking. If an attached collection or if using container managed transactions, simply pass an existing session or persistence manager instance in as a parameter to the driver.
- Create an instance of the Field-Name class. Instances can be globally created and reused. The Field-Name classes are light-weight, so instance creation is preferred unless memory and performance are extremely restricted.
- Bind the query to the field-name class.
- Define the selection criteria using the method operations defined in the Field class.
- Define the query meta-criteria using the method operations defined in the Query class.
- Execute and return a Collection of objects that are type specific to the persistence-capable class referenced by record variable within the field-name class.
public Field qbe = new Field(record);
// Field reference array
public Field[] fields = { sal, firstname, lastname,
title, employer, employeeNum, addr1, addr2,
city, state, zip, qbe };
// Field-Name Class internal reference
public String var = "empl2005";
}
}