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.
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
...
}
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.
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"; }
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();
}