Skip to content

Commit e4b31c1

Browse files
committed
add new section about bytecode enhancer to intro
1 parent 172b1c4 commit e4b31c1

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

documentation/src/main/asciidoc/introduction/Advanced.adoc

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,81 @@ There are a number of annotations which are useful to express this sort of compl
584584
| `@JoinColumn` | Specifies the foreign key column
585585
|===
586586

587-
Of course, `@Any` mappings are disfavored, except in extremely special cases, since it's much more difficult to enforce referential integrity at the database level.
587+
Of course, `@Any` mappings are disfavored, except in extremely special cases, since it's much more difficult to enforce referential integrity at the database level.
588+
589+
[[bytecode-enhancer]]
590+
=== Using the bytecode enhancer
591+
592+
:enhancer: {userGuideBase}#BytecodeEnhancement
593+
594+
Hibernate's {enhancer}[bytecode enhancer] enables the following features:
595+
596+
- _attribute-level lazy fetching_ for basic attributes annotated `@Basic(fetch=LAZY)` and for lazy non-polymorphic associations,
597+
- _interception-based_—instead of the usual _snapshot-based_—detection of modifications.
598+
599+
To use the bytecode enhancer, we must add the Hibernate plugin to our gradle build:
600+
601+
[source,groovy]
602+
----
603+
plugins {
604+
id "org.hibernate.orm" version "6.2.2.Final"
605+
}
606+
607+
hibernate { enhancement }
608+
----
609+
610+
// [discrete]
611+
// ==== Attribute-level lazy fetching
612+
613+
Consider this field:
614+
615+
[source,java]
616+
----
617+
@Entity
618+
class Book {
619+
...
620+
621+
@Basic(optional = false, fetch = LAZY)
622+
@Column(length = LONG32)
623+
String fullText;
624+
625+
...
626+
}
627+
----
628+
629+
The `fullText` field maps to a `clob` or `text` column, depending on the SQL dialect.
630+
Since it's expensive to retrieve the full book-length text, we've mapped the field `fetch=LAZY`, telling Hibernate not to read the field until it's actually used.
631+
632+
- _Without_ the bytecode enhancer, this instruction is ignored, and the field is always fetched immediately, as part of the initial `select` that retrieves the `Book` entity.
633+
- _With_ bytecode enhancement, Hibernate is able to detect access to the field, and lazy fetching is possible.
634+
635+
[TIP]
636+
====
637+
By default, Hibernate fetches all lazy fields of a given entity at once, in a single `select`, when any one of them is accessed.
638+
Using the `@LazyGroup` annotation, it's possible to assign fields to distinct "fetch groups", so that different lazy fields may be fetched independently.
639+
====
640+
641+
Similarly, interception lets us implement lazy fetching for non-polymorphic associations without the need for a separate proxy object.
642+
However, if an association is polymorphic, that is, if the target entity type has subclasses, then a proxy is still required.
643+
644+
// [discrete]
645+
// ==== Interception-based change detection
646+
647+
Interception-based change detection is a nice performance optimization with a slight cost in terms of correctness.
648+
649+
- _Without_ the bytecode enhancer, Hibernate keeps a snapshot of the state of each entity after reading from or writing to the database.
650+
When the session flushes, the snapshot state is compared to the current state of the entity to determine if the entity has been modified.
651+
Maintaining these snapshots does have an impact on performance.
652+
- _With_ bytecode enhancement, we may avoid this cost by intercepting writes to the field and recording these modifications as they happen.
653+
654+
[CAUTION]
655+
====
656+
Interception-based change detection is less accurate than snapshot-based dirty checking.
657+
For example, consider this attribute:
658+
659+
[source,java]
660+
byte[] image;
661+
662+
Interception is able to detect writes to the `image` field, that is, replacement of the whole array.
663+
It's not able to detect modifications made directly to the _elements_ of the array, and so such modifications may be lost.
664+
====

0 commit comments

Comments
 (0)