<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<chapter xml:id="identifiers"
         version="5.0"
         xml:lang="en"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xi="http://www.w3.org/2001/XInclude">

    <info>
        <title>Identifiers</title>
        <abstract>
            <para>
                This chapter discusses the characteristics of entity identifier attributes and modelling
                them.
            </para>
        </abstract>
    </info>

    <para>
        Identifiers model the primary key of an entity.  They are used to uniquely identify each specific entity.
    </para>

    <para>
        Hibernate and JPA both make the following assumptions about the corresponding database column(s):
        <itemizedlist>
            <listitem>
                <para>
                    <literal>UNIQUE</literal> - The values must uniquely identify each row.
                </para>
            </listitem>
            <listitem>
                <para>
                    <literal>NOT NULL</literal> - The values cannot be null.  For composite ids, no part can be null.
                </para>
            </listitem>
            <listitem>
                <para>
                    <literal>IMMUTABLE</literal> - The values, once inserted, can never be changed.  This is more
                    a general guide, than a hard-fast rule as opinions vary.  JPA defines the behavior of changing the
                    value of the identifier attribute to be undefined; Hibernate simply does not support that.  In cases
                    where the values for the PK you have chosen will be updated, Hibernate recommends mapping the
                    mutable value as a natural id, and use a surrogate id for the PK.  See <xref linkend="naturalid"/>.
                </para>
            </listitem>
        </itemizedlist>
    </para>

    <note>
        <para>
            Technically the identifier does not have to map to the column(s) physically defined as the entity
            table's primary key.  They just need to map to column(s) that uniquely identify each row.  However
            this documentation will continue to use the terms identifier and primary key interchangeably.
        </para>
    </note>

    <para>
        Every entity must define an identifier.  For entity inheritance hierarchies, the identifier must be
        defined just on the entity that is the root of the hierarchy.
    </para>

    <para>
        An identifier might be simple (single value) or composite (multiple values).
    </para>

    <section xml:id="identifiers-simple">
        <title>Simple identifiers</title>
        <para>
            Simple identifiers map to a single basic attribute, and are denoted using the
            <interfacename>javax.persistence.Id</interfacename> annotation.
        </para>

        <para>
            According to JPA only the following types should be used as identifier attribute types:
            <itemizedlist>
                <listitem><para>any Java primitive type</para></listitem>
                <listitem><para>any primitive wrapper type</para></listitem>
                <listitem><para>java.lang.String</para></listitem>
                <listitem><para>java.util.Date (TemporalType#DATE)</para></listitem>
                <listitem><para>java.sql.Date</para></listitem>
                <listitem><para>java.math.BigDecimal</para></listitem>
                <listitem><para>java.math.BigInteger</para></listitem>
            </itemizedlist>
            Any types used for identifier attributes beyond this list will not be portable.
        </para>

        <para>
            Values for simple identifiers can be assigned, as we have seen in the examples above.  The expectation
            for assigned identifier values is that the application assigns (sets them on the entity attribute) prior
            to calling save/persist.
        </para>

        <example>
            <title>Simple assigned identifier</title>
            <programlisting role="JAVA"><xi:include href="extras/SimpleAssigned.java" parse="text" /></programlisting>
        </example>

        <para>
            Values for simple identifiers can be generated.  To denote that an identifier attribute is
            generated, it is annotated with <interfacename>javax.persistence.GeneratedValue</interfacename>
        </para>

        <example>
            <title>Simple generated identifier</title>
            <programlisting role="JAVA"><xi:include href="extras/SimpleGenerated.java" parse="text" /></programlisting>
        </example>

        <para>
            Additionally to the type restriction list above, JPA
            says that if using generated identifier values (see below) only integer types (short, int, long) will be
            portably supported.
        </para>

        <para>
            The expectation for generated identifier values is that Hibernate will generate the value
            when the save/persist occurs.
        </para>

        <para>
            Identifier value generations strategies are discussed in detail in <xref linkend="identifiers-generators"/>.
        </para>
    </section>

    <section xml:id="identifiers-composite">
        <title>Composite identifiers</title>

        <para>
            Composite identifiers correspond to one or more persistent attributes.  Here are the rules governing
            composite identifiers, as defined by the JPA specification.
            <itemizedlist>
                <listitem>
                    <para>
                        The composite identifier must be represented by a "primary key class".  The primary key class
                        may be defined using the <interfacename>javax.persistence.EmbeddedId</interfacename> annotation
                        (see <xref linkend="identifiers-composite-aggregated"/>) or defined using the
                        <interfacename>javax.persistence.IdClass</interfacename> annotation (see
                        <xref linkend="identifiers-composite-nonaggregated"/>).
                    </para>
                </listitem>
                <listitem>
                    <para>
                        The primary key class must be public and must have a public no-arg constructor.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        The primary key class must be serializable.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        The primary key class must define equals and hashCode methods, consistent with equality for
                        the underlying database types to which the key is mapped.
                    </para>
                </listitem>
            </itemizedlist>
        </para>

        <note>
            <para>
                The restriction that a composite identifier has to be represented by a "primary key class" is
                a JPA restriction.  Hibernate does allow composite identifiers to be defined without a
                "primary key class", but use of that modeling technique is deprecated and not discussed here.
            </para>
        </note>

        <para>
            The attributes making up the composition can be either basic, composite, ManyToOne.  Note especially
            that collections and one-to-ones are never appropriate.
            <!-- todo : discuss why a real one-to-one is never appropriate? -->
        </para>

        <section xml:id="identifiers-composite-aggregated">
            <title>Composite identifiers - aggregated (EmbeddedId)</title>

            <para>
                Modelling a composite identifier using an EmbeddedId simply means defining an
                Embeddable to be a composition for the the one or more attributes making up the
                identifier and then exposing an attribute of that Embeddable type on the entity.
            </para>

            <example>
                <title>Basic EmbeddedId</title>
                <programlisting role="JAVA"><xi:include href="extras/EmbeddedId1.java" parse="text" /></programlisting>
            </example>

            <para>
                As mentioned before, EmbeddedIds can even contain ManyToOne attributes.
            </para>

            <example>
                <title>EmbeddedId with ManyToOne</title>
                <programlisting role="JAVA"><xi:include href="extras/EmbeddedId2.java" parse="text" /></programlisting>
            </example>

            <note>
                <para>
                    Hibernate supports directly modeling the ManyToOne in the PK class, whether EmbeddedId or IdClass.
                    However that is not portably supported by the JPA specification.  In JPA terms one would
                    use "derived identifiers"; for details, see <xref linkend="identifiers-derived"/>.
                </para>
            </note>
        </section>

        <section xml:id="identifiers-composite-nonaggregated">
            <title>Composite identifiers - non-aggregated (IdClass)</title>

            <para>
                Modelling a composite identifier using an IdClass differs from using an EmbeddedId in that the entity
                defines each individual attribute making up the composition.  The IdClass simply acts as a "shadow".
            </para>

            <example>
                <title>Basic IdClass</title>
                <programlisting role="JAVA"><xi:include href="extras/IdClass1.java" parse="text" /></programlisting>
            </example>

            <para>
                Non-aggregated composite identifiers can also contain ManyToOne attributes as we saw with aggregated
                ones (still non-portably)
            </para>

            <example>
                <title>IdClass with ManyToOne</title>
                <programlisting role="JAVA"><xi:include href="extras/IdClass2.java" parse="text" /></programlisting>
            </example>

            <para>
                With non-aggregated composite identifiers, Hibernate also supports "partial" generation of the
                composite values.
            </para>

            <example>
                <title>IdClass with partial generation</title>
                <programlisting role="JAVA"><xi:include href="extras/IdClass3.java" parse="text" /></programlisting>
            </example>

            <note>
                <para>
                    This feature exists because of a highly questionable interpretation of the JPA specification
                    made by the SpecJ committee.  Hibernate does not feel that JPA defines support for this, but
                    added the feature simply to be usable in SpecJ benchmarks.  Use of this feature may or may not
                    be portable from a JPA perspective.
                </para>
            </note>
        </section>

    </section>

    <section xml:id="identifiers-generators">
        <title>Generated identifier values</title>

        <!-- todo : discuss select generator -->

        <note>
            <para>
                For discussion of generated values for non-identifier attributes, see <xref linkend="generated"/>
            </para>
        </note>

        <para>
            Hibernate supports identifier value generation across a number of different types.  Remember
            that JPA portably defines identifier value generation just for integer types.
        </para>

        <para>
            Identifier value generation is indicates using the <interfacename>javax.persistence.GeneratedValue</interfacename>
            annotation.  The most important piece of information here is the specified
            <interfacename>javax.persistence.GenerationType</interfacename> which indicates how values will be generated.
        </para>

        <note>
            <para>
                The discussions below assume that the application is using Hibernate's "new generator mappings" as
                indicated by the <literal>hibernate.id.new_generator_mappings</literal> setting or
                <methodname>MetadataBuilder.enableNewIdentifierGeneratorSupport</methodname> method during bootstrap.
                This is set to true by default, however if applications set this to false the resolutions discussed
                here will be very different.  The rest of the discussion here assumes this setting is enabled (true).
            </para>
        </note>

        <itemizedlist>
            <title>GenerationTypes</title>
            <listitem>
                <para>
                    <literal>AUTO</literal> (the default) - Indicates that the persistence provider (Hibernate) should
                    chose an appropriate generation strategy.  See <xref linkend="identifiers-generators-auto"/>.
                </para>
            </listitem>
            <listitem>
                <para>
                    <literal>IDENTITY</literal> - Indicates that database IDENTITY columns will be used for
                    primary key value generation.  See <xref linkend="identifiers-generators-identity"/>.
                </para>
            </listitem>
            <listitem>
                <para>
                    <literal>SEQUENCE</literal> - Indicates that database sequence should be used for obtaining
                    primary key values.   See <xref linkend="identifiers-generators-sequence"/>.
                </para>
            </listitem>
            <listitem>
                <para>
                    <literal>TABLE</literal> - Indicates that a database table should be used for obtaining
                    primary key values.   See <xref linkend="identifiers-generators-table"/>.
                </para>
            </listitem>
        </itemizedlist>

        <section xml:id="identifiers-generators-auto">
            <title>Interpreting AUTO</title>

            <para>
                How a persistence provider interprets the AUTO generation type is left up to the provider.  Hibernate
                interprets it in the following order:
                <itemizedlist>
                    <listitem>
                        <para>
                            If the given name matches the name for a <interfacename>javax.persistence.SequenceGenerator</interfacename>
                            annotation -> <xref linkend="identifiers-generators-sequence"/>.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            If the given name matches the name for a <interfacename>javax.persistence.TableGenerator</interfacename>
                            annotation -> <xref linkend="identifiers-generators-table"/>.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            If the given name matches the name for a <interfacename>org.hibernate.annotations.GenericGenerator</interfacename>
                            annotation -> <xref linkend="identifiers-generators-generic"/>.
                        </para>
                    </listitem>
                </itemizedlist>
                The fallback is to consult with the pluggable <interfacename>org.hibernate.boot.model.IdGeneratorStrategyInterpreter</interfacename>
                contract, which is covered in detail in the <citetitle>Hibernate Integrations Guide</citetitle>.  The default
                behavior is to look at the java type of the identifier attribute:
                <itemizedlist>
                    <listitem>
                        <para>
                            If it is UUID -> <xref linkend="identifiers-generators-uuid"/>
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Otherwise -> <xref linkend="identifiers-generators-sequence"/>
                        </para>
                    </listitem>
                </itemizedlist>
            </para>
        </section>

        <section xml:id="identifiers-generators-sequence">
            <title>Using sequences</title>

            <para>
                For implementing database sequence-based identifier value generation Hibernate makes use of its
                <classname>org.hibernate.id.enhanced.SequenceStyleGenerator</classname> id generator.  It is important
                to note that SequenceStyleGenerator is capable of working against databases that do not support sequences
                by switching to a table as the underlying backing.  This gives Hibernate a huge degree of portability
                across databases while still maintaining consistent id generation behavior (versus say choosing
                between sequence and IDENTITY).  This backing storage is completely transparent to the user.
            </para>

            <para>
                The preferred (and portable) way to configure this generator is using the JPA-defined
                <interfacename>javax.persistence.SequenceGenerator</interfacename> annotation.
            </para>

            <para>
                The simplest form is to simply request sequence generation; Hibernate will use a single, implicitly-named
                sequence (<literal>hibernate_sequence</literal>) for all such unnamed definitions.
            </para>

            <example>
                <title>Unnamed sequence</title>
                <programlisting role="JAVA"><xi:include href="extras/UnnamedSequence.java" parse="text" /></programlisting>
            </example>

            <para>
                Or a specifically named sequence can be requested
            </para>

            <example>
                <title>Named sequence</title>
                <programlisting role="JAVA"><xi:include href="extras/NamedSequence.java" parse="text" /></programlisting>
            </example>

            <para>
                Use <interfacename>javax.persistence.SequenceGenerator</interfacename> to specify additional configuration.
            </para>

            <example>
                <title>Configured sequence</title>
                <programlisting role="JAVA"><xi:include href="extras/ConfiguredSequence.java" parse="text" /></programlisting>
            </example>

            <!-- todo : SequenceStyleGenerator specific config (optimizer, forceTable, etc) -->
        </section>

        <section xml:id="identifiers-generators-identity">
            <title>Using IDENTITY columns</title>

            <para>
                For implementing identifier value generation based on IDENTITY columns, Hibernate makes use of its
                <classname>org.hibernate.id.IdentityGenerator</classname> id generator which expects the identifier
                to generated by INSERT into the table.  IdentityGenerator understands 3 different ways that the
                INSERT-generated value might be retrieved:
                <itemizedlist>
                    <listitem>
                        <para>
                            If Hibernate believes the JDBC environment supports <methodname>java.sql.Statement#getGeneratedKeys</methodname>,
                            then that approach will be used for extracting the IDENTITY generated keys.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Otherwise, if <methodname>Dialect#supportsInsertSelectIdentity</methodname> reports
                            true, Hibernate will use the Dialect specific INSERT+SELECT statement syntax.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Otherwise, Hibernate will expect that the database supports some form of asking
                            for the most recently inserted IDENTITY value via a separate SQL command as
                            indicated by <methodname>Dialect#getIdentitySelectString</methodname>
                        </para>
                    </listitem>
                </itemizedlist>
            </para>

            <para>
                It is important to realize that this imposes a runtime behavior where the entity row *must* be
                physically inserted prior to the identifier value being known.  This can mess up extended persistence
                contexts (conversations).  Because of the runtime imposition/inconsistency Hibernate suggest other
                forms of identifier value generation be used.
            </para>

            <para>
                There is yet another important runtime impact of choosing IDENTITY generation: Hibernate will not
                be able to JDBC batching for inserts of the entities that use IDENTITY generation.  The importance
                of this depends on the application's specific use cases.  If the application is not usually
                creating many new instances of a given type of entity that uses IDENTITY generation, then
                this is not an important impact since batching would not have been helpful anyway.
            </para>
        </section>

        <section xml:id="identifiers-generators-table">
            <title>Using identifier table</title>

            <para>
                Hibernate achieves table-based identifier generation based on its
                <interfacename>org.hibernate.id.enhanced.TableGenerator</interfacename> id generator which defines
                a table capable of holding multiple named value segments for any number of entities.
            </para>

            <example>
                <title>Table generator table structure</title>
                <programlisting role="SQL"><xi:include href="extras/TableGenerator.sql" parse="text" /></programlisting>
            </example>

            <para>
                The basic idea is that a given table-generator table (<literal>hibernate_sequences</literal> for example)
                can hold multiple segments of identifier generation values.
            </para>

            <example>
                <title>Unnamed table generator</title>
                <programlisting role="JAVA"><xi:include href="extras/UnnamedTable.java" parse="text" /></programlisting>
            </example>

            <para>
                If no table name is given Hibernate assumes an implicit name of <literal>hibernate_sequences</literal>.
                Additionally, because no <methodname>javax.persistence.TableGenerator#pkColumnValue</methodname> is
                specified, Hibernate will use the default segment (<literal>sequence_name='default'</literal>) from the
                hibernate_sequences table.
            </para>

            <!-- todo : discuss setting org.hibernate.id.enhanced.TableGenerator specific settings -->
        </section>

        <section xml:id="identifiers-generators-uuid">
            <title>Using UUID generation</title>

            <para>
                As mentioned above, Hibernate supports UUID identifier value generation.  This is supported through its
                <classname>org.hibernate.id.UUIDGenerator</classname> id generator.
            </para>

            <para>
                UUIDGenerator supports pluggable strategies for exactly how the UUID is generated.  These strategies
                are defined by the <interfacename>org.hibernate.id.UUIDGenerationStrategy</interfacename> contract.
                The default strategy is a version 4 (random) strategy according to IETF RFC 4122.  Hibernate does ship
                with an alternative strategy which is a RFC 4122 version 1 (time-based) strategy (using ip address
                rather than mac address).
            </para>

            <example>
                <title>Implicitly using the random UUID strategy</title>
                <programlisting role="JAVA"><xi:include href="extras/UUIDRandom.java" parse="text" /></programlisting>
            </example>

            <para>
                To specify an alternative generation strategy, we'd have to define some configuration via
                @GenericGenerator.  Here we choose the RFC 4122 version 1 compliant strategy named
                <classname>org.hibernate.id.uuid.CustomVersionOneStrategy</classname>
            </para>

            <example>
                <title>Implicitly using the random UUID strategy</title>
                <programlisting role="JAVA"><xi:include href="extras/UUIDCustomVersionOneStrategy.java" parse="text" /></programlisting>
            </example>

        </section>

        <section xml:id="identifiers-generators-generic">
            <title>Using @GenericGenerator</title>
            <para>
                @GenericGenerator allows integration of any Hibernate <interfacename>org.hibernate.id.IdentifierGenerator</interfacename>
                implementation, including any of the specific ones discussed here and any custom ones.
            </para>
        </section>

        <section xml:id="identifiers-generators-optimizer">
            <title>Optimizers</title>

            <para>
                Most of the Hibernate generators that separately obtain identifier values from database structures
                support the use of pluggable optimizers.  Optimizers help manage the number of times Hibernate
                has to talk to the database in order to generate identifier values.  For example, with no optimizer
                applied to a sequence-generator, everytime the application asked Hibernate to generate an identifier
                it would need to grab the next sequence value from the database.  But if we can minimize the
                number of times we need to communicate with the database here, the application will be able to perform
                better.  Which is in fact the role of these optimizers.
            </para>

            <variablelist>
                <varlistentry>
                    <term>none</term>
                    <listitem>
                        <para>
                            No optimization is performed.  We communicate with the database each and every time
                            an identifier value is needed from the generator.
                        </para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>pooled-lo</term>
                    <listitem>
                        <para>
                            The pooled-lo optimizer works on the principle that the increment-value is encoded into
                            the database table/sequence structure.  In sequence-terms this means that the sequence
                            is defined with a greater-that-1 increment size.  For example, consider a brand new sequence
                            defined as <literal>create sequence my_sequence start with 1 increment by 20</literal>.
                            This sequence essentially defines a "pool" of 20 usable id values each and every time
                            we ask it for its next-value.  The pooled-lo optimizer interprets the next-value as the
                            low end of that pool.  So when we first ask it for next-value, we'd get 1.  We then assume
                            that the valid pool would be the values from 1-20 inclusive.  The next call to
                            the sequence would result in 21, which would define 21-40 as the valid range.  And so on.
                            The "lo" part of the name indicates that the value from the database table/sequence is
                            interpreted as the pool lo(w) end.
                        </para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>pooled</term>
                    <listitem>
                        <para>
                            Just like pooled-lo, except that here the value from the table/sequence is interpreted
                            as the high end of the value pool.
                        </para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>hilo</term>
                    <term>legacy-hilo</term>
                    <listitem>
                        <para>
                            Define a custom algorithm for generating pools of values based on a single value from
                            a table or sequence.  These optimizers are not recommended for use.  They are maintained
                            (and mentioned) here simply for use by legacy applications that used these strategies
                            previously.
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>

            <para>
                Applications can also implement and use their own optimizer strategies, as defined by the
                <interfacename>org.hibernate.id.enhanced.Optimizer</interfacename> contract.
            </para>
        </section>
    </section>

    <section xml:id="identifiers-derived">
        <title>Derived Identifiers</title>
        <para>
            <!-- todo : write -->
            Ugh...
        </para>
    </section>
</chapter>