惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
N
Netflix TechBlog - Medium
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
B
Blog
F
Fortinet All Blogs
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
Google Developers Blog
A
About on SuperTechFans
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
B
Blog RSS Feed

IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog

The Evolution of WSL Support in JetBrains IDEs - The JetBrains Blog Debug Past an HTTP 403 Without Breaking Spring Security - The JetBrains Blog Java Annotated Monthly – September 2026  - The JetBrains Blog IntelliJ IDEA 2026.2.2 Is Out! - The JetBrains Blog The Grails Plugin Has a New Home: Apache Grails - The JetBrains Blog Project Loom in IntelliJ IDEA: Virtual Threads, Scoped Values, and Structured Concurrency - The JetBrains Blog Spring Boot Configuration Management Best Practices - The JetBrains Blog How to Use AI Agents in IntelliJ IDEA With ACP - The JetBrains Blog Top 5 AI Features in IntelliJ IDEA - The JetBrains Blog Agent Skills in IntelliJ IDEA - The JetBrains Blog IntelliJ IDEA 2026.2.1 Is Out! - The JetBrains Blog Println Debugging Done Right - The JetBrains Blog Java Annotated Monthly – August 2026  - The JetBrains Blog IntelliJ IDEA Goes LSP: Java and Kotlin Intelligence Comes to VS Code, Cursor, and Agentic Flows - The JetBrains Blog Reverse Engineering with Hibernate 7.4 and IntelliJ IDEA - The JetBrains Blog What's New in IntelliJ IDEA 2026.2 - The JetBrains Blog What’s fixed in IntelliJ IDEA 2026.2 - The JetBrains Blog IntelliJ Scala Plugin 2026.2 Is Out! - The JetBrains Blog Java Annotated Monthly – July 2026  - The JetBrains Blog IntelliJ IDEA 2026.1.4 Is Out! - The JetBrains Blog Kotlin Notebook Sunset - The JetBrains Blog Open-Sourcing the LSP Client API in IntelliJ IDEA 2026.2 - The JetBrains Blog Your JetBrains IDE Expertise, Now on LinkedIn - The JetBrains Blog Java Annotated Monthly – June 2026  | The IntelliJ IDEA Blog IntelliJ IDEA 2026.1.3 Is Out! | The IntelliJ IDEA Blog IntelliJ IDEA 2025.3.6 Is Out! | The IntelliJ IDEA Blog IntelliJ IDEA 2026.2 EAP Is Open | The IntelliJ IDEA Blog Improving Accessibility in JetBrains IDEs: What’s New and What’s Next in 2026 | The JetBrains Platform Blog IntelliJ IDEA 2026.1.2 Is Out! | The IntelliJ IDEA Blog 将 Spring Data JDBC 与 Kotlin 搭配使用 | The IntelliJ IDEA Blog
Hibernate 7.4 New Features | The IntelliJ IDEA Blog
Siva Katamreddy · 2026-05-29 · via IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
Idea logo

IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin

Java

Hibernate 7.4 New Features

Hibernate 7.4 introduced several improvements that simplify loading a page of data along with their associated child collection, historical data access, and audit logging.

The article will focus on the following features:

  • Limits and Fetch Joins: How Hibernate 7.4 improves working with paginated queries that include fetched associations.
  • History and Audit Tables: How the new capabilities support querying entity state across time and working with historical data.


You can check out the sample code for this article in this GitHub repository.

Limits and Fetch Joins

One common requirement in data-driven applications is loading a page of parent entities along with an associated child entity collection. For example, suppose an application has an Order entity with a Set<OrderItem> collection, and we want to load the first few orders together with their order items.

List<Order> orders = session
        .createSelectionQuery(
            "select o from Order o join fetch o.items order by o.id",
            Order.class
        )
        .setMaxResults(10)
        .getResultList();

In Hibernate versions before 7.4, applying a limit to a query that used a collection fetch join could not be safely pushed down to the database. Because each Order may have multiple OrderItem rows, limiting the SQL result directly could cut off part of an order’s item collection. To avoid returning incomplete collections, Hibernate loaded all matching rows from the database and applied pagination in memory at the application layer.

That behavior was correct, but it could be expensive. A query intended to load only 10 orders might still read many more rows if the table contained a large number of orders and order items.

Before Hibernate 7.4, the generated SQL would look like the following:

select
    o1_0.id, i1_0.order_id, i1_0.id, i1_0.product_code,
    i1_0.quantity, o1_0.order_number, o1_0.status
from
    orders o1_0
        join
    order_items i1_0
    on o1_0.id=i1_0.order_id

As you can see, the limit(pagination) is not applied at the SQL query level. So, it will load all the orders and their associated order_items, which could be a very expensive operation and may result in OutOfMemoryException.

You can see a WARNING logged by Hibernate as follows:

[WARN] HHH90003004: firstResult/maxResults specified with collection fetch; applying in memory

One option to prevent Hibernate performing pagination in memory is by setting the following property:

hibernate.query.fail_on_pagination_over_collection_fetch=true

By configuring this property, Hibernate throws an exception instead of performing pagination in memory.

Hibernate 7.4 fixes this problem by using nested queries. Instead of applying the limit directly to the joined result set, Hibernate first determines the limited set of parent entity identifiers and then fetches the associated collection for only those parent rows. 

This allows pagination to happen in the database while still returning complete items collections for each selected Order.

With Hibernate 7.4, the SQL will be generated as follows:

select
        o1_0.id, i1_0.order_id, i1_0.id, i1_0.product_code,
        i1_0.quantity, o1_0.order_number,o1_0.status 
    from
        (select
            o1_0.id, o1_0.order_number, o1_0.status 
        from
            orders o1_0 
        where
            exists(select
                1 from order_items i1_0 
            where
                o1_0.id=i1_0.order_id) 
        offset
            ? rows 
        fetch
            first ? rows only) o1_0(id, order_number, status) 
    join
        order_items i1_0 
            on o1_0.id=i1_0.order_id

This improvement makes fetch joins more practical for paginated screens, such as an order listing page that displays each order with its line items, without forcing the application to load the full result set first.

History and Audit Tables

Hibernate 7.4 adds built-in support for temporal history tables and audit tables. Both features help track changes to entity data, but they serve slightly different use cases: history tables let us query the state of an entity at a point in time, while audit tables record the sequence of changes that happened to an entity.

Consider the following Product entity:

@Entity
@Table(name = "products")
class Product {
    //fields id, code, name, price
}

History Tables

To enable temporal history for Product, annotate the entity with @Temporal and optionally specify the history table name using @Temporal.HistoryTable.

@Entity
@Table(name = "products")
@Temporal
@Temporal.HistoryTable(name="products_history")
class Product {
    //fields id, code, name, price
}

With this mapping, Hibernate stores previous versions of product rows in the products_history table. The table includes the entity columns plus two temporal columns: effective, which marks when a version became active, and superseded, which marks when that version was replaced.

products_history table:

idcodenamepriceeffectivesuperseded
2251P1000Product-100040.002026-05-15 08:21:39.949001 +00:00null
2301P1001Product-100190.002026-05-15 08:22:24.765883 +00:002026-05-15 08:22:24.778067 +00:00
2301P1001Product-1001100.002026-05-15 08:22:24.778067 +00:00null

We can get the Product entity data at a given point of time as follows:

Instant someTime = ...
try (var session = sessionFactory.withOptions().asOf(someTime).open()) {
    var product = session.find(Product.class, productId);
    
}

This makes temporal queries feel like normal entity lookups while Hibernate resolves the correct historical row behind the scenes.

Hibernate offers several different strategies(NATIVE, SINGLE_TABLE, HISTORY_TABLE) for mapping temporal entities. For more info check out the Temporal data section.

Audit Tables

Previously, Hibernate-based applications typically used the separate Hibernate Envers library for auditing entity changes. Hibernate 7.4 brings audit table support into Hibernate ORM itself, so applications can use auditing features natively without adding Envers for this use case.

Audit support is enabled by adding @Audited and can be mapped to a custom table using @Audited.Table.

@Entity
@Table(name = "products")
@Audited
@Audited.Table(name="products_aud_log")
class Product {
    //fields id, code, name, price
}

When auditing is enabled, Hibernate writes one row per change into the audit table. Unlike the history table, the audit table focuses on recording what operation happened and when.

idcodenamepricerevrevtype
2001P1002Product-100290.002026-05-13 14:58:17.505775 +00:000
2001P1002Product-1002100.002026-05-13 14:58:17.518194 +00:001

The rev values are the timestamps at which the change happened. The revtype values are represented using ModificationType enum as follows:

public enum ModificationType {
    /**
    * Creation, encoded as 0
    */
    ADD,
    /**
    * Modification, encoded as 1
    */
    MOD,
    /**
    * Deletion, encoded as 2
    */
    DEL
}

For more info check out the Audit logs section.

Summary

Most of the applications use pagination to show a list of resources, and we used to write custom logic to load paginated data along with the associated child collection. Now this is being handled at the framework level itself. Also, we used to rely on external libraries like Envers to implement auditing, which is now provided by Hibernate itself.

Hibernate 7.4 brings practical improvements that address real problems in JPA/ Hibernate-based applications. Whether we are optimizing pagination query behavior or tracking historical data, Hibernate 7.4 reduces the amount of custom infrastructure needed and provides better support out of the box without requiring additional libraries.

Go ahead and explore these new features using this GitHub repository.

Subscribe to IntelliJ IDEA Blog updates

Discover more