Blog

cbORM v2.2.0 Released!

Luis Majano August 23, 2019

Spread the word

Luis Majano

August 23, 2019

Spread the word


Share your thoughts

We are so excited to bring you yet another minor release for our cborm project to version 2.2. We have fine tuned our module with some cool new features and some major improvements. So let's start with our orm adventure by installing or updating.

Install or Update

To get started with cborm, just install it via CommandBox: box install cborm. To update your current install just run a update cborm and off you go.

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 with services and Basic CRUD with Active Entity and 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();

What's New With 2.2.0

This release not only has some bug fixes but several new features that pack a punch.

Major Features

 

Criteria Query Fluent If Statements - when()

How many times have you been dealing with if statements in order to add some restrictions into your criteria object? Many, this was the only way before, not anymore. So instead of doing something like the following:

c = newCriteria();

if( isBoolean( arguments.isPublished ) ){
  
	c.isEq( "isPublished", isPublished );

	// Published eq true evaluate other params
    if( isPublished ){
        c.isLt( "publishedDate", now() )
        .$or( c.restrictions.isNull( "expireDate" ), c.restrictions.isGT( "expireDate", now() ) )
        .isEq( "passwordProtection","" );
    }

}

if( !isNull( arguments.showInSearch ) ){
	c.isEq( "showInSearch", showInSearch );
}


return c.list();

This looks like normal code, but we can do a more functional approach by introducing the when() function:

/**
* @test The boolean evaluation
* @target The closure to execute if test is true
*/
when( boolean test, function target )

This function takes in as the first argument a boolean value, if the value is true, then the target closure will be called for you and the criteria will be passed via the arguments scope:

newCriteria()
    .when( isBoolean( arguments.isPublished ), function( c ){
        // Published bit
        c.isEq( "isPublished", isPublished )
        	.when( isPublished, function( c ){
        		c.isLt( "publishedDate", now() )
	            .$or( c.restrictions.isNull( "expireDate" ), c.restrictions.isGT( "expireDate", now() ) )
	            .isEq( "passwordProtection","" );
        	} )
    } )
  .when( !isNull( arguments.showInSearch ), function( criteria ){	
  	c.isEq( "showInSearch", showInSearch );
   } )
  .list()

This construct will help you create more fluent designs when building criteria queries, enjoy!

 

PeekaBoo! - peek()

We have also enhanced the criteria queries with a peek() function which allows you to peek in the current position of the criteria build up. This allows you to debug or inspect the SQL/HQL inside the criteria at that point in time. You can use it for sending debug data or logging, or auditing.

/**
* @target the closure to execute, the criteria is passed as an argument
*/
peek( target )

Enjoy your peekaboo function!

newCriteria()
    .when( isBoolean( arguments.isPublished ), function( c ){
        // Published bit
        c.isEq( "isPublished", isPublished )
        	.when( isPublished, function( c ){
        		c.isLt( "publishedDate", now() )
	            .$or( c.restrictions.isNull( "expireDate" ), c.restrictions.isGT( "expireDate", now() ) )
	            .isEq( "passwordProtection","" );
        	} )
    } )
  .peek( function( c ){
      systemOutput( "HQL after publish: #criteria.getSql()# ");
  } )
  .when( !isNull( arguments.showInSearch ), function( criteria ){	
  	c.isEq( "showInSearch", showInSearch );
   } )
   .peek( function( c ){
      systemOutput( "HQL before listing: #criteria.getSql()# ");
  } )
  .list()

 

ValidateOrFail

We have added a new function on the ActiveEntity object to assist with validations. The validateOrFail() function will allow you to validate the entity and if it validates it just returns the instance of the entity for a nice fluent design. However, if the validation fails, it throws a ValidationException and the errors are passed to the exception object via the extendedInfo key. You can then deal with the exception as needed.

getInstance( "User" )
    .populate( rc )
    .validateOrFail()
    .save();

 

Release Notes

  • Features: New function for criteria query when( boolean, target ) that you can use to build functional criterias without the use of if statements.
  • Feature: Missing nullValue() is BaseBuilder class
  • Feature: Added new criteria query peek( closure ) function to allow for peeking into the building process. Pass in your closure that receives the criteria and interact with it.
  • Feature: Added a validateOrFail() to the active entity, which if the validation fails it will throw an exception or return back to you the same entity validated now.
  • Improvement: Better documentation for deleteById() since it does bulk deletion, which does not do any type of cascading.
  • Improvement: isValid() in active entity missing includeFields argument
  • Improvement: Timeout hints for criteria builder
  • Improvement: Updated exception type for criteria builder get()
  • Bug: ACF2016 issues with elvis operator.
  • Bug: getOrFail() had an invalid throw statement

Add Your Comment

Recent Entries

ColdBox 7.2.0 Released

ColdBox 7.2.0 Released

ColdBox, a widely used development platform for ColdFusion (CFML), has unveiled version 7.2. Packed with compelling new features, bug fixes, and enhancements, this release is designed to empower developers by boosting productivity, refining scheduled task capabilities, and enhancing the overall reliability and efficiency of application development. This article will delve into the key highlights of ColdBox 7.2 and elucidate how these advancements can positively impact developers in their daily coding endeavors.

Luis Majano
Luis Majano
November 20, 2023
Into the Box 2023 Series on CFCast

Into the Box 2023 Series on CFCast

Excitement is in the air as we unleash the highly anticipated ITB 2023 series exclusively for our valued CFCast subscribers – and the best part? It's FREE for CFCast members! Now is the perfect time if you haven't joined the CFCast community yet. Plus, we've got an incredible End-of-Year deal that's too good to miss

Maria Jose Herrera
Maria Jose Herrera
November 20, 2023
Ortus Deals are Finally Here!

Ortus Deals are Finally Here!

The much-anticipated Ortus End-of-the-Year Sale has arrived, and it's time to elevate your development experience! Whether you're a seasoned developer, a tech enthusiast, or someone on the lookout for top-notch projects, Ortus has something special in store for you. Brace yourself for incredible discounts across a wide array of products and services, including Ortus annual events, books, cutting-edge services, and more.

Maria Jose Herrera
Maria Jose Herrera
November 15, 2023