That's all that is needed to get started with Quick. There are a few defaults of Quick worth mentioning here.
You can generate Quick entities from CommandBox! Install quick-commands and use quick entity create to get started!
Tables
We don't need to tell Quick what table name to use for our entity. By default, Quick uses the pluralized name of the component for the table name. That means for our User entity Quick will assume the table name is users. You can override this by specifying a table metadata attribute on the component.
Quick also assumes a key type that is auto-incrementing. If you would like a different key type, override thekeyType function and return the desired key type from that function.
keyType can be any component that adheres to the keyType interface, so feel free to create your own and distribute them via ForgeBox.
interfacedisplayname="KeyType" {/** * Called to handle any tasks before inserting into the database. * Recieves the entity as the only argument. */publicvoidfunctionpreInsert( required entity );/** * Called to handle any tasks after inserting into the database. * Recieves the entity and the queryExecute result as arguments. */publicvoidfunctionpostInsert( required entity, required struct result );}
Attributes
You specify what attributes are retrieved by adding properties to your component.
Now, only the id, username, and email attributes will be retrieved.
Make sure to include the primary key (id by default) as a property.
Persistent
To prevent Quick from mapping a property to a database column add the persistent="false" attribute to the property. This is needed mostly when using dependency injection.
If the column name in your table is not the column name you wish to use in Quick, you can specify the column name using the column metadata attribute. The attribute will be available using the name of the attribute.
In some cases you will need to specify an exact SQL type for your attribute. Any value set for the sqltype attribute will be used when inserting or updating the attribute in the database. It will also be used when you use the attribute in a where constraint.
The casts attribute allows you to use a value in your CFML code as a certain type while being a different type in the database. A common example of this is a boolean which is usually represented as a BIT in the database.
Two casters ship with Quick: BooleanCast@quick and JsonCast@quick. You can add them using those mappings to any applicable columns.
Custom Casts
The casts attribute must point to a WireBox mapping that resolves to a component that implements the quick.models.Casts.CastsAttribute interface. (The implements keyword is optional.) This component defines how to get a value from the database in to the casted value and how to set a casted value back to the database. Below is an example of the built-in BooleanCast, which comes bundled with Quick.
// BooleanCast.cfccomponent implements="CastsAttribute" {/** * Casts the given value from the database to the target cast type. * * @entity The entity with the attribute being casted. * @key The attribute alias name. * @value The value of the attribute. * * @return The casted attribute. */ public any functionget( required any entity, required string key, any value ) {returnisNull( arguments.value ) ?false:booleanFormat( arguments.value ); }/** * Returns the value to assign to the key before saving to the database. * * @entity The entity with the attribute being casted. * @key The attribute alias name. * @value The value of the attribute. * * @return The value to save to the database. A struct of values * can be returned if the cast value affects multiple attributes. */ public any functionset( required any entity, required string key, any value ) {return arguments.value ?1:0; }}
Casted values are lazily loaded and cached for the lifecycle of the component. Only cast values that have been loaded will have set called on them when persisting to the database.
Casts can be composed of multiple fields as well. Take this Address value object, for example:
Noticed that the casted address is neither persistent nor does it have a getter or setter created for it.
The last piece of the puzzle is our AddressCast component that handles casting the value to and from the native database values:
component implements="quick.models.Casts.CastsAttribute" { property name="wirebox" inject="wirebox";/** * Casts the given value from the database to the target cast type. * * @entity The entity with the attribute being casted. * @key The attribute alias name. * @value The value of the attribute. * @attributes The struct of attributes for the entity. * * @return The casted attribute. */ public any functionget( required any entity, required string key, any value ) {returnwirebox.getInstance( dsl ="Address" ).setStreetOne( entity.retrieveAttribute( "streetOne" ) ).setStreetTwo( entity.retrieveAttribute( "streetTwo" ) ).setCity( entity.retrieveAttribute( "city" ) ).setState( entity.retrieveAttribute( "state" ) ).setZip( entity.retrieveAttribute( "zip" ) ); }/** * Returns the value to assign to the key before saving to the database. * * @entity The entity with the attribute being casted. * @key The attribute alias name. * @value The value of the attribute. * @attributes The struct of attributes for the entity. * * @return The value to save to the database. A struct of values * can be returned if the cast value affects multiple attributes. */ public any functionset( required any entity, required string key, any value ) {return {"streetOne":arguments.value.getStreetOne(),"streetTwo":arguments.value.getStreetTwo(),"city":arguments.value.getCity(),"state":arguments.value.getState(),"zip":arguments.value.getZip() }; }}
You can see that returning a struct of values from the set function assigns multiple attributes from a single cast.
Insert & Update
You can prevent inserting and updating a property by setting the insert or update attribute to false.
Quick uses a default datasource and default grammar, as described here. If you are using multiple datasources you can override default datasource by specifying a datasource metadata attribute on the component. If your extra datasource has a different grammar you can override your grammar as well by specifying a grammar attribute.
At the time of writing Valid grammar options are: MySQLGrammar@qb, PostgresGrammar@qb, SqlServerGrammar@qb and OracleGrammar@qb. Please check the qb docs for additional options.
Comparing Entities
You can compare entities using the isSameAs and isNotSameAs methods. Each method takes another entity and returns true if the two objects represent the same entity.