# Introduction

The Ortus ORM Extension is a native Lucee Extension that allows your CFML application to integrate with the powerful Hibernate ORM

## Ortus ORM Extension

<figure><img src="/files/gZBCOiYc2qCfORyGJywT" alt=""><figcaption></figcaption></figure>

The [Ortus ORM Extension](https://www.ortussolutions.com/products/orm-extension) is a **native** Lucee Extension that allows your CFML application to integrate with the powerful [Hibernate ORM](https://hibernate.org/orm/). With Hibernate, you can interact with your database records in an object oriented fashion, using components to denote each record and simple getters and setters for each field value:

```js
component entityName="Auto" persistent="true" {

	property name="id" type="string" fieldtype="id" ormtype="string";
	property name="make" type="string";
	property name="model" type="string";

    function onPreInsert(){
        log.info( "Inserting new Auto: #getMake()# #getModel()#" );
    }
}
```

The Ortus ORM extension also enables transactional persistence, where an error during a save will roll back the entire transaction to prevent leaving the database in a broken state:

```js
transaction{
    try{
        entitySave(
            entityNew( "Purchase", {
                productID : "123-expensive-watch",
                purchaseTime : now(),
                customerID : customer.getId()
            })
        );
        var cartProducts = entityLoad( "CartProduct", customer.getID() );
        entityDelete( cartProducts );
    } catch ( any e ){
        // don't clear the user's cart if the purchase failed
        transactionRollback();
        rethrow;
    }
}
```

### Requirements

* Lucee 5.3.9.73 and above
* Java 8, 11 or 17

### Hibernate Version Support

#### Extension v6.2+

The Ortus ORM Extension bundles Hibernate `5.6.15.FINAL` since extension version 6.2.0.

* <https://hibernate.org/orm/releases/5.6/>
* <https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html>
* <https://docs.jboss.org/hibernate/orm/5.6/javadocs/>

#### Extension v6.1-

Previous versions of the Ortus ORM Extension bundle Hibernate `5.4.29.FINAL`:

* <https://hibernate.org/orm/releases/5.4/>
* <https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html>
* <https://docs.jboss.org/hibernate/orm/5.4/javadocs/>

### Open Source Product

The Ortus ORM extension is an open source Lucee server extension with no license purchase necessary. If you are looking to further the development of this extension, consider [sponsoring a feature or opening a support contract](#support).

### Features In A Nutshell

* Add Object Relational Mapping to any CFML app with Hibernate ORM
* Use native CFML methods to update and persist entities to the database (`entityNew()`, `entitySave()`, `ormFlush()`, etc.)
* Supports 80+ database dialects, from `SQLServer2005` to `MySQL8` and `PostgreSQL`
* 60% faster startup than the Lucee Hibernate extension
* Generate your mapping XML once and never again with the `autoGenMap=false` ORM configuration setting
* React to entity changes with pre and post event listeners such as `onPreInsert()`, `onPreUpdate()` and `onPreDelete()`
* Over 20 native CFML functions:
  * `EntityDelete()`
  * `EntityLoad()`
  * `EntityLoadByExample()`
  * `EntityLoadByPK()`
  * `EntityMerge()`
  * `EntityNameArray()`
  * `EntityNameList()`
  * `EntityNew()`
  * `EntityReload()`
  * `EntitySave()`
  * `EntityToQuery()`
  * `ORMClearSession()`
  * `ORMCloseAllSessions()`
  * `ORMEvictCollection()`
  * `ORMEvictEntity()`
  * `ORMEvictQueries()`
  * `ORMExecuteQuery()`
  * `ORMFlush()`
  * `ORMGetSession()`
  * `ORMGetSessionFactory()`
  * `ORMReload()`

See the [extension changelog](https://github.com/Ortus-Solutions/extension-hibernate/blob/master/CHANGELOG.md) for a full list of enhancements and bug fixes.

### Support

Our expertise with Hibernate ORM and Lucee Server allows us to give back to the community, as well as offer premium support to enterprises looking for a level up in their Hibernate implementations. If you need performance optimization, session management or caching integrations, please [contact us for support](https://ortussolutions.atlassian.net/servicedesk/customer/portal/9).

* Source Code: <https://github.com/Ortus-Solutions/extension-hibernate>
* Support Plans: <https://www.ortussolutions.com/services/support>
* Bug Tracker: <https://ortussolutions.atlassian.net/browse/OOE>


# Release History

Release history for all versions of the Ortus ORM Extension

In this section, you will find the release notes for each version we release under this major version. If you are looking for the release notes of previous major versions, use the version switcher at the top left of this documentation book. Here is a breakdown of our major version releases.

## Version 6.x

A new layout, cache and logging improvements, and much more.

## Version 5.x

Our initial fork of the Lucee Extension.


# What's New With 6.x

Version 6.x release notes for the Ortus ORM Extension

### [6.5.4](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.5.3...v6.5.4) - 2026-03-16

### 🐛 Fixed

* fix duplicate entries in manifest
* Remove old org.lucee.xml.apis from Require-bundle

Big thanks to Zack Spitzer on the Lucee team.

### [6.5.3](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.5.2...v6.5.3) - 2025-09-01

### 🐛 Fixed

* Resolved "NoClassDefFoundError: javax/validation/ValidatorFactory" on Lucee 6 by adding missing javax.validation dependency. Big thanks to [Zack Spitzer on the Lucee team](https://github.com/Ortus-Solutions/extension-hibernate/pull/18)! - Resolves [OOE-29](https://ortussolutions.atlassian.net/browse/OOE-29)

### 🔐 Security

* Bumped Logback dependency to `1.3.15` to resolve [SNYK-JAVA-CHQOSLOGBACK-8539866](https://security.snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-8539866) vulnerability.

### New Contributors

* @zspitzer made their first contribution in <https://github.com/Ortus-Solutions/extension-hibernate/pull/18>

### [6.5.2](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.5.1...v6.5.2) - 2024-02-21

#### 🐛 Fixed

* Fixes a regression on [OOE-26](https://ortussolutions.atlassian.net/browse/OOE-26) where empty string values are coerced to `NULL` when an ORM type *is* declared. Originally reported against `6.4.0`, resolved in `6.5.0`, then regressed in `6.5.1`. - Resolves [OOE-26](https://ortussolutions.atlassian.net/browse/OOE-26).

### [6.5.1](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.5.0...v6.5.1) - 2024-02-20

#### 🐛 Fixed

* Fixes empty string values coercing to `NULL` when no property type is declared. - Resolves [OOE-25](https://ortussolutions.atlassian.net/browse/OOE-25), introduced in 6.5.0.

### [6.5.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.4.0...v6.5.0) - 2024-02-16

#### 🐛 Fixed

* Fixes an incorrect property name lookup for the `unsavedValue` persistent property attribute.
* Fixes the pre-event listeners to ignore empty strings in entity state properties if the field type is one of `string`, `character`, or `text`. This resolves issues where a `preInsert()` or `preUpdate()` throws a "can't cast \[] to date value" when processing event listeners if a date field (for example) is unpopulated or has an empty `default` attribute.

#### ♻️ Changed

Add the entity name to the exception message when attempting to persist changes from `preInsert` or `preUpdate` event listeners. The updated exception message is now:

> Error populating event state for persistance in \[\<entity name>] entity pre-event listener method: \<error message from Hibernate>

#### 🔐 Security

Bump Lucee build dependency to `5.4.4.38` to avoid [vulnerable dependencies in the build process](https://mvnrepository.com/artifact/org.lucee/lucee/5.4.1.8).

### [6.4.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.3.2...v6.4.0) - 2023-12-05

#### 🔐 Security

Resolve an [Uncontrolled Resource Consumption vulnerability disclosed on 12/4/2023](https://security.snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6097493) by upgrading `logback-core` to `1.3.14`. [See vulnerability details](https://security.snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6097493).

#### ⭐ Added

New `ORMQueryExecute()` alias for the `ORMExecuteQuery`. This new alias behaves identically to the `ORMExecuteQuery()` method, but is named consistently with the `queryExecute()` method.

#### 🐛 Fixed

* Fixes custom configuration support via `this.ormSettings.ormConfig`.
* Fixes named argument support for `entityLoad()` - [LDEV-4285](https://luceeserver.atlassian.net/browse/LDEV-4285)
* Fixes named argument support for `entityLoadByPK()` - [LDEV-4461](https://luceeserver.atlassian.net/browse/LDEV-4461)

#### ♻️ Changed

While not technically a change in ORM functionality, the `useDBforMapping` implementation has been greatly improved "under the hood", with tests to boot.

### [6.3.2](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.3.1...v6.3.2) - 2023-09-29

#### 🐛 Fixed

Fixed pre-event listeners to include parent component properties when checking for entity mutations to persist back to the event entity state. This resolves issues with changes made in `preInsert()`/`preUpdate()` not persisting if the changes are made on a persistent property from a parent component. Resolves [OOE-14](https://ortussolutions.atlassian.net/browse/OOE-14).

### [6.3.1](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.3.0...v6.3.1) - 2023-09-26

#### 🐛 Fixed

Refactored nullability checks to occur *after* pre-event listener methods fire. Resolves [OOE-12](https://ortussolutions.atlassian.net/browse/OOE-12)

#### ⭐ Added

Added context to the error message in `CFCGetter`, which handles retrieving entity values from Hibernate code. This improves odd error messages in some edge cases with the Hibernate tuplizer.

### [6.3.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.2.0...v6.3.0) - 2023-08-18

#### 🔐 Security

Switched the [EHCache](https://mvnrepository.com/artifact/net.sf.ehcache/ehcache/2.10.6) library to use [net.sf.ehcache.internal:ehcache-core](https://mvnrepository.com/artifact/net.sf.ehcache.internal/ehcache-core/2.10.9.2).

* Upgrades EHCache version from `2.10.6` to `2.10.9.2`.
* Drops an embedded `rest-management-private-classpath` directory
* Drops a number of (unused) vulnerable jackson and jetty libraries such as jackson-core.
* As an added bonus, this reduces the final `.lex` extension file size by over 6 MB. 🎉

**Note:** While it is not 100% clear, [some of these CVEs may have been false positives](https://github.com/jeremylong/DependencyCheck/issues/517).

### [6.2.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.1.0...v6.2.0) - 2023-08-03

### ♻️ Changed

#### Hibernate Upgraded from 5.4 to 5.6

This brings the Hibernate dependencies up to date (released Feb. 2023), and should not change any CFML-facing features for *most* users. (See [CLOB columns in Postgres81](#clob-columns-in-postgres81))

See the migration guides for more info:

* [Hibernate 5.4 -> 5.4 migration guide](https://github.com/hibernate/hibernate-orm/blob/5.5/migration-guide.adoc)
* [Hibernate 5.5 -> 5.6 migration guide](https://github.com/hibernate/hibernate-orm/blob/5.6/migration-guide.adoc)

#### CLOB columns in Postgres81

Due to the Hibernate 5.6 upgrade, if you are using the `PostgreSQL81` dialect and have `CLOB` columns in your database, [it is recommended you migrate existing text columns for LOBs to `oid`](https://github.com/hibernate/hibernate-orm/blob/5.6/migration-guide.adoc#changes-to-the-ddl-type-for-clob-in-postgresql81dialect-and-its-subclasses).

#### Default EHCache Configuration

The default `ehcache.xml` for EHCache changed to include [`clearOnFlush="true"`](https://www.ehcache.org/apidocs/2.10.1/net/sf/ehcache/config/CacheConfiguration.html#clearOnFlush) and [`diskSpoolBufferSizeMB="30MB"`](https://www.ehcache.org/apidocs/2.10.1/net/sf/ehcache/config/CacheConfiguration.html#diskSpoolBufferSizeMB) properties to match [Adobe ColdFusion 9's default `ehCache.xml` config](https://helpx.adobe.com/coldfusion/developing-applications/coldfusion-orm/performance-optimization/caching.html). Both these values represent default settings in EHCache itself.

### 🐛 Fixed

* Fixes handling of `"timezone"`-typed column values. Previously, fields defined with `ormtype="timezone"` would neither use the `default` value nor allow new values to be set. [OOE-10](https://ortussolutions.atlassian.net/browse/OOE-10)
* Fixes entity state changes in `preInsert()`/`preUpdate()` listeners for properties with no `default` defined. [OOE-9](https://ortussolutions.atlassian.net/browse/OOE-9)

### [6.1.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/v6.0.0...v6.1.0) - 2023-07-14

#### ♻️ Changed

* Lots of java source code cleanup that won't affect the CFML experience, but will aid in faster development and fewer bugs.

#### 🐛Fixed

* Any hibernate exceptions returned during schema generation are once again logged to the Lucee ORM log file.

#### 💥 Removed

* Dropped the public method from the Dialect class. This method was unused (to my knowledge) and unnecessary.

#### 🔐 Security

* Switched to [Snyk vulnerability scanner](https://github.com/snyk/actions/tree/master/maven-3-jdk-11) to limit false positives. Security vulnerabilities will now be published on the [GitHub repository's Security Advisories page](https://github.com/Ortus-Solutions/extension-hibernate/security/advisories).
* Bumped Lucee dependency to to remove vulnerability notices on [org.apache.tika:tika-core](https://security.snyk.io/vuln/SNYK-JAVA-ORGAPACHETIKA-2936441) and [commons-net:commons-net](https://security.snyk.io/vuln/SNYK-JAVA-COMMONSNET-3153503). These vulnerabilities are only theoretical, since Lucee is a dependency and not bundled with the extension.

### [6.0.0](https://github.com/Ortus-Solutions/extension-hibernate/compare/b86f26e383ead941d18791e2e008cb62b2598cdc...6.0.0) - 2023-07-01

#### ⭐ Added

**Second-Level Caching**

The extension will now throw an error if you try to configure an unsupported cache provider like , , etc. Previously, the extension would silently switch to ehcache if any cache provider besides EHCache was configured.

**Hibernate Logging**

This version re-enables Hibernate logging via SLF4j and LogBack. Hibernate root and cache loggers are defaulted to level, while SQL logging is set to if is enabled. (Set to .)

**OWASP Dependency CVE Scans**

The extension [GitHub Release page](https://github.com/Ortus-Solutions/extension-hibernate/releases/latest) now generates a dependency CVE report via [Jeremy Long's OWASP dependency-check maven plugin](https://jeremylong.github.io/DependencyCheck/index.html). Any known CVEs contained in dependencies ( excluding and -scoped dependencies) will be noted in [each release's CVE report artifact](https://github.com/Ortus-Solutions/extension-hibernate/releases/download/latest/owasp-cve-report.html).

#### ♻️ Changed

**New Repo Layout**

* Java source moved to
* All java classes are now under the package
* Dropped the java source format-on-push in favor of format-on-save IDE tooling

**New Test Layout**

* Internal tests rewritten to native Testbox specs
* Cloned all ORM tests from the Lucee repository
* Updated to TestBox 5.0

**New Build (and .jar file) Layout**

We re-architected the build to inline most dependencies. I.e. we no longer copy in extension dependencies as (custom-built) OSGI bundles, but instead as compiled classes.

* This resolves intermittent issues with bundle resolution and/or duplicate bundle collision upon installing the ORM extension into a Lucee server prior to uninstalling the Lucee Hibernate extension.
* This also removes a number of direct dependencies on custom OSGI bundles, thus it is more reliable and will offer easier dependency upgrades with less pain.

**Other**

* The attribute is deprecated in Hibernate 5.x, and is no longer generated on HBM/XML mapping files to avoid Hibernate warning that Use of DOM4J entity-mode is considered deprecated.

#### 🐛Fixed

* The definition file for all built-ins was missed during the conversion to a Maven build. (Since [v5.4.29.25](https://github.com/Ortus-Solutions/extension-hibernate/releases/tag/v5.4.29.25)). This caused the and built-in method calls to be picked up by Lucee core before being routed to this extension. No known errors resulted from this mistake, but we feel embarrassed anyway. 😅
* Clear ORM context data once per ORM reload, not once per ORM entity parsing. This should improve ORM startup/reload time and avoid difficult session or cache manager lifecycle issues.


# What's New With 5.x

Version 5.x release notes for the Ortus ORM Extension

### \[5.4.29.28] - 2023-06-07

#### 🐛 Fixed

We now set the JAXB system property based on the JRE version. If less than JRE 11, we set . If JRE 11 or greater, we set .

This prevents the following warning from being logged on each ORM method call:

```
WARNING: Using non-standard property: javax.xml.bind.context.factory. Property javax.xml.bind.JAXBContextFactory should be used instead.
```

See [OOE-3](https://ortussolutions.atlassian.net/browse/OOE-3).

### \[5.4.29.27] - 2023-05-29

#### 🐛 Fixed

* We now set a System property to ensure the JAXB API can find its implementation in CommandBox environments. This may trigger a log message, but shouldn't cause any concern. Vanilla Tomcat installations *may* need to overwrite or clear this property. [LDEV-4276](https://luceeserver.atlassian.net/browse/)

### \[5.4.29.26] - 2023-05-24

#### ♻️ Changed

* Improved logo for Lucee admin 🤩

#### 🐛 Fixed

* Entity changes made in and do not persist [OOE-2](https://ortussolutions.atlassian.net/browse/OOE-2)

### \[5.4.29.25] - 2023-05-23

#### ♻️ Changed

* Switched to Maven for a faster, more stable build process
* Improved entity event listeners for a much speedier ORM startup ([8924b58a9058d296e2a783ccfabbf90e26dc9c1b](https://github.com/Ortus-Solutions/extension-hibernate/commit/8924b58a9058d296e2a783ccfabbf90e26dc9c1b))
* New and Improved logo for Lucee admin visibility ([10bdf56a7a78f0221ab1a6e66a5512a92819e5b7](https://github.com/Ortus-Solutions/extension-hibernate/commit/10bdf56a7a78f0221ab1a6e66a5512a92819e5b7))

#### 🐛 Fixed

* Entity has no state when listener method (, for example) is fired ([014814263b5d31b8bac4c17479c2ca731ceb4e7c](https://github.com/Ortus-Solutions/extension-hibernate/commit/014814263b5d31b8bac4c17479c2ca731ceb4e7c), [OOE-1](https://ortussolutions.atlassian.net/browse/OOE-1))

### \[5.4.29.24] - 2023-05-17

#### 🔐 Security

* Upgraded dom4j library from 1.6.1 to 2.1.4. This removes [two potential vulnerabilities](https://mvnrepository.com/artifact/dom4j/dom4j/1.6.1) in dom4j's XML parsing capabilities.

### \[5.4.29.23] - 2023-05-15

#### 🐛 Fixed

* ORMExecuteQuery ignores argument if struct is passed

### \[5.4.29.22] - 2023-05-11

#### ⭐ Added

* Adds support for - [LDEV-3525](https://luceeserver.atlassian.net/browse/LDEV-3525)
* Adds javadocs auto-published to [apidocs.ortussolutions.com](https://apidocs.ortussolutions.com/#/lucee/hibernate-extension/)

#### 🐛 Fixed

* ORM events not firing ([LDEV-4308](https://luceeserver.atlassian.net/browse/LDEV-4308))
* Session close on transaction end ([LDEV-4017](https://luceeserver.atlassian.net/browse/LDEV-4017))
* length not used on varchar fields ([LDEV-4150](https://luceeserver.atlassian.net/browse/LDEV-4150))

#### ♻️ Changed

* Dramatic improvements in initialization performance
* Cuts ORM reload time by 60%
* Better build/test documentation
* Improved maintenance and build docs


# About This Book

More info on this documentation gitbook for the Ortus ORM Extension

The source code for this book is hosted in GitHub:

{% @github-files/github-code-block url="<https://github.com/ortus-docs/orm-extension>" %}

You can freely contribute to it and submit pull requests. The contents of this book is copyright by [Ortus Solutions, Corp](http://www.ortussolutions.com) and cannot be altered or reproduced without author's consent. All content is provided *"As-Is"* and can be freely distributed.

* The majority of code examples in this book are done in `cfscript`.
* The majority of code generation and running of examples are done via **CommandBox**: The ColdFusion (CFML) CLI, Package Manager, REPL - <https://www.ortussolutions.com/products/commandbox>​

## External Licensing

Both Lucee Server and Hibernate ORM are licensed under the LGPL v2.1.

## Notice of Liability <a href="#notice-of-liability" id="notice-of-liability"></a>

The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software and resources described in it.

## Contributing <a href="#contributing" id="contributing"></a>

We highly encourage contribution to this book and our open source software. The source code for this book can be found in our [GitHub repository](https://github.com/ortus-docs/orm-extension) where you can submit pull requests.

## Charitable Proceeds <a href="#charitable-proceeds" id="charitable-proceeds"></a>

10% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - [https://www.harvesting.org/](https://www.harvesting.org). So please donate and purchase the printed version of this book, every book sold can help a child for almost 2 months.

### Shalom Children's Home <a href="#shalom-childrens-home" id="shalom-childrens-home"></a>

{% embed url="<https://harvesting.org>" %}
[www.harvesting.org](http://www.harvesting.org)
{% endembed %}

**Shalom Children’s Home** is one of the ministries that is dear to our hearts located in El Salvador. During the 12 year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.

Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education and life skills training in a Christian environment. The home is supported by a child sponsorship program.

We have personally supported Shalom for over 6 years now; it is a place of blessing for many children in El Salvador that either have no families or have been abandoned. This is good earth to seed and plant.


# Installation

Get up and running in seconds!

## CommandBox

You can install this extension by adding the extension ID to the `lucee-extensions` environment variable and restarting the server:

<pre class="language-bash"><code class="lang-bash"><strong>box server set env.LUCEE_EXTENSIONS="D062D72F-F8A2-46F0-8CBC91325B2F067B" &#x26;&#x26; box restart
</strong></code></pre>

You can install a specific version by appending a version string to the extension ID:

```bash
box server set env.LUCEE_EXTENSIONS="D062D72F-F8A2-46F0-8CBC91325B2F067B;version=6.5.2" && box restart
```

(For all available version numbers, see our [Release History](/readme/release-history) or the [GitHub Releases page](https://github.com/Ortus-Solutions/extension-hibernate/releases).)

Running the `box server set env.lucee-extensions` command will edit your `server.json` file to look something like this:

{% code title="server.json" %}

```json
{
    // ...
    "env":{
        "LUCEE_EXTENSIONS":"D062D72F-F8A2-46F0-8CBC91325B2F067B;version=6.5.2"
    }
}
```

{% endcode %}

This config instructs Lucee (not CommandBox) to install the Ortus ORM Extension when Lucee starts up.

## From the Lucee Server Admin

You can manually install the extension by opening the Lucee server admin page and browsing to `Extension > Applications` page, where you'll see a "Ortus ORM Extension" option. Clicking this option will open the installation screen, where you can choose any extension version and click "Install" to install from Forgebox.

### Direct Download

You can also download a `.lex` file from [our downloads page](https://downloads.ortussolutions.com/#/ortussolutions/lucee-extensions/ortus-orm/) and upload this through the Lucee Server admin's Applications page.

### Don't Forget To Restart!

Whichever method you use to install the extension, we recommend restarting the server after installing.

Via CommandBox:

```
server restart
```


# Configuration

Easily configure Hibernate with CFML

### Application.cfc

The ORM can be configured by a struct of settings set in `this.ormSettings` in your main `Application.cfc`:

```js
component{
    this.ORMenabled = true;
    this.ormSettings = {
        // << Here Be ORM Configuration! 🤪 >>
    };
}
```

### ORM Settings

The full list of available properties you can use to configure the ORM are the following:

<table><thead><tr><th width="258">Setting Name</th><th width="128">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>autoGenMap</code></td><td><code>true</code></td><td>Specifies whether ColdFusion should automatically generate entity mappings for the persistent CFCs. If <code>autogenmap=false</code>, the mapping should be provided in the form of <code>.HBMXML</code> files.</td></tr><tr><td><code>autoManageSession</code></td><td><code>true</code></td><td>Allows the engine to manage the Hibernate session. It is recommended not to let the engine manage it for you.<br><br>Use <code>transaction</code> blocks in order to demarcate your regions that should start, flush and end a transaction.<br><br><a href="https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#transactions">https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#transactions</a></td></tr><tr><td><code>cacheConfig</code></td><td><code>true</code></td><td>Specifies the location of the configuration file that the secondary cache provider should use. This setting is used only when <code>secondaryCacheEnabled=true</code>. See <a href="#secondary-cache">Secondary Cache</a> below.</td></tr><tr><td><code>cacheProvider</code></td><td><code>"ehcache"</code></td><td><p>Specifies the cache provider that ORM should use as a secondary cache. The values can be:</p><ul><li><code>Ehcache</code></li><li><code>ConcurrentHashMap</code></li><li>The fully qualified name of the class for any other cache provider.</li></ul><p>See <a href="#secondary-cache">Secondary Cache</a> below.</p></td></tr><tr><td><code>catalog</code></td><td></td><td>Specifies the default Database Catalog that ORM should use.</td></tr><tr><td><code>cfclocation</code></td><td><code>empty</code></td><td><p>Specifies the directory (or array of directories) that should be used to search for persistent CFCs to generate the mapping.</p><p><strong>Always specify it or pay a performance startup price.</strong></p><p><strong>Important:</strong></p><p>If it is not set, the extension looks at the application directory, its sub-directories, and its mapped directories to search for persistent CFCs.</p></td></tr><tr><td><code>datasource</code></td><td><code>application.datasource</code></td><td>This setting defines the data source to be utilized by the ORM. If not used, defaults to the <code>this.datasource</code> in the <code>Application.cfc</code></td></tr><tr><td><code>dbcreate</code></td><td><code>none</code></td><td><ul><li><code>update</code> : Creates the database according to your ORM model. It only does incremental updates. It will never remove tables, indexes, etc.</li><li><code>dropcreate</code> : Same as above but it destroys the database if it has ny content and recreates it every time the ORM is reloaded.</li><li><code>none</code> : Does not change the database at all.</li></ul></td></tr><tr><td><code>dialect</code></td><td><code>autodiscover</code></td><td>The dialect to use for your database. By default Hibernate will introspect the datasource and try to figure it out. See the dialects section below.<br><br>You can also use the fully Java qualified name of the class.<br><br>See the <a href="#dialects">dialects</a> section below.</td></tr><tr><td><code>eventHandling</code></td><td><code>false</code></td><td>If true, then it enables the ORM event callbacks in entities and globally via the <code>eventHandler</code></td></tr><tr><td><code>eventHandler</code></td><td></td><td>The CFC path of the CFC that will manage the global ORM events.</td></tr><tr><td><code>flushAtRequestEnd</code></td><td><code>true</code></td><td>Specifies if an orm flush should be called automatically at the end of a request. In our opinion this SHOULD never be true. A database persistence should be done via <code>transaction</code> tags and good transaction demarcation.</td></tr><tr><td><code>logSQL</code></td><td><code>false</code></td><td>Specifies if the SQL queries should be logged to the console.</td></tr><tr><td><code>namingstrategy</code></td><td><code>default</code></td><td>Defines the naming convention to use on table and column names.<br><br>- <code>default</code> : Uses the table or column names as is<br>- <code>smart</code> : This strategy changes the logical table or column name to uppercase.<br>- <code>CFC PATH</code> : Use your own CFC to determine naming - see <a href="#custom-naming-strategy">Custom Naming Strategy</a>.</td></tr><tr><td><code>ormconfig</code></td><td></td><td>The path to a custom Hibernate configuration file:<br><br>- hibernate.properties<br>- hibernate.cfc.xml<br><br>Please see <a href="/pages/iTYLLR2JAMvV1EQDKnSV">Custom Hibernate Config</a></td></tr><tr><td><code>savemapping</code></td><td><code>false</code></td><td>If enabled, the ORM will create the Hibernate mapping XML (<code>*.hbmxml</code>) files alongside the entities. This is great for debugging your entities and relationships.</td></tr><tr><td><code>schema</code></td><td></td><td>The default database schema to use</td></tr><tr><td><code>secondaryCacheEnabled</code></td><td><code>false</code></td><td>Enable the secondary cache or not. See our <a href="/pages/CQe1XX6kGAn7sUJTEcwG">Caching</a> section.</td></tr><tr><td><code>skipCFCWithError</code></td><td><code>false</code></td><td>If <code>true</code>, then the ORM will ignore CFCs that have compile time errors in them. Use <code>false</code> to throw exceptions.</td></tr><tr><td><code>sqlScript</code></td><td></td><td>Path to a SQL script file that will be executed after the ORM is initialized. A great way to seed a database.</td></tr><tr><td><code>useDBForMapping</code></td><td><code>true</code></td><td><p>Specifies whether the database has to be inspected to identify the missing information required to generate the Hibernate mapping.</p><p>The database is inspected to get the column data type, primary key and foreign key information.</p></td></tr></tbody></table>

### Dialects

By using the `ormsettings.dialect` you can tell Hibernate which specific database dialect to use for building queries. By default, Hibernate tries to inspect the datasource and define it for you. 95% of the time, this works. However, if you want a specific one, then you can use the following names or a fully qualified Java class name.

<table><thead><tr><th width="238">Dialect (short name)</th><th>Remarks</th></tr></thead><tbody><tr><td>Cache71</td><td>Support for the Caché database, version 2007.1.</td></tr><tr><td>CockroachDB192</td><td>Support for the CockroachDB database version 19.2.</td></tr><tr><td>CockroachDB201</td><td>Support for the CockroachDB database version 20.1.</td></tr><tr><td>CUBRID</td><td>Support for the CUBRID database, version 8.3. May work with later versions.</td></tr><tr><td>DB2</td><td>Support for the DB2 database, version 8.2.</td></tr><tr><td>DB297</td><td>Support for the DB2 database, version 9.7.</td></tr><tr><td>DB2390</td><td>Support for DB2 Universal Database for OS/390, also known as DB2/390.</td></tr><tr><td>DB2400</td><td>Support for DB2 Universal Database for iSeries, also known as DB2/400.</td></tr><tr><td>DB2400V7R3</td><td>Support for DB2 Universal Database for i, also known as DB2/400, version 7.3</td></tr><tr><td>DerbyTenFive</td><td>Support for the Derby database, version 10.5</td></tr><tr><td>DerbyTenSix</td><td>Support for the Derby database, version 10.6</td></tr><tr><td>DerbyTenSeven</td><td>Support for the Derby database, version 10.7</td></tr><tr><td>Firebird</td><td>Support for the Firebird database</td></tr><tr><td>FrontBase</td><td>Support for the Frontbase database</td></tr><tr><td>H2</td><td>Support for the H2 database</td></tr><tr><td>HANACloudColumnStore</td><td>Support for the SAP HANA Cloud database column store.</td></tr><tr><td>HANAColumnStore</td><td>Support for the SAP HANA database column store, version 2.x. This is the recommended dialect for the SAP HANA database. May work with SAP HANA, version 1.x</td></tr><tr><td>HANARowStore</td><td>Support for the SAP HANA database row store, version 2.x. May work with SAP HANA, version 1.x</td></tr><tr><td>HSQL</td><td>Support for the HSQL (HyperSQL) database</td></tr><tr><td>Informix</td><td>Support for the Informix database</td></tr><tr><td>Ingres</td><td>Support for the Ingres database, version 9.2</td></tr><tr><td>Ingres9</td><td>Support for the Ingres database, version 9.3. May work with newer versions</td></tr><tr><td>Ingres10</td><td>Support for the Ingres database, version 10. May work with newer versions</td></tr><tr><td>Interbase</td><td>Support for the Interbase database.</td></tr><tr><td>JDataStore</td><td>Support for the JDataStore database</td></tr><tr><td>McKoi</td><td>Support for the McKoi database</td></tr><tr><td>Mimer</td><td>Support for the Mimer database, version 9.2.1. May work with newer versions</td></tr><tr><td>MySQL5</td><td>Support for the MySQL database, version 5.x</td></tr><tr><td>MySQL5InnoDB</td><td>Support for the MySQL database, version 5.x preferring the InnoDB storage engine when exporting tables.</td></tr><tr><td>MySQL57InnoDB</td><td>Support for the MySQL database, version 5.7 preferring the InnoDB storage engine when exporting tables. May work with newer versions</td></tr><tr><td>MariaDB</td><td>Support for the MariaDB database. May work with newer versions</td></tr><tr><td>MariaDB53</td><td>Support for the MariaDB database, version 5.3 and newer.</td></tr><tr><td>Oracle8i</td><td>Support for the Oracle database, version 8i</td></tr><tr><td>Oracle9i</td><td>Support for the Oracle database, version 9i</td></tr><tr><td>Oracle10g</td><td>Support for the Oracle database, version 10g</td></tr><tr><td>Pointbase</td><td>Support for the Pointbase database</td></tr><tr><td>PostgresPlus</td><td>Support for the Postgres Plus database</td></tr><tr><td>PostgreSQL81</td><td>Support for the PostgrSQL database, version 8.1</td></tr><tr><td>PostgreSQL82</td><td>Support for the PostgreSQL database, version 8.2</td></tr><tr><td>PostgreSQL9</td><td>Support for the PostgreSQL database, version 9. May work with later versions.</td></tr><tr><td>Progress</td><td>Support for the Progress database, version 9.1C. May work with newer versions.</td></tr><tr><td>SAPDB</td><td>Support for the SAPDB/MAXDB database.</td></tr><tr><td>SQLServer</td><td>Support for the SQL Server 2000 database</td></tr><tr><td>SQLServer2005</td><td>Support for the SQL Server 2005 database</td></tr><tr><td>SQLServer2008</td><td>Support for the SQL Server 2008 database</td></tr><tr><td>Sybase11</td><td>Support for the Sybase database, up to version 11.9.2</td></tr><tr><td>SybaseAnywhere</td><td>Support for the Sybase Anywhere database</td></tr><tr><td>SybaseASE15</td><td>Support for the Sybase Adaptive Server Enterprise database, version 15</td></tr><tr><td>SybaseASE157</td><td>Support for the Sybase Adaptive Server Enterprise database, version 15.7. May work with newer versions.</td></tr><tr><td>Teradata</td><td>Support for the Teradata database</td></tr><tr><td>TimesTen</td><td>Support for the TimesTen database, version 5.1. May work with newer versions</td></tr></tbody></table>

{% hint style="info" %}
See the Hibernate Dialect Section: <https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#database-dialect>
{% endhint %}

### Sample Config

Here is an example configuration from the popular ContentBox Modular CMS application

```cfscript
// THE CONTENTBOX DATASOURCE NAME
this.datasource  = "contentbox";
// ORM SETTINGS
this.ormEnabled  = true;
// cfformat-ignore-start
this.ormSettings = {
	// ENTITY LOCATIONS, ADD MORE LOCATIONS AS YOU SEE FIT
	cfclocation           : [
		// If you create your own app entities
		"models",
		// The ContentBox Core Entities
		"modules/contentbox/models",
		// Custom Module Entities
		"modules_app",
		// Custom Module User Entities
		"modules/contentbox/modules_user"
	],
	// THE DIALECT OF YOUR DATABASE OR LET HIBERNATE FIGURE IT OUT, UP TO YOU TO CONFIGURE.
	dialect              : request.$systemHelper.getSystemSetting( "ORM_DIALECT", "" ),
	// DO NOT REMOVE THE FOLLOWING LINE OR AUTO-UPDATES MIGHT FAIL.
	dbcreate             : "update",
	secondarycacheenabled: request.$systemHelper.getSystemSetting( "ORM_SECONDARY_CACHE", false ),
	cacheprovider        : request.$systemHelper.getSystemSetting( "ORM_SECONDARY_CACHE", "ehCache" ),
	logSQL               : request.$systemHelper.getSystemSetting( "ORM_LOGSQL", false ),
	sqlScript            : request.$systemHelper.getSystemSetting( "ORM_SQL_SCRIPT", "" ),
	// ORM SESSION MANAGEMENT SETTINGS, DO NOT CHANGE
	flushAtRequestEnd    : false,
	autoManageSession    : false,
	// ORM EVENTS MUST BE TURNED ON FOR CONTENTBOX TO WORK DO NOT CHANGE
	eventHandling        : true,
	eventHandler         : "cborm.models.EventHandler",
	// THIS IS ADDED SO OTHER CFML ENGINES CAN WORK WITH CONTENTBOX
	skipCFCWithError     : true,
	// TURN ON FOR Debugging if ORM mappings are not working.
	savemapping          : false
};
```

## Custom Naming Strategy

You can define your own naming convention for table and column names by pointing `this.ormSettings.namingStrategy` to a custom CFC path:

```js
this.ormSettings = {
	// ...
	namingStrategy : "models.orm.UnderscoreNamingStrategy"
}
```

The `UnderscoreNamingStrategy.cfc` component should then define two methods: `getTableName()` and `getColumnName()`:

```js
// models/orm/UnderscoreNamingStrategy.cfc
component{
	function getTableName( string tableName ){
		// funky table name conversion here...
	}

	function getColumnName( string columnName ){
		// funky column name conversion here...
	}
}
```


# Custom Hibernate Config

For full Hibernate configuration support, you can point the ORM extension to an XML file containing any configuration properties you wish to configure:

```js
this.ormSettings = {
    // ...
    ormconfig : "./config/persistence.xml"
};
```

You can then populate the XML file with valid Hibernate configuration syntax:

```xml
<!-- persistence.xml -->
<?xml version="1.0" encoding="UTF-8"?>    
<!DOCTYPE hibernate-configuration PUBLIC    
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"    
        "https://hibernate.org/dtd/hibernate-reverse-engineering-3.0.dtd">    
<hibernate-configuration>    
    <session-factory>    
    
    <!-- https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/cfg/AvailableSettings.html#USE_SQL_COMMENTS -->
    <property name="hibernate.use_sql_comments">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
         
    </session-factory>
</hibernate-configuration>
```


# Secondary Caches

Hibernate's secondary cache is a powerful tool that can greatly improve the performance of your application. By storing frequently accessed data in memory, the secondary cache can reduce the number of database queries that need to be made, resulting in faster response times and more efficient use of system resources. Whether you're working on a small project or a large enterprise application, the secondary cache is an essential part of any Hibernate-based system. So if you want to get the most out of your Hibernate application, take advantage of this powerful caching feature!

<figure><img src="/files/YgtXxBxoyT0jocBunM9q" alt=""><figcaption></figcaption></figure>

Please see the [caching section](/usage/caching) for all the wonderful caching strategies you can do with Hibernate.

### Configuration

A secondary cache provider is a class that manages a level of caching secondary to Hibernate's main caching context - the Hibernate session. A secondary cache enables longer-running cache contexts, more fine-grained control over cache busting, and other performance-related benefits.

The only setting necessary to enable secondary caching is the `secondaryCacheEnabled` setting:

```js
this.ormSettings = {
    secondaryCacheEnabled : true
};
```

To configure the caching, specify the path to an XML cache configuration file in `cacheConfig`:

```js
this.ormSettings = {
    secondaryCacheEnabled: true,
    cacheConfig          : "./config/ehcache.xml"
};
```

This `ehcache.xml` cache configuration then should look something like this:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" name="default">
    <diskStore path="java.io.tmpdir"/>
        <defaultCache
            maxElementsInMemory="10000" eternal="false"
            timeToIdleSeconds="120" timeToLiveSeconds="120"
            maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        </defaultCache>
        <cache
            name="Autos"
            maxElementsInMemory="20"
            overflowToDisk="false"
            eternal="true">
        </cache>
</ehcache>
```

### Alternate Cache Providers Are Unsupported

While there is a `cacheProvider` setting, only EHCache (currently) is supported as a secondary cache provider.

```js
this.ormSettings = {
    secondaryCacheEnabled : true,
    // NOT SUPPORTED!
    cacheProvider : "ConcurrentHashMap"
};
```

Thus, any usage of `cacheProvider` other than `"ehcache"` will be ignored.

Savepoints are not *currently* supported on ORM transactions.

{% hint style="info" %}
Looking for alternate cache providers? [Contact our Support team to consider sponsoring this feature](https://www.ortussolutions.com/products/orm-extension#support).
{% endhint %}


# Logging

How do Hibernate logs work in the Ortus ORM Extension?

## How can I configure/acquire Hibernate logging in the Ortus ORM Extension?

The Ortus ORM Extension reconfigures all Hibernate logging output on startup to log `ERROR`-level events to the server console.

## How can I configure/acquire Hibernate logging in the Lucee Hibernate Extension?

This depends on the version of Lucee you are running - specifically, on whether you're on Log4J 2 or not.

### Lucee versions running Log4J 1.x

Lucee versions containing the older log4j 1.x can use this code to set a custom logging level and redirect the Hibernate logs to the server console:

```
void function setupHibernateLogging( level = "WARN" ){
	var Logger       = createObject( "java", "org.apache.log4j.Logger" );
	var log4jLevel   = createObject( "java", "org.apache.log4j.Level" );
	var hibernateLog = Logger.getLogger( "org.hibernate" );
	// set a custom log level
	hibernateLog.setLevel( log4jLevel[ arguments.level ] );

	/**
	 * Redirect all Hibernate logs to system.out
	 */
	if ( listFindNoCase( "Lucee", server.coldfusion.productname ) ) {
		var printWriter     = getPageContext().getConfig().getOutWriter();
		var layout          = createObject( "java", "lucee.commons.io.log.log4j.layout.ClassicLayout" );
		var consoleAppender = createObject( "java", "lucee.commons.io.log.log4j.appender.ConsoleAppender" ).init(
			printWriter,
			layout
		);
		hibernateLog.addAppender( consoleAppender );
		writeDump( var = "** Lucee Hibernate Logging Redirected", output = "console" );
	}
}
```

### Lucee versions running Log4J 2.x

For versions of Lucee running log4j 2.x, the above workaround does not apply. If you are interested in tweaking the Hibernate logging level in the Lucee Hibernate extension, I would suggest [sponsoring this feature](https://www.ortussolutions.com/products/orm-extension#support) and future users can benefit from the shared knowledge.


# Entities

Learn the basics of modeling ORM entities

A persistent entity is a CFML component that is marked as a database entity via the `persistent` annotation upon the component definition:

```js
component persistent="true"{

}
```

By default, the entity name will be the CFC file name - minus the file extension, of course. We can modify the entity name via the `entityname` annotation:

```js
component persistent="true" entityname="Author" {

}
```

And the table name via the `table` annotation:

```js
component persistent="true" entityname="Author" table="authors" {

}
```

Here's the full list of available annotations for a persistent component:

<table data-full-width="true"><thead><tr><th width="235">Attribute</th><th width="111">Type</th><th width="107">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>persistent</code></td><td><code>boolean</code></td><td><code>false</code></td><td>Mark this component as an ORM entity</td></tr><tr><td><code>entityname</code></td><td><code>string</code></td><td></td><td>Set a custom entity name which is different than the CFC name</td></tr><tr><td><code>table</code></td><td><code>string</code></td><td></td><td>Specify the database table name</td></tr><tr><td><code>schema</code></td><td><code>string</code></td><td></td><td>Specify the database schema name.</td></tr><tr><td><code>catalog</code></td><td><code>string</code></td><td></td><td>Specify the database catalog name.</td></tr><tr><td><code>dynamicinsert</code></td><td></td><td></td><td>Specifies whether INSERT SQL is to be generated at runtime. Only those columns whose values are not null are included in the SQL.</td></tr><tr><td><code>dynamicinsert</code></td><td><code>boolean</code></td><td><code>false</code></td><td>Specifies whether INSERT SQL is to be generated at runtime. Only those columns whose values are not null are included in the SQL.</td></tr><tr><td><code>dynamicupdate</code></td><td><code>boolean</code></td><td><code>false</code></td><td>Specifies whether UPDATE SQL is to be generated at runtime. Only those columns whose values are not null are included in the SQL.</td></tr><tr><td><code>readonly</code></td><td><code>boolean</code></td><td><code>false</code></td><td>Specify whether table is readonly or not</td></tr><tr><td><code>selectbeforeupdate</code></td><td><code>boolean</code></td><td></td><td>Specify whether Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified. In cases when a transient object is associated with a new session using update(), Hibernate performs an extra SQL SELECT to determine if an UPDATE is actually required.</td></tr><tr><td><code>optimisticlock</code></td><td><code>string</code></td><td></td><td>Determines the locking strategy. It can be any one of: <code>all</code>,<code>dirty</code>,<code>version</code>,<code>none</code></td></tr><tr><td><code>batchsize</code></td><td><code>integer</code></td><td></td><td>An integer value that specifies the number of records to be retrieved at a single instance.</td></tr><tr><td><code>lazy</code></td><td><code>boolean</code></td><td><code>true</code></td><td>Whether loading is to be done lazily or not.</td></tr><tr><td><code>rowid</code></td><td><code>string</code></td><td></td><td>Specify the row id</td></tr><tr><td><code>discriminatorColumn</code></td><td><code>string</code></td><td></td><td>Use this attribute to define the discriminator column to be used in inheritance mapping</td></tr><tr><td><code>discriminatorValue</code></td><td><code>string</code></td><td></td><td>Use this attribute to define the discriminator value to be used in inheritance mapping</td></tr><tr><td><code>joinColumn</code></td><td><code>string</code></td><td></td><td>Define a join column for inheritance mapping</td></tr><tr><td><code>embedded</code></td><td><code>boolean</code></td><td></td><td>Marks CFC as embedded, used when a CFC has an embedded object which also needs to be persisted along with the parent's data</td></tr><tr><td><code>cacheUse</code></td><td><code>string</code></td><td></td><td>Specify the caching strategy to be used for caching this component's data in the secondary cache: <code>read-only</code></td></tr><tr><td><code>cacheName</code></td><td><code>string</code></td><td></td><td>Specify the name of the secondary cache</td></tr><tr><td><code>saveMapping</code></td><td><code>boolean</code></td><td><code>false</code></td><td>Specifies whether the generated Hibernate mapping file has to be saved to disk. If you set the value to true, the Hibernate mapping XML file is saved as <code>{CFC name}.hbm.xml</code> in the same directory as the CFC.</td></tr><tr><td><code>datasource</code></td><td><code>string</code></td><td></td><td>Name a specific datasource to persist this entity to.</td></tr></tbody></table>


# Identifiers

All about entity identifiers, from primary keys, and generators to composite keys and field types.

Identifier properties are denoted via `fieldtype="id"`.

We highly recommend disabling updates on identifier properties via `update="false"`:

```js
property name="id"
            fieldtype="id"
            ormtype="string"
            generator="assigned"
            update="false";
```

## Common Generator Types

### Assigned Generator

The Assigned generator is the default identifier generator type, and simply allows the application (your CFML) to assign identifier values prior to insertion. You can think of this as `generator=none`.

> lets the application assign an identifier to the object before save() is called. This is the default strategy if no element is specified. - [*Hibernate 3.3 mapping reference docs*](https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id-generator)

```js
property name="id"
            fieldtype="id"
            generator="assigned"
            update="false";
```

Assigned generators will commonly use [a `preInsert()` event listener](/usage/events#entity-event-handler) to assign the identifer value:

```js
function preInsert( entity ){
    setId( createUUID() );
}
```

### Select Generator

A select generator will attempt to select the next identifier value from the specified `selectKey` column:

> retrieves a primary key, assigned by a database trigger, by selecting the row by some unique key and retrieving the primary key value. - [*Hibernate 3.3 mapping reference docs*](https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id-generator)

```js
property name="userID"
            fieldtype="id"
            generator="select"
            selectKey="ssn"
            update="false";
```

### UUID Generator

The UUID generator uses Hibernate's uuid generator under the hood:

> uses a 128-bit UUID algorithm to generate identifiers of type string that are unique within a network (the IP address is used). The UUID is encoded as a string of 32 hexadecimal digits in length. - [*Hibernate 3.3 mapping reference docs*](https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id-generator)

```js
property name="userID"
            fieldtype="id"
            generator="uuid"
            update="false";
```

### Increment Generator

The Increment generator uses a simple incrementing value to create identifiers. Do not use in concurrent applications, as the values may no longer be unique.

> Generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster. - [*Hibernate 3.3 mapping reference docs*](https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id-generator)

```js
property name="userID"
            fieldtype="id"
            generator="increment"
            update="false";
```

#### Other Valid Generator Types

There are several lesser-known identifier generator types, including:

* `foreign` - use a foreign CFC's generator configuration
* `seqhilo`
* `sequence`
* `select` - select the next value from the column denoted in `selectKey`
* `uuid` - use Hibernate's UUID generation


# Properties

Entity properties are how we map table columns to CFML object values. You can specify an entity property by setting `persistent="true"` on any `property` inside a persistent CFML component:

```js
component persistent="true"{
    property name="name" type="string" persistent="true";
}
```

By default, all properties inside a `persistent=true` component are assumed to be persistent as well. Thus, we can skip the `persistent=true` annotation for brevity:

```js
component persistent="true"{
    property name="name" type="string";
}
```

## Common Property Annotations

| Attribute    | Type      | Description                                                                                                                           |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `persistent` | `boolean` | Define this property as a persistent property. If `false`, this property will be completely ignored in Hibernate / the ORM extension. |
| `name`       | `string`  | Property name                                                                                                                         |
| `default`    | `string`  | Default value for the property. This only reaches the CFML engine, and *does not affect creation of the entity table.*                |
| `column`     | `string`  | Table column where the property value is stored.                                                                                      |
| `dbDefault`  | `string`  | Set the default value for the property.                                                                                               |

Make sure you quote datetime `dbdefault` values to avoid invalid date errors in MySQL:

```js
property
    name     ="createdOn"
    ormtype  ="datetime"
    dbdefault="'2016-10-10'";
```

## Property Types

There are several "type" concepts and annotations you may need to use to keep the proper format when persisting or retrieving table data. While these may look similar, they are not equivalent.

| Attribute   | Examples                     | Description                                                                            |
| ----------- | ---------------------------- | -------------------------------------------------------------------------------------- |
| `type`      | `date`,`numeric`             | CFML data type                                                                         |
| `fieldtype` | `column`,`id`, `one-to-many` | Denote a special type of field, like an identifier or relationship field.              |
| `ormType`   | `big_decimal`,`timestamp`    | Data type for the database value.                                                      |
| `sqlType`   | `nvarchar`                   | A vendor-specific SQL type used for table creation only. This can normally be ignored. |

## Field Type

The `fieldtype` attribute allows you to define the behavior and purpose of this property:

```js
property
    name="userID"
    fieldtype="id"
    type="string";
```

There are several options for the `fieldtype` value:

* `column` - By far the most common, this is the default behavior of every field.
* `id` - Notes this field as the primary key or part of the a composite key.
* `collection` - Denote a collection of items - this could represent a struct, an array
* `version` - Denote a version field, useful for [optimistic locking](https://en.wikipedia.org/wiki/Optimistic_concurrency_control) on an entity
* `timestamp` - Denote a timestamp field
* `one-to-one` - Denote a [one-to-one relationship](/modeling/relationships#one-to-one)
* `one-to-many` - Denote a [one-to-many relationship](/modeling/relationships#one-to-many)
* `many-to-one` - Denote a [many-to-one relationship](/modeling/relationships#many-to-one)
* `many-to-many` - Denote a [many-to-many relationship](/modeling/relationships#many-to-many)
* `primary` - Not currently used.

## Generator Annotations

| Attribute   | Type               | Description                                                                                                        |
| ----------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |
| `generator` | `string`           | One of `increment`,`identity`,`native`,`seqhilo`,`uuid`,`guid`,`select`,`foreign`, `assigned`                      |
| `params`    | `struct`, `string` | `{ "table: "uuid_table", column: "uuid_value_column" }`                                                            |
| `sequence`  | `string`           |                                                                                                                    |
| `selectkey` | `string`           | Only used with `generator=select`. Specify the select key to use when selecting sequence values from the database. |
| `generated` | `string`           | `always`, `insert`, `never`.                                                                                       |

## Validation

| Attribute        | Type      | Description                                                                                                  |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------ |
| `insert`         | `boolean` | Allow inserting values to new rows.                                                                          |
| `update`         | `boolean` | Allow value updates on existing rows.                                                                        |
| `notnull`        | `boolean` | Specify a not-null constraint.                                                                               |
| `uniquekey`      | `string`  | Specify a key name for a unique constraint. Useful for defining a unique constraint across multiple columns. |
| `unique`         | `boolean` | Specify a unique constraint. Default `false`.                                                                |
| `validateParams` | `string`  | *Not currently supported*                                                                                    |
| `validate`       | `string`  | *Not currently supported*                                                                                    |

## Collection Modifiers

These property annotations are used when setting `fieldtype="collection"` and `collectiontype` is either `struct` or `map`.

| Attribute         | Type     | Description |
| ----------------- | -------- | ----------- |
| `structkeycolumn` | `string` |             |
| `structkeytype`   | `string` |             |
| `elementtype`     | `string` |             |
| `elementcolumn`   | `string` |             |

## Relationship Modifiers

| Attribute           | Type                      | Description                                                                                                                                                                                 |
| ------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `table`             | `string`                  | Define the table where the foreign items are stored.                                                                                                                                        |
| `lazy`              | `boolean`, `string`       | Define a lazy association retrieval type. One of `true`, `false`, `extra`.                                                                                                                  |
| `inverse`           | `boolean`                 | Specify that the association "owner" is referenced and managed on the opposite entity - not this current entity.                                                                            |
| `inversejoincolumn` | `string`                  | Specify the join column on the associated entity. For `inverse` associations only.                                                                                                          |
| `linkschema`        | `string`                  | Specify the schema name of the link table                                                                                                                                                   |
| `linkcatalog`       | `string`                  | Specify the catalog name of the link table                                                                                                                                                  |
| `linktable`         | `string`                  | Specify the name of the link table                                                                                                                                                          |
| `missingRowIgnored` | `boolean`                 | Do not throw an error if a foreign key has no match in the foreign entity                                                                                                                   |
| `fkcolumn`          | `string`                  |                                                                                                                                                                                             |
| `orderby`           | `string`                  |                                                                                                                                                                                             |
| `fetch`             | `string`                  |                                                                                                                                                                                             |
| `cascade`           | `string`                  |                                                                                                                                                                                             |
| `constrained`       | `boolean`                 | Only valid for `one-to-one` relationships. [See Hibernate 3.3 Mapping Documentation](https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-onetoone) |
| `optimisticLock`    | `boolean`                 | Enable optimistic locking on this association. One of `all`, `dirty`, `version`, `none`.                                                                                                    |
| `mappedby`          | `string`                  | Specify the property on the association that maps to this entity.                                                                                                                           |
| `cfc`               | `string`                  | Specify the CFC location of the foreign entity.                                                                                                                                             |
| `joinColumn`        | `string`                  | Join the foreign entity on this column in this entity.                                                                                                                                      |
| `where`             | `string`                  | Arbitrary SQL where clause for the relation.                                                                                                                                                |
| `singularname`      | *Not currently supported* |                                                                                                                                                                                             |

## Other

| Attribute      | Type      | Description                                                                                                                              |
| -------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `scale`        | `integer` |                                                                                                                                          |
| `length`       | `integer` |                                                                                                                                          |
| `precision`    | `integer` |                                                                                                                                          |
| `formula`      | `string`  | Define this property as a computed property by using a SQL query to determine the property value. Formula properties cannot be modified. |
| `index`        | `string`  | Key name for a property value index.                                                                                                     |
| `cacheUse`     | `string`  | Define a cache type to use for this property. One of `read-only`, `nonstrict-read-write`, `read-write`, or `transactional`.              |
| `cacheName`    | `string`  | Set the name of the cache to use for this property.                                                                                      |
| `unSavedValue` | `string`  | Set a value to use for newly instantiated objects.                                                                                       |

## Formula Property

```js
property name="totalPosts"
    ormType="integer"
    formula="(
        SELECT COUNT(*)
        FROM posts
        WHERE posts.FK_user = id
    )";
```

## Unsupported Attributes

{% hint style="info" %}
Looking for better support of a specific persistent attribute? [Contact our Support team to consider sponsoring this feature](https://www.ortussolutions.com/products/orm-extension#support).
{% endhint %}


# Relationships

Entity relationships let you define an association between two entity types.

## Relationships

Every relationship property must define the state of the relationship. In each case, the relationship property is defined in an entity which represents the "left" side of the relationship. If you bring a `Posts` relationship into the `User` entity, then from the `User` entity, the `User` is the left side of the relationship, and `Posts` is the right.

## One To One

A one to one relationship couples a single row on the left side to a single row on the right side:

```js
property name="Contact"
    fieldtype="one-to-one"
    cfc="Contact";
```

One to one relationships can be seen as simply extending the entity with additional information. Since there is no possibility of multiple records per entity instance, it may be worthwhile to set `lazy=false` to fetch the related entity along with any entity load:

```js
property name="Contact"
    fieldtype="one-to-one"
    cfc="Contact"
    lazy="false";
```

## One To Many

A one to many relationship couples a single row on the left side (the "one") to multiple rows on the right side (the "many"):

```js
component entityName="User" persistent="true"{
    property name="posts"
        fieldtype="one-to-many"
        cfc="Post";
}
```

You'll normally want to set `lazy="true"` to (for example) avoid fetching every Post on a User:

```js
property name="posts"
    fieldtype="one-to-many"
    cfc="Post"
    lazy="true";
```

## Many To One

A many to one relationship couples multiple rows on the left side (the "many") to a single row on the right side( the "one"):

```js
component entityName="Post" persistent="true"{
    property name="Authors"
        fieldtype="many-to-one"
        cfc="User";
}
```

Thus, a single Post can have only one Author... but an author (or a User, really) can have many Posts.

## Many To Many

A many to many relationship allows each entity to relate to multiple rows on the opposite side. A good example might be a blog which allows multiple authors for a single blog post. Each blog post can then have multiple authors, and each author has (likely) written multiple blog posts:

```js
component entityName="User" persistent="true"{
    property name="posts"
        fieldtype="many-to-many"
        cfc="Post"
        linktable="user_posts_link";
}
```

The `linktable` attribute is required on a `many-to-many` property to set the locationfor storing join records. You can further alter the storage location via `linkschema` and `linkcatalog`:

```js
property name="posts"
    fieldtype="many-to-many"
    cfc="Post";
    linkschema="blog"
    linkcatalog="dbo";
```

### Singular Name

On many\* relationships like `one-to-many`, `many-to-one`, etc., you'll be manipulating the full set of items via the property name: `hasAuthors()`, `setAuthors()`, etc. However, this plural terminology becomes weird when used on a single item addition or removal, such as `addAuthors( Author )`. For this reason, you can define a `singularName=STRING` attribute to clean up your entity manipulation:

```js
property name="Authors"
    singularName="Author"
    fieldtype="many-to-one"
    cfc="User";
```

### Lazy

Man, you wanna get lazy? How about don't-fetch-the-data-until-you-need-it kinda lazy?

Using `lazy=true`, we can tell Hibernate not to fetch the relational data *unless* and *until* a method call such as `Authors()` attempts to load it. This greatly improves performance on page requests which do not need that particular data:

```js
property name="posts"
    fieldtype="one-to-many"
    cfc="Post"
    lazy="true";
```

We can also use `lazy=extra` to only retrieve the rows that we touch. This may work well if we commonly only access a few rows out of the full set of child items:

```js
property name="posts"
    fieldtype="one-to-many"
    cfc="Post"
    lazy="extra";
```

### Relationship Methods

{% hint style="info" %}
This section is missing documentation - would you care to [add it yourself](https://quick.ortusbooks.com/6.2.0/guide/relationships/relationship-types/belongsto)?
{% endhint %}


# Built-In Functions

The Ortus ORM Extension offers a number of CFML functions for loading and manipulating entities as well as managing the ORM session:

* [Built-In Functions](#built-in-functions)
  * [EntityDelete](#entitydelete)
  * [EntityLoad](#entityload)
  * [EntityLoadByExample](#entityloadbyexample)
  * [EntityLoadByPK](#entityloadbypk)
  * [EntityMerge](#entitymerge)
  * [EntityNameArray](#entitynamearray)
  * [EntityNameList](#entitynamelist)
  * [EntityNew](#entitynew)
  * [EntityReload](#entityreload)
  * [EntitySave](#entitysave)
  * [EntityToQuery](#entitytoquery)
  * [IsValidDatasource](#isvaliddatasource)
  * [ORMClearSession](#ormclearsession)
  * [ORMCloseAllSessions](#ormcloseallsessions)
  * [ORMCloseSession](#ormclosesession)
  * [ORMEvictCollection](#ormevictcollection)
  * [ORMEvictEntity](#ormevictentity)
  * [ORMEvictQueries](#ormevictqueries)
  * [ORMExecuteQuery](#ormexecutequery)
  * [ORMFlush](#ormflush)
  * [ORMGetSession](#ormgetsession)
  * [ORMGetSessionFactory](#ormgetsessionfactory)
  * [ORMQueryExecute](#ormqueryexecute)
  * [ORMReload](#ormreload)

## EntityDelete

`EntityDelete` allows you to delete the row associated with an instantiated entity from the database:

```js
entityDelete( myEntity );
```

Only a single argument is accepted - the entity to delete - and the deletion is not persisted until the session is flushed.

```js
entityDelete( myEntity );
// entity (row) still exists in the database.
ormFlush();
// entity (row) is now wiped from the database.
```

**Returns: `null`**

## EntityLoad

**Returns: `Array`|`Component`|`null`**

## EntityLoadByExample

**Returns: `Array`|`Component`|`null`**

## EntityLoadByPK

`EntityLoadByPK()` allows you to instantiate an entity using the row identified by a primary key:

```js
var theUser = entityLoadByPk( "User", url.userID );
```

A third argument, `unique`, is documented *but not implemented* in either the Lucee Hibernate extension or the Ortus ORM Extension.

**Returns: `Component`|`null`**

## EntityMerge

`EntityMerge()` will merge a "detached" entity (meaning, not connected to any open session) back into the session.

For example, running `ormClearSession()` will detach all loaded entities from the session. If you then make changes to an entity via a setter and run `ormFlush()`, those entity modifications will not be persisted unless you first merge the entity back to the session:

```js
var detachedAutoEntity = entityLoadByPK( "Auto", "12345" );

// make a change but don't save it
detachedAutoEntity.setModel( "Fusion" );

// clear session - will "detach" the entity
ormClearSession();

// "merge" it back to the session
var merged = entityMerge( detachedAutoEntity );

// changes should be reflected in the new entity
expect( merged.getModel() ).toBe( "Fusion" );
```

**Returns: `Component`**

## EntityNameArray

`EntityNameArray()` returns an array of all mapped entity names for the CFML application:

```js
var entityTypes = entityNameArray();
```

EntityNameArray accepts no arguments.

**Returns: `Array`**

## EntityNameList

True to its name, EntityNameList returns a string list of all mapped entity names for the CFML application:

```js
var entityTypes = entityNameList();
```

You can pass a string delimiter value as the first argument, if you don't like commas:

```js
var entityTypes = entityNameList( "|" );
```

**Returns: `string`**

## EntityNew

The `entityNew()` method allows you to create a new instance of a known entity type:

```js
var myCar = entityNew( "Auto" );
```

You can also pass a struct of properties to populate into the entity:

```js
var myCar = entityNew( "Auto", {
  make : "Ford",
  model : "Fusion",
  id : createUUID()
} );
```

Note that if you try to populate a property which does not exist, you will get an error:

```js
var myCar = entityNew( "Auto", {
    make : "Ford",
    model : "Fusion",
    propThatDoesntExist : "abc"
} );
```

This will throw an error: `component [Auto] has no function with name [setPROPTHATDOESNTEXIST]`

**Returns: `Component`**

## EntityReload

`entityReload()` will reload or refresh the entity state from the database. Local, unpersisted modifications will be replaced with database values.

Here's a quick example:

```js
var myCar = entityLoadByPK( "Auto", "12345" );

// make a change but don't save it
myCar.setModel( "Revuelto" );

// reload the entity
entityReload( myCar );

// our local changes should be replaced with the DB value
expect( myCar.getModel() ).toBe( "Aventador" );
```

**Returns: `null`**

## EntitySave

`EntitySave()` is how you save entity modifications. The changes will not persist to the database until `ormFlush()` is called:

```js
var myCar = entityNew( "Auto", {
  make : "Ford",
  model : "Fusion",
  id : createUUID()
} );
entitySave( myCar );
ormFlush();
```

EntitySave accepts an optional boolean parameter, `forceInsert`, which will tell Hibernate to skip the entity existence check and insert the entity:

```js
var myCar = entityNew( "User", {
  username : "Johnny.Appleseed",
  password : "McinT0sh"
} );
entitySave( myCar, true );
```

Most of the time this will be unnecessary.

**Returns: `null`**

## EntityToQuery

**Returns: `Query`**

## IsValidDatasource

**Returns: `Boolean`**

## ORMClearSession

**Returns: `null`**

## ORMCloseAllSessions

**Returns: `null`**

## ORMCloseSession

**Returns: `null`**

## ORMEvictCollection

**Returns: `null`**

## ORMEvictEntity

**Returns: `null`**

## ORMEvictQueries

**Returns: `null`**

## ORMExecuteQuery

**Returns: `Array`|`Struct`|`any`**

## ORMFlush

**Returns: `null`**

## ORMGetSession

**Returns: `Session`**

## ORMGetSessionFactory

**Returns: `SessionFactory`**

## ORMQueryExecute

Alias for `ORMExecuteQuery()`.

Added in `v6.4.0` (unreleased, version number subject to change.) - [5600833](https://github.com/Ortus-Solutions/extension-hibernate/commit/5600833a78f432dc07618895b65b0f3da46474b1)

**Returns: `Array`|`Struct`|`any`**

## ORMReload

**Returns: `null`**


# Querying

{% hint style="info" %}
This page is missing documentation - would you care to [add it yourself](https://github.com/ortus-docs/orm-extension/blob/master/usage/querying.md)?
{% endhint %}


# Events

Easily run actions on entity insertion, update, and more with event listeners

Hibernate ORM allows reacting to various events in the session lifecycle such as `onPreInsert`, `onPostUpdate`, `onFlush`, etc. You can enable event handling in CFML by setting `eventHandling` to `true` in your `this.ormSettings` struct:

```js
this.ormSettings = {
    eventHandling: true
};
```

This will enable two different event listener types for listening to Hibernate events:

* Listen to all events across all entities via the [global event handler](#global-event-handler)
* Listen to specific events on a specific entity via [entity event handler](#entity-event-handler) methods

## Global Event Handler

To use a global event handler, you must set a path to the global event handler using the `eventHandler` setting:

```js
this.ormSettings = {
    eventHandling: true,
    eventHandler : "path/to/global/EventHandler.cfc"
};
```

The `EventHandler.cfc` must then contain function definitions matching the ORM events you wish to listen for.

Currently, the available event names are:

* `onFlush`
* `preLoad`
* `postLoad`
* `preInsert`
* `postInsert`
* `preUpdate`
* `postUpdate`
* `preDelete`
* `onDelete`
* `postDelete`
* `onEvict`
* `onClear`
* `onDirtyCheck`
* `onAutoFlush`

Here's an example of an EventHandler configured for all events:

```js
component {

	public component function init(){
		return this;
	}

	function onFlush( entity ) {
		// Do something upon function call
	}

	function preLoad( entity ){
		// Do something upon function call
	}
	function postLoad( entity ){
		// Do something upon function call
	}

	function preInsert( entity ){
		// Do something upon function call
	}
	function postInsert( entity ){
		// Do something upon function call
	}

	function preUpdate( entity, Struct oldData  ){
		// Do something upon function call
	}
	function postUpdate( entity ){
		// Do something upon function call
	}

	function preDelete( entity ){
		// Do something upon function call
	}	
	function onDelete( entity ) {
		// Do something upon function call
	}
	function postDelete( entity ) {
		// Do something upon function call
	}

	function onEvict() {
		// Do something upon function call
	}
	function onClear( entity ) {
		// Do something upon function call
	}
	function onDirtyCheck( entity ) {
		// Do something upon function call
	}
	function onAutoFlush( entity ) {
		// Do something upon function call
	}
}
```

## Entity Event Handler

You can also listen to events on a specific entity at the entity level by adding methods to the entity (component) itself:

```js
component persistent="true"{
	function preInsert( entity ){
		setDateCreated( now() );
	}
	function preUpdate( entity ){
		setDateModified( now() );
	}
}
```

{% hint style="info" %}
Note that only events related to a specific entity will fire upon that entity. For example, you cannot listen to `onFlush` in an entity event handler because a flush is not tied to any one entity.
{% endhint %}

Here is the full list of event types which can be listened to in entity event listeners:

* `preLoad`
* `postLoad`
* `preInsert`
* `postInsert`
* `preUpdate`
* `postUpdate`
* `preDelete`
* `onDelete`
* `postDelete`


# Session Management

{% hint style="info" %}
This page is missing documentation - would you care to [add it yourself](https://github.com/ortus-docs/orm-extension/blob/master/usage/session-management.md)?
{% endhint %}


# HQL

{% hint style="info" %}
This page is missing documentation - would you care to [add it yourself](https://github.com/ortus-docs/orm-extension/blob/master/usage/hql.md)?
{% endhint %}


# Transactions

Learn transaction management with the ORM Extension

A transaction is any discrete unit of work used to pool database queries and statements to execute at once. This helps us to prevent a failed update from leaving the database in a broken state.

To denote a transaction, we wrap it in the `transaction{}` tag:

```js
transaction{
    // queries go here
}
```

The transaction will automatically commit (persist) at the end of the transaction block.

## Transaction Rollback

{% hint style="info" %}
This section is missing documentation - would you care to [add it yourself](https://github.com/ortus-docs/orm-extension/blob/master/usage/transactions.md)?
{% endhint %}

## Transaction Commit

{% hint style="info" %}
This section is missing documentation - would you care to [add it yourself](https://github.com/ortus-docs/orm-extension/blob/master/usage/transactions.md)?
{% endhint %}

## Transaction Savepoint

Savepoints are not *currently* supported on ORM transactions.

{% hint style="info" %}
Looking for ORM savepoint support? [Contact our Support team to consider sponsoring this feature](https://www.ortussolutions.com/products/orm-extension#support).
{% endhint %}


# Caching

Improve your database performance with secondary caching in Hibernate ORM.

## Secondary Cache

A secondary cache provider is a class which manages a level of caching that is secondary to Hibernate's main caching context - the Hibernate session. A secondary cache enables longer-running cache contexts, more fine-grained control over cache busting, and other performance-related benefits.

The only setting necessary to enable secondary caching is the `secondaryCacheEnabled` setting:

```js
this.ormSettings = {
    secondaryCacheEnabled : true
};
```

To configure the caching, specify the path to an XML cache configuration file in `cacheConfig`:

```js
this.ormSettings = {
    secondaryCacheEnabled: true,
    cacheConfig          : "./config/ehcache.xml"
};
```

This `ehcache.xml` cache configuration then should look something like this:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" name="default">
    <diskStore path="java.io.tmpdir"/>
        <defaultCache
            maxElementsInMemory="10000" eternal="false"
            timeToIdleSeconds="120" timeToLiveSeconds="120"
            maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        </defaultCache>
        <cache
            name="Autos"
            maxElementsInMemory="20"
            overflowToDisk="false"
            eternal="true">
        </cache>
</ehcache>
```

## Configure Each Entity Cache

Notice how our `ehcache.xml` defines a default cache configuration?

```xml
<defaultCache
    maxElementsInMemory="10000" eternal="false"
    timeToIdleSeconds="120" timeToLiveSeconds="120"
    maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU">
    <persistence strategy="localTempSwap"/>
</defaultCache>
```

We highly recommend adding a cache configuration for each cacheable entity. This will help you optimize caching, and will silence error logs like the below:

```
WARN: HHH90001006: Missing cache[default-update-timestamps-region] was created on-the-fly. The created cache will use a provider-specific default configuration: make sure you defined one. You can disable this warning by setting 'hibernate.cache.ehcache.missing_cache_strategy' to 'create'
```

Here's a quick example. Say we have an `Autos.cfc` persistent component with caching enabled:

```js
component persistent="true" cacheUse="true"{
    // persistent properties...
}
```

For this entity, we'll want to create a `<cache></cache>` entry with a `name` attribute that matches the entity name OR our `cacheName` component annotation:

```xml
<cache
    name="Autos"
    maxElementsInMemory="20"
    overflowToDisk="false"
    eternal="true">
</cache>
```

### Alternate Cache Providers Are Unsupported

While there is a `cacheProvider` setting, only EHCache (currently) is supported as a secondary cache provider.

```js
this.ormSettings = {
    secondaryCacheEnabled : true,
    // NOT SUPPORTED!
    cacheProvider : "ConcurrentHashMap"
};
```

Thus, any usage of `cacheProvider` other than `"ehcache"` will be ignored.


