////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////

You saw in an earlier section that you can use composition (with the `embedded` property) to break a table into multiple objects. You can achieve a similar effect with Hibernate's custom user types. These are not domain classes themselves, but plain Java or Groovy classes. Each of these types also has a corresponding "meta-type" class that implements https://docs.jboss.org/hibernate/orm/5.6/javadocs/org/hibernate/usertype/UserType.html[org.hibernate.usertype.UserType].

The https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#_custom_type[Hibernate reference manual] has some information on custom types, but here we will focus on how to map them in GORM. Let's start by taking a look at a simple domain class that uses an old-fashioned (pre-Java 1.5) type-safe enum class:

[source,groovy]
----
class Book {

    String title
    String author
    Rating rating

    static mapping = {
        rating type: RatingUserType
    }
}
----

All we have done is declare the `rating` field the enum type and set the property's type in the custom mapping to the corresponding `UserType` implementation. That's all you have to do to start using your custom type. If you want, you can also use the other column settings such as "column" to change the column name and "index" to add it to an index.

Custom types aren't limited to just a single column - they can be mapped to as many columns as you want. In such cases you explicitly define in the mapping what columns to use, since Hibernate can only use the property name for a single column. Fortunately, GORM lets you map multiple columns to a property using this syntax:

[source,java]
----
class Book {

    String title
    Name author
    Rating rating

    static mapping = {
        author type: NameUserType, {
            column name: "first_name"
            column name: "last_name"
        }
        rating type: RatingUserType
    }
}
----

The above example will create "first_name" and "last_name" columns for the `author` property. You'll be pleased to know that you can also use some of the normal column/property mapping attributes in the column definitions. For example:

[source,java]
----
column name: "first_name", index: "my_idx", unique: true
----

The column definitions do _not_ support the following attributes: `type`, `cascade`, `lazy`, `cache`, and `joinTable`.

One thing to bear in mind with custom types is that they define the _SQL types_ for the corresponding database columns. That helps take the burden of configuring them yourself, but what happens if you have a legacy database that uses a different SQL type for one of the columns? In that case, override the column's SQL type using the `sqlType` attribute:

[source,java]
----
class Book {

    String title
    Name author
    Rating rating

    static mapping = {
        author type: NameUserType, {
            column name: "first_name", sqlType: "text"
            column name: "last_name", sqlType: "text"
        }
        rating type: RatingUserType, sqlType: "text"
    }
}
----

Mind you, the SQL type you specify needs to still work with the custom type. So overriding a default of "varchar" with "text" is fine, but overriding "text" with "yes_no" isn't going to work.
