Hibernate shifts the developer mindset from SQL statements to entity state transitions. Once an entity is actively managed by Hibernate, all changes are going to be automatically propagated to the database.
Manipulating domain model entities (along with their associations) is much easier than writing and maintaining SQL statements. Without an ORM tool, adding a new column requires modifying all associated INSERT/UPDATE statements.
But Hibernate is no silver bullet either. Hibernate doesn’t free us from ever worrying about the actual executed SQL statements. Controlling Hibernate is not as straightforward as one might think and it’s mandatory to check all SQL statements Hibernate executes on our behalf.
Continue reading “A beginner’s guide to entity state transitions with JPA and Hibernate”
In this post, we’ll uncover a sequence identifier generator combining identifier assignment efficiency and interoperability with other external systems (concurrently accessing the underlying database system).
Traditionally there have been two sequence identifier strategies to choose from.
The sequence identifier, always hitting the database for every new value assignment. Even with database sequence preallocation we have a significant database round-trip cost.
The seqhilo identifier, using the hi/lo algorithm. This generator calculates some identifier values in-memory, therefore reducing the database round-trip calls. The problem with this optimization technique is that the current database sequence value no longer reflects the current highest in-memory generated value. The database sequence is used as a bucket number, making it difficult for other systems to interoperate with the database table in question. Other applications must know the inner-workings of the hi/lo identifier strategy to properly generate non-clashing identifiers.
The enhanced identifiers
Hibernate offers a new class of identifier generators, addressing many shortcomings of the original ones. The enhanced identifier generators don’t come with a fixed identifier allocation strategy. The optimization strategy is configurable and we can even supply our own optimization implementation. By default Hibernate comes with the following built-in optimizers:
- none: every identifier is fetched from the database, so it’s equivalent to the original sequence generator.
- hi/lo: it uses the hi/lo algorithm and it’s equivalent to the original seqhilo generator.
- pooled: This optimizer uses a hi/lo optimization strategy, but the current in-memory identifiers highest boundary is extracted from an actual database sequence value.
- pooled-lo: It’s similar to the pooled optimizer but the database sequence value is used as the current in-memory lowest boundary
Continue reading “Hibernate pooled and pooled-lo identifier generators”
JPA identifier generators
JPA defines the following identifier strategies:
||The persistence provider picks the most appropriate identifier strategy supported by the underlying database
||Identifiers are assigned by a database IDENTITY column
||The persistence provider uses a database sequence for generating identifiers
||The persistence provider uses a separate database table to emulate a sequence object
In my previous post I exampled the pros and cons of all these surrogate identifier strategies.
Continue reading “A beginner’s guide to Hibernate enhanced identifier generators”
In my previous post I talked about different database identifier strategies. This post will compare the most common surrogate primary key strategies:
- TABLE (SEQUENCE)
The IDENTITY type (included in the SQL:2003 standard) is supported by:
The IDENTITY generator allows an integer/bigint column to be auto-incremented on demand. The increment process happens outside of the current running transaction, so a roll-back may end-up discarding already assigned values (value gaps may happen).
The increment process is very efficient since it uses a database internal lightweight locking mechanism as opposed to the more heavyweight transactional course-grain locks.
The only drawback is that we can’t know the newly assigned value prior to executing the INSERT statement. This restriction is hindering the “transactional write behind” flushing strategy adopted by Hibernate. For this reason, Hibernates disables the JDBC batch support for entities using the IDENTITY generator.
Continue reading “How do Identity, Sequence, and Table (sequence-like) generators work in JPA and Hibernate”
In my previous post I talked about UUID surrogate keys and the use cases when there are more appropriate than the more common auto-incrementing identifiers.
A UUID database type
There are several ways to represent a 128-bit UUID, and whenever in doubt I like to resort to Stack Exchange for an expert advice.
Because table identifiers are usually indexed, the more compact the database type the less space will the index require. From the most efficient to the least, here are our options:
- Some databases (PostgreSQL, SQL Server) offer a dedicated UUID storage type
- Otherwise we can store the bits as a byte array (e.g. RAW(16) in Oracle or the standard BINARY(16) type)
- Alternatively we can use 2 bigint (64-bit) columns, but a composite identifier is less efficient than a single column one
- We can store the hex value in a CHAR(36) column (e.g 32 hex values and 4 dashes), but this will take the most amount of space, hence it’s the least efficient alternative
Hibernate offers many identifier strategies to choose from and for UUID identifiers we have three options:
- the assigned generator accompanied by the application logic UUID generation
- the hexadecimal “uuid” string generator
- the more flexible “uuid2” generator, allowing us to use java.lang.UUID, a 16 byte array or a hexadecimal String value
Continue reading “Hibernate and UUID identifiers”