We are so excited to release a second major version of our cborm project to version 2.x. This is a complete overhaul of our library and it now includes support for Hibernate 3, 4 and 5 in order to support Lucee5, Adobe ColdFusion 2016, 2018 and beyond. We have made tremendous new improvements and compelling performance upgrades for any ORM related operation. So get ready for a new ORM adventure. Let's begin with a small intro to cborm and show you how easy it is to get started with a simple CommnadBox command:

install cborm

New Documentation Book

We have completely overhauled the documentation for this module and converted it to a comprehensive book. The new book contains a refreshed look, better categorization, improved structure and some very nice intros to working with Basic CRUD all the way to advanced criteria queries.

What is cborm

The cborm module is a module that will enhance your experience when working with the ColdFusion ORM powered by Hibernate. It will not only enhance it with dynamic goodness but give you a fluent and human approach to working with Hibernate

  • Service Layers with all the methods you could probably think off to help you get started in any project
  • Virtual service layers so you can create virtual services for any entity in your application
  • ActiveEntity our implementation of Active Record for ORM
  • Fluent queries via Hibernate's criteria and detached criteria queries with some Dynamic CFML goodness
  • Automatic transaction demarcation for save and delete operations
  • Dynamic finders and counters for expressive and fluent shorthand SQL
  • Automatic Java casting
  • Entity population from json, structs, xml, and queryies including building up their relationships
  • Entity validation via cbValidation
  • Includes the Mementifier project to produce memento states from any entity, great for producing JSON
  • Ability for finders and queries to be returned as Java streams using our cbStreams project.
# A quick preview of some functionality

var book = new Book().findByTitle( "My Awesome Book" );
var book = new Book().getOrFail( 2 );
new Book().getOrFail( 4 ).delete();
new Book().deleteWhere( isActive:false, isPublished:false );

property name="userService" inject="entityService:User";

return userService.list();
return userService.list( asStream=true );

var count = userService.countWhere( age:20, isActive:true );
var users = userService.findAllByLastLoginBetween( "01/01/2019", "05/01/2019" );

userService
    .newCriteria()
    .eq( "name", "luis" )
    .isTrue( "isActive" )
    .getOrFail();

userService
    .newCriteria()
    .isTrue( "isActive" )
    .joinTo( "role" )
        .eq( "name", "admin" )
    .asStream()
    .list();

userService
    .newCriteria()
    .withProjections( property="id,fname:firstName,lname:lastName,age" )
    .isTrue( "isActive" )
    .joinTo( "role" )
        .eq( "name", "admin" )
    .asStruct()
    .list();

Release Notes

In this release we focused on the complete rewrite of the module to support a more modern and fluent approach to working with Hibernate/ColdFusion ORM. In this release we had to support 3 versions of Hibernate: 3 (Lucee), 4 (ACF 2016) and 5 (ACF 2018), which in itself proved to be a gargantuan task.

We also focused on bringing more functional programming aspects to working with collections of entities and even introduced cbStreams as part of the cborm module. This gives you the ability to produce streams out of any method that produces a collection of entities.

We also focused on converting the state of an object graph to a raw ColdFusion data struct as we live in the world of APIs. We include the mementifier module which allows every single entity to have a getMemento() method that will convert itself and its relationships to raw CF data constructs so you can take that state and either marshall it to another format (json,xml,excel) or audit the state.

General Updates

  • Mementifier is now a dependency for cborm (www.forgebox.io/view/mementifier), which can be used for producing state out of ORM entities for auditing or building JSON Api's.
  • cbStreams is now a dependency for cborm (www.forgebox.io/view/cbstreams), all criteria queries and major listing methods support the return of streams instead of array of objects
  • Full Null Support
  • Performance update on creating active entities as datasource discovery has been reworked
  • Updated build process to latest in Ortus template
  • Dropped Railo, Lucee 4.5, ACF11 support
  • More direct scoping for performance updates
  • Optimized EventHandler so it is lighter and quicker when doing orm injections
  • Documented all functions with extra examples and notes and hibernate references
  • ColdBox 5 and 4 discrete ORM Injection DSLs

Criteria Queries

  • They have been adapted to work with Hibernate 3, 4 and 5
  • New fail fast method for get() -> getOrFail() to throw an entity not found exception
  • New alias methods for controlling the result transformations asStruct(), asStream(), asDistinct() that will apply result transformers for you instead of doing .resultTransformer( c.ALIAS_TO_ENTITY_MAP ), whish is long and boring, or return to you a java stream via cbStreams.
  • When calling native restrictions, no more reflection is used to discover the restriction type thus increasing over 70% in performance when creating criteria queries
  • You can now negate any criteria restriction by prefixing it with a not. So you can do: .notEq(), notBetween(), notIsNull(), notIsIn() and much more.
  • The list() method has a new asStream boolean argument that if true, will return the results as a cbStream. ((www.forgebox.io/view/cbStreams))
  • New Methods: idCast() and autoCast() added for quick casting of values
  • New method: queryHint() so you can add your own vendor specific query hints for optimizers.
  • New method: comment( string ) so you can add arbitrary comments to the generated SQL, great for debugging
  • sqlRestriction() deprecated in favor of the shorthand notation: sql()
  • The sql() restriction now supports binding positional parameters. You can pass them in an array and we will infer the types: sql( "id = ? and isActive = ?", [ "123", true ] ). Or you can pass in a struct of {value:"", type:""} instead:
restrictions.sql( "userName = ? and firstName like ?", [
    { value : "joe", type : "string" },
    { value : "%joe%", type : "string" }
] );

The available types are the following which match the Hibernate Types

this.TYPES = {
    "string"         : "StringType",
    "clob"            : "ClobType",
    "text"            : "TextType",
    "char"            : "ChareacterType",
    "boolean"         : "BooleanType",
    "yesno"         : "YesNoType",
    "truefalse"        : "TrueFalseType",
    "byte"             : "ByteType",
    "short"         : "ShortType",
    "integer"         : "IntegerType",
    "long"             : "LongType",
    "float"            : "FloatType",
    "double"         : "DoubleType",
    "bigInteger"    : "BigIntegerType",
    "bigDecimal"    : "BigDecimalType",
    "timestamp"     : "TimestampType",
    "time"             : "TimeType",
    "date"             : "DateType",
    "calendar"        : "CalendarType",
    "currency"        : "CurrencyType",
    "locale"         : "LocaleType",
    "timezone"        : "TimeZoneType",
    "url"             : "UrlType",
    "class"         : "ClassType",
    "blob"             : "BlobType",
    "binary"         : "BinaryType",
    "uuid"             : "UUIDCharType",
    "serializable"    : "SerializableType"
};
  • Detached Criteria builder now has a maxResults( maxResults ) method to limit the results by
  • Detached Criteria sql projections now take aliases into account
  • SQL Projections and SQL Group By projections now respect aliases

Base ORM Service

  • New Fail fast methods: getOrFail() proxies to get(), findOrFail() proxies to findIt() that if not entity is produced will throw a EntityNotFound exception
  • All listing methods can now return the results as a cbStream by passing the asStream boolean argument.
  • Removed criteriaCount(), criteriaQuery() from BaseService, this was the legacy criteria builder approach, please use newCriteria() instead.
  • Update getEntityGivenName to support ACF2018
  • Lazy loading BeanPopulator for performance on creations
  • Lazy loading ORMEventHandler for performance on creations
  • Lazy loading restrictions for performance on creations
  • Base service can now be initialized with a datasource, or uses the default one declared
  • Added optional datasource to many listing methods
  • Added consistency on querying options to all major functions to include ignoreCase, sorting and timeouts.
  • Added ability to getAll() to retrieve read only entities using the readOnly argument.
  • The getAll() method has a new properties argument that if passed will allow you to retrieve an array of structs according to the passed in properties.
  • New method: idCast( entity, id ) to auto cast your entity id value to java type automatically for you, no more javacasting
  • New method: autoCast( entity, propertyName, value ) to auto cast any value for any entity property automatically, no more javacasting.
  • New method: getKeyValue( entity ) which will give you the value of the entity's unique identifier
  • New method: isDirty( entity ) which will let you know if the entity has dirty values or has its values changed since loaded from the db
  • New method: getEntityMetadata( entity ) which will return to you the hibernate's metadata for a specific entity.
  • getPropertyNames() argument of entityname renamed to entity to allow not only for a name but an actual entity as well.
  • getTableName() argument of entityname renamed to entity to allow not only for a name but an actual entity as well.
  • getKey() argument of entityname renamed to entity to allow not only for a name but an actual entity as well.
  • ORM Encapsulation of hibernate metadata retrieval via getEntityMetadata()
  • deleteByQuery() reworked entirely to do native bulk delete queries. It now also returns the number of records removed
  • deleteWhere() missing flush argument, added datasource as well
  • New properties: wirebox : a WireBox reference already injected, logger : a prepared logger for the class, datasource The default datasource or constructed datasource for the class.
  • Logging of all activity now available via the debug level, even for dynamic methods.
  • Refactored all dynamic finders and counters to their own class, which improves not only performance but weight of orm service based entities.
  • All dynamic method calls can now return cbStreams as the results
  • All dynamic method calls accept a structure as an argument or named as options that can have the following keys now:
{
    ignoreCase     : boolean (false)
    maxResults     : numeric (0)
    offset         : numeric (0)
    cacheable      : boolean (false)
    cacheName      : string (default)
    timeout        : numeric (0)
    datasource     : string (defaults)
    sortBy         : hql to sort by,
    autoCast       : boolean (true),
    asStream    : boolean (false)
}

results = ormservice.findByLastLoginBetween( "User", "01/01/2008", "11/01/2008", { sortBy="LastName" } );
  • All dynamic finders/counters values are autocasted, you no longer need to cast the values, we will do this for you. You can turn it off via the autocast:false in the options to the calls.

Virtual Entity Service

Remember this entity extends Base Service, so we get all the features above plus the following:

Active Entity

Remember this entity extends the Virtual Service, so we get all the features above plus the following:

  • Faster creation speeds due to lazy loading of dependencies and better datasource determination.
  • refresh(), merge(), evict() refactored to encapsulate login in the base orm service and not itself