mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
117 lines
5.1 KiB
Plaintext
117 lines
5.1 KiB
Plaintext
== QRecordEntities
|
|
include::../variables.adoc[]
|
|
|
|
While `<<QRecords>>` provide a flexible mechanism for passing around record data in a QQQ Application, they have one big disadvantage from the point-of-view of a Java Application:
|
|
They do not provide a mechanism to ensure compile-time checks of field names or field types.
|
|
|
|
As such, an alternative mechanism exists, which allows records in a QQQ application to be worked with following a more familiar Java Bean (Entity Bean) like pattern.
|
|
This mechanism is known as a `QRecordEntity`.
|
|
|
|
Specifically speaking, `QRecordEntity` is an abstract base class, whose purpose is to be the base class for entity-bean classes.
|
|
Using reflection, `QRecordEntity` is able to convert objects back and forth from `QRecord` to specific entity-bean subtypes.
|
|
|
|
For example, the method `QRecordEntity::toQRecord()` converts a record entity object into a `QRecord`.
|
|
|
|
Inversely, `QRecordEntity::populateFromQRecord(QRecord record)` sets fields in a record entity object, based on the values in the supplied `QRecord`.
|
|
It is conventional for a subclass of `QRecordEntity` to have both a no-arg (default) constructor, and a constructor that takes a `QRecord` as a parameter, and calls `populateFromQRecord`.
|
|
|
|
In addition to these constructors, a `QRecordEntity` subclass will generally contain:
|
|
|
|
* A `public static final String TABLE_NAME`, used throughout the application as a constant reference to the name for the {link-table}.
|
|
* A series of `private` fields, corresponding to the fields in the table that the entity represents.
|
|
** If these fields are annotated as `@QField()`, then the {link-table} meta-data for the table that the entity represents can in part be inferred by QQQ, by using the method `QTableMetaData::withFieldsFromEntity`.
|
|
* `getX()`, `setX()`, and `withX()` methods for all of the entity's fields.
|
|
|
|
=== Examples
|
|
[source,java]
|
|
.Example Definition of a QRecordEntity subclass: Person.java
|
|
----
|
|
/*******************************************************************************
|
|
** QRecordEntity for the person table.
|
|
*******************************************************************************/
|
|
public class Person extends QRecordEntity
|
|
{
|
|
public static final String TABLE_NAME = "person";
|
|
|
|
@QField(isEditable = false)
|
|
private Integer id;
|
|
|
|
@QField()
|
|
private String firstName;
|
|
|
|
@QField()
|
|
private String lastName;
|
|
|
|
@QField()
|
|
private Integer age;
|
|
|
|
// all other fields
|
|
|
|
/*******************************************************************************
|
|
** Default constructor
|
|
*******************************************************************************/
|
|
public Person()
|
|
{
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
** Constructor that takes a QRecord
|
|
*******************************************************************************/
|
|
public Person(QRecord record)
|
|
{
|
|
populateFromQRecord(record);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
** Custom method to concatenate firstName and lastName
|
|
*******************************************************************************/
|
|
public String getFullName()
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
// if there were more than an example, we could do some null-checks //
|
|
// here to avoid silly output like "Bobby null" :) //
|
|
//////////////////////////////////////////////////////////////////////
|
|
return (firstName + " " + lastName);
|
|
}
|
|
|
|
// all getter, setter, and fluent setter (wither) methods
|
|
}
|
|
----
|
|
|
|
The core ORM actions and process-execution actions of QQQ work with `QRecords`.
|
|
However, application engineers may want to apply patterns like the following example, to gain the compile-time safety of `QRecordEntities`:
|
|
|
|
[source,java]
|
|
.Example Usage of a QRecordEntity
|
|
----
|
|
//////////////////////////////////////////////////////////////////////
|
|
// assume we're working with the "person" table & entity from above //
|
|
//////////////////////////////////////////////////////////////////////
|
|
List<QRecord> recordsToUpdate = new ArrayList<>();
|
|
for(QRecord record : inputRecordList)
|
|
{
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// call the constructor that copies values from the record into the entity //
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Person person = new Person(record);
|
|
|
|
////////////////////////////////////////////////
|
|
// call a custom method defined in the entity //
|
|
////////////////////////////////////////////////
|
|
LOG.info("Processing: " + person.getFullName());
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// age is an Integer, so no type-conversion is needed here //
|
|
/////////////////////////////////////////////////////////////
|
|
person.setAge(person.getAge() + 1);
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// to pass the updated records to UpdateAction, convert them to QRecords //
|
|
///////////////////////////////////////////////////////////////////////////
|
|
recordsToUpdate.add(person.toQRecord());
|
|
}
|
|
----
|
|
|