Let's pull the Code together-Hibernate's various primary key generation policies and configuration details, hibernate
1. assigned
A primary key is generated by an external program and must be specified before saving. Hibernate does not maintain primary key generation. It has nothing to do with Hibernate and underlying databases and can be cross-database. Before storing an object, you must use the setter method of the primary key to assign a value to the primary key. As for how to generate this value, it is up to you. This method should be avoided as much as possible.
<Id name = "id" column = "id">
<GeneratorClass = "assigned"/>
</Id>
"Ud" is the name of a custom policy. It is a human name and is represented by "ud.
Features: You can control the generation of primary keys across databases and avoid them as much as possible.
2. increment
Hibernate extracts the maximum value of the primary key from the database (each session takes only one time). Based on this value, each increment is 1 and the primary key is generated in the memory, it does not depend on the underlying database, so it can be cross-database.
<Id name = "id" column = "id">
<Generator class = "increment"/>
</Id>
Hibernate calls the generate () method in the org. hibernate. id. IncrementGenerator class and uses the select max (idColumnName) from tableName statement to obtain the maximum value of the primary key. This method is declared as synchronized, so there is no problem in an independent Java Virtual Machine. However, when multiple JVMs concurrently access the database select max, the same value may be obtained, then insert will cause the Dumplicate entry error. Therefore, only one Hibernate application process can access the database. Otherwise, a primary key conflict may occur. Therefore, it is not suitable for multi-process concurrent database update. It is suitable for a single process to access the database and cannot be used in a cluster environment.
Official documentation: This document can be used only when no other process inserts data into the same table. It is not used in a cluster.
Features: Cross-database, not suitable for multi-process concurrent database updates, suitable for a single process to access the database, cannot be used in a cluster environment.
3. hilo
Hilo (high low) is one of the most common generation methods in hibernate, and requires an additional table to save the hi value. The table that saves the hi value has at least one record (only related to the first record). Otherwise, an error occurs.Cross-database.
<Id name = "id" column = "id">
<Generator class = "hilo">
<Param name = "table"> hibernate_hilo </param>
<Param name = "column"> next_hi </param>
<Param name = "max_lo"> 100 </param>
</Generator>
</Id>
<Param name = "table"> hibernate_hilo </param>Name of the table that saves the hi Value
<Param name = "column"> next_hi </param>Name of the column that saves the hi Value
<Param name = "max_lo"> 100 </param>Specify the maximum value of A Low Position
You can also omit the table and column configurations. The default table is hibernate_unique_key, and the column is next_hi.
<Id name = "id" column = "id">
<Generator class = "hilo">
<Param name = "max_lo"> 100 </param>
</Generator>
</Id>
The process in which the hilo generator generates the primary key (in the hibernate_unique_key table, the next_hi column is used as an example ):
1. Obtain the hi value: Read and record the value of the next_hi field in the hibernate_unique_key table of the database. Save the value of this field with 1.
2. Obtain the lo value: the loop value from 0 to max_lo. The difference is 1. When the value is max_lo, obtain the hi value again, and then the lo value continues from 0 to max_lo.
3. Calculate the primary key value based on the formula hi * (max_lo + 1) + lo.
Note: When the hi value is 0, the first value is not 0 * (max_lo + 1) + 0 = 0, but lo skips 0 from 1, directly 1, 2, 3 ......
What is the proper configuration of max_lo?
This depends on the specific situation. If the system generally does not restart and you need to use this table to create a large number of primary keys, you can configure max_lo to be larger, which can reduce the number of reads to the data table, improve efficiency; otherwise, if the server is often restarted, you can lower the max_lo configuration to avoid the large interval between the primary keys every time you restart, resulting in inconsistency of the primary key values.
Features: The identifier generated by the hilo algorithm is unique across databases.
4. seqhilo
Similar to hilo, the primary key generation mechanism implemented through the hi/lo algorithm only replaces the data table in hilo with a sequence. You need to create a sequence in the database, which is suitable for databases that support sequence, such as Oracle.
<Id name = "id" column = "id">
<Generator class = "seqhilo">
<Param name = "sequence"> hibernate_seq </param>
<Param name = "max_lo"> 100 </param>
</Generator>
</Id>
Features: similar to hilo, it can only be used in databases supporting sequences.5. sequence
Use the sequence mechanism provided by the database to generate a primary key. The database must support sequence. For example, sequence in oralce, DB, sap db, PostgerSQL, and McKoi. MySQL is not applicable to databases that do not support sequence (identity can be used ).
<Generator class = "sequence">
<Param name = "sequence"> hibernate_id </param>
</Generator>
<Param name = "sequence"> hibernate_id </param> Specify the sequence name
When Hibernate generates a primary key, it searches for the sequence and assigns it to the primary key value. The primary key value is generated by the database. Hibernate is not responsible for maintenance. A sequence must be created before use. If no sequence name is specified, the default sequence of Hibernate is used, and its name is hibernate_sequence. This sequence must be created in the database.
Features: it can only be used in databases supporting sequences, such as Oracle.
6. identity
Identity is generated by the underlying database. Identity is generated by the database, but the primary key must be set to auto-increment. The prerequisite for using identity is that the underlying database supports auto-increment field types, such as DB2, SQL Server, MySQL, Sybase, and HypersonicSQL. Oracle does not support auto-incrementing fields.
<Id name = "id" column = "id">
<Generator class = "identity"/>
</Id>
For example, if a MySQL database is used, the primary key field must be set to auto_increment.
Id int (11) primary key auto_increment
Feature: it can only be used in field databases that support automatic growth, such as MySQL.
7. native
Native uses identity, hilo, and sequence as the primary key generation method based on the database used by hibernate, which is flexible. If identity is supported, identity is used. If sequence is supported, sequence is used.
<Id name = "id" column = "id">
<Generator class = "native"/>
</Id>
For example, MySQL uses identity and Oracle uses sequence.
NOTE: If Hibernate automatically selects sequence or hilo, the primary keys of all tables will be obtained from the default sequence or hilo table of Hibernate. In addition, some databases support the test of primary key generation by default, and the efficiency is not very high.
When using sequence or hilo, you can add parameters to specify the sequence name or the hi value table name, such
<Param name = "sequence"> hibernate_id </param>
Feature: automatic selection based on the database. This method can be used when multiple databases are used in the project. You need to set the auto-increment field or sequence of the table and create a table.
8. uuid
UUID: Universally Unique Identifier, a number generated on a machine. It is Unique to all machines in the same time and space. According to the standards set by the Open Software Foundation (OSF), ethernet card addresses, nanoseconds, chip ID codes, and many possible numbers are used. The standard UUID format is:
Xxxxxxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
EachXIt is a hexadecimal number in the range of 0-9 or a-f.
<Id name = "id" column = "id">
<Generator class = "uuid"/>
</Id>
When Hibernate saves objects, it generates a UUID string as the primary key to ensure uniqueness. However, it does not have any business logic meaning and can only be used as the primary key. The only drawback is that the length is large, the 32-bit (Hibernate deletes the "-" in the middle of UUID) string, which occupies a large storage space. However, there are two important advantages: When Hibernate maintains the primary key, you do not need to query the database to improve efficiency, and it is cross-database, so it is extremely convenient to switch the database in the future.
Features: uuid is long, occupies a large amount of space, and is cross-database. The primary key value is generated without access to the database. Therefore, it is highly efficient and can ensure uniqueness. It is very convenient to transplant and is recommended for use.
9. guid
GUID: Globally Unique Identifier of Globally Unique Identifier, also known as UUID. It is a 128-bit long number expressed in hexadecimal notation. The core idea of an algorithm is to combine the machine's Nic, local time, and a random number to generate a GUID. Theoretically, if a machine generates 10000000 guids per second, it can ensure (in probability) that there will be no duplicates in 3240.
<Id name = "id" column = "id">
<Generator class = "guid"/>
</Id>
When Hibernate maintains a primary key, it first queries the database and obtains a uuid string, which is the primary key value. This value is unique and has a large length. It supports a limited number of databases and has the same advantages as uuid, cross-database, but still need to access the database.
Note: The length varies with the database.
MySQL uses the select uuid () statement to obtain 36 bits (including "-" in the standard format).
In Oracle, using the select rawtohex (sys_guid () from dual statement gets 32 bits (excluding "-")
Features: the database must support uuid query. The database needs to be queried when the database is generated. The efficiency is not as high as that of uuid. We recommend that you use uuid.
10. foreign
Use the primary key of another associated object as the primary key of the object. It is mainly used in one-to-one relationships.
<Id name = "id" column = "id">
<Generator class = "foreign">
<Param name = "property"> user </param>
</Generator>
</Id>
<One-to-one name = "user" class = "domain. User" constrained = "true"/>
In this example, the primary key of domain. User is used as the primary key mapped to this class.
Features: rarely used, mostly used in one-to-one systems.
11. select
The trigger is used to generate a primary key. It is mainly used to generate a primary key in the early stage of the database, and is rarely used.
12. Other annotation configuration methods
The annotation method is the same as the underlying implementation method of the configuration file, but the configuration method is changed to the annotation method.
Auto-increment: Applicable to databases that support auto-increment Fields
@ Id
@ GeneratedValue (strategy = GenerationType.IDENTITY)
Based on the method automatically selected by the underlying database, you need to set the underlying database
For example, MySQL uses an auto-increment field. You must set the primary key to auto_increment.
@ Id
@ GeneratedValue (strategy = GenerationType.AUTO)
The primary key generated by table store can be used across databases.
The query name is"Hibernate_table"To find the primary key columns."Gen_pk"The value is"2"Record to obtain"Gen_val"Value, according to this value, andAllocationSizeTo generate the primary key value.
@ Id
@ GeneratedValue (strategy = GenerationType.TABLE, Generator = "ud ")
@ TableGenerator (name = "ud ",
Table = "hibernate_table ",
PkColumnName = "gen_pk ",
PkColumnValue = "2 ",
ValueColumnName = "gen_val ",
InitialValue = 2,
AllocationSize = 5)
Use sequence to store primary key values
@ Id
@ GeneratedValue (strategy = GenerationType.SEQUENCE, Generator = "ud ")
@ SequenceGenerator (name = "ud ",
SequenceName = "hibernate_seq ",
AllocationSize = 1,
InitialValue = 2)
13. Summary
1To ensure the uniqueness and non-variability of object identifiers, Hibernate should be assigned a value for the primary key instead of a program.
2Normally, Hibernate is used to maintain the primary key. It is best to set the setter method of the primary key to private, so as to avoid manual or program modification of the primary key. In assigned mode, private cannot be used, otherwise, the primary key cannot be assigned a value.
2. The only simple and common primary key generator in Hibernate is uuid. Although it is a 32-bit unreadable long string, it does not have the problem of cross-database, it will be extremely simple and convenient to switch to the database in the future, it is recommended to use!
3. Automatically increasing field types and Sequences
Database |
Auto-increment Field |
Sequence |
MySQL |
Yes |
|
Oracle |
|
Yes |
DB2 |
Yes |
Yes |
Ms SQL Server |
Yes |
|
Sybase |
Yes |
|
HypersonicSQL |
Yes |
|
PostgreSQL |
|
Yes |
SAP DB |
|
Yes |
HSQLDB |
Yes |
|
Infomix |
Yes |
|
4. Notes about the hilo mechanism:
The identifier generated by the hilo algorithm must be unique in only one database.
You cannot use hilo when you provide a connection for Hibernate or obtain a database connection from the data source of the application server through JTA, this does not ensure that hilo accesses the hi-value table in the transaction of the new database connection. In this case, if the database supports sequence, seqhilo can be used.
5. When using identity, native, GenerationType. AUTO, and other methods to generate a primary key, as long as the AUTO-increment field is used, the fields in the database table must be set to AUTO-increment; otherwise, an error occurs.
6. Some methods are not listed, such as uuid. hex, sequence-identity, etc. These methods are not very common and have been replaced by other methods, such as uuid. hex, which is not recommended in the official documentation, directly using the uuid method.
7. The primary key generation policy configurations of Hibernate versions are slightly different, but the implementation is basically the same. For example, in some versions, if sequence does not specify the sequence name by default, the sequence name hibernate_sequence is used. In some versions, the sequence name must be specified.
8. You can also customize the primary key generation policy. We will not discuss it here. We will only discuss built-in official generation policies.