Prev Next

Hibernate / Hibernate 7 Basics Interview Questions

1. What is Hibernate 7 and when was it released? 2. What is ORM and why is Hibernate used instead of writing raw JDBC? 3. How do you configure Hibernate 7 with Maven? 4. What is an entity in Hibernate 7 and how do you define one? 5. What are entity states in Hibernate 7 and how do they transition? 6. What is the biggest breaking change in Hibernate 7: detached entity reassociation removal? 7. What is the Session in Hibernate 7 and what are its core CRUD operations? 8. What is the Hibernate SessionFactory and how do you create one? 9. What is HQL (Hibernate Query Language) in Hibernate 7? 10. What is JPQL vs HQL in Hibernate 7? 11. How does Hibernate 7 handle primary key generation strategies? 12. What is the first-level cache (persistence context) in Hibernate 7? 13. What is the second-level cache in Hibernate 7 and how does it work with StatelessSession? 14. What are lazy and eager fetching in Hibernate 7 and how do you avoid the N+1 problem? 15. How do you map one-to-many and many-to-one relationships in Hibernate 7? 16. What is the StatelessSession in Hibernate 7 and when should you use it? 17. What is the Criteria API in Hibernate 7 and what are SelectionSpecification and RestrictionSpecification? 18. How does @Embeddable and @Embedded mapping work in Hibernate 7? 19. What are the new FindOptions in Jakarta Persistence 3.2 and Hibernate 7? 20. What is optimistic locking in Hibernate 7 and how do you implement it? 21. What is pessimistic locking in Hibernate 7 and what are the improvements? 22. What is the @ManyToMany relationship in Hibernate 7 and how do you map it? 23. What is Hibernate's flush behaviour and how does it affect SQL execution? 24. What are named queries in Hibernate 7 and how are they type-safe with TypedQueryReference? 25. What is the @Inheritance mapping in Hibernate 7 and what strategies are available? 26. What is the @Filter and auto-enabled filters feature in Hibernate 7? 27. What is key-based pagination in Hibernate 7 and how does it differ from offset pagination? 28. What is Jakarta Data 1.0 and how does it integrate with Hibernate 7? 29. What is the @NaturalId feature in Hibernate 7 and what is @NaturalIdClass? 30. How does Hibernate 7 support vector data types for AI/ML applications? 31. What are the key removed APIs in Hibernate 7 and how do you migrate? 32. What is @SQLRestriction and @SQLJoinTableRestriction in Hibernate 7? 33. How does Hibernate 7 handle schema validation and generation (hbm2ddl)? 34. What are Hibernate 7's improvements to multi-tenancy support? 35. What is the @Check constraint and @ColumnDefault annotation in Hibernate 7? 36. What is @BatchSize and how does it solve the N+1 problem differently from JOIN FETCH? 37. What is Hibernate 7's @Struct mapping for database composite types? 38. What are Hibernate 7's logging improvements for SQL and parameter binding? 39. How does Hibernate 7 work with Spring Boot 4 - what is auto-configured? 40. What are the key Hibernate 7 vs Hibernate 6 differences interviewers ask about?
Could not find what you were looking for? send us the question and we would be happy to answer your question.

1. What is Hibernate 7 and when was it released?

Hibernate ORM 7 is the current major version of Hibernate, the most widely used Java ORM framework. Hibernate 7.0 was released on May 20, 2025. The current latest stable release is 7.4 (mid-2026).

  • First production-ready release entirely under Apache Software License v2 (including Envers)
  • Complete implementation of Jakarta Persistence 3.2
  • Complete implementation of Jakarta Data 1.0
  • Full support for Jakarta EE 11
Hibernate 7 at a glance
PropertyDetail
GA releaseMay 20, 2025
Latest stable7.4 (mid-2026)
LicenseApache Software License v2
Jakarta Persistence3.2
Jakarta Data1.0
Minimum JavaJava 17
Managed in Spring BootSpring Boot 4.x
What license did Hibernate 7 adopt for ALL modules including Envers?
Which Jakarta Persistence version does Hibernate 7 fully implement?

2. What is ORM and why is Hibernate used instead of writing raw JDBC?

ORM (Object-Relational Mapping) automatically maps Java objects to relational database tables, eliminating JDBC boilerplate. Hibernate is the most widely used Java ORM.

Raw JDBC vs Hibernate
TaskRaw JDBCHibernate
QueryWrite SQL, iterate ResultSet, map columnssession.find(Order.class, id) or JPQL
InsertPreparedStatement + executeUpdate()session.persist(order)
UpdateWrite UPDATE SQLModify managed entity - Hibernate auto-detects
RelationshipsManual JOIN queries@OneToMany, @ManyToOne - automatic
CachingNoneFirst-level + optional second-level cache
PortabilityDB-specific SQLDialect abstracts DB differences
// Raw JDBC (boilerplate):
try (Connection c = ds.getConnection();
     PreparedStatement ps = c.prepareStatement("SELECT * FROM products WHERE id=?")) {
    ps.setLong(1, id);
    ResultSet rs = ps.executeQuery();
    // manually map columns to fields...
}

// Hibernate 7 (clean):
try (Session s = sf.openSession()) {
    return s.find(Product.class, id);
}

What is the primary benefit of using Hibernate over raw JDBC?
What does Hibernate's Dialect abstraction provide?

3. How do you configure Hibernate 7 with Maven?

Hibernate 7 can be used standalone or as the JPA provider in Spring Boot 4. Key dependencies:

<!-- Standalone -->
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>7.4.0.Final</version>
</dependency>

<!-- Spring Boot 4 (managed version) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <!-- Includes hibernate-core 7.x transitively -->
</dependency>

<!-- Annotation processor for static metamodel -->
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-processor</artifactId>
    <version>7.4.0.Final</version>
    <scope>provided</scope>
</dependency>

What artifact provides the core Hibernate 7 ORM functionality?
What is the hibernate-processor artifact used for?

4. What is an entity in Hibernate 7 and how do you define one?

An entity is a Java class mapped to a database table. Each instance corresponds to a row. In Hibernate 7, entity classes follow Jakarta Persistence 3.2 rules.

import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "product_name", nullable = false, length = 200)
    private String name;

    @Column(precision = 10, scale = 2)
    private BigDecimal price;

    @Enumerated(EnumType.STRING)  // store as 'ACTIVE' not 0/1
    private ProductStatus status;

    protected Product() {}  // JPA proxy constructor
    public Product(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
        this.status = ProductStatus.ACTIVE;
    }
}

Which import package must you use for @Entity in Hibernate 7?
What does @Enumerated(EnumType.STRING) do on an enum field?

5. What are entity states in Hibernate 7 and how do they transition?

Every entity instance in Hibernate exists in one of three states relative to a Session. Hibernate 7 enforces stricter rules on detached entities.

The three entity states
StateDescriptionIn session?DB record?
TransientNever associated with a SessionNoNo
PersistentAssociated with open Session; changes trackedYesYes
DetachedWas persistent; Session closedNoYes
// TRANSIENT
Product p = new Product("Laptop", new BigDecimal("999"));

// TRANSIENT -> PERSISTENT
session.persist(p);  // INSERT scheduled

// Auto dirty checking: change field -> UPDATE at flush
p.setPrice(new BigDecimal("899"));
session.getTransaction().commit();  // flush: UPDATE sent

// PERSISTENT -> DETACHED (session closes)
// p is detached: changes NOT tracked

// Hibernate 7: ONLY merge() re-integrates detached entities
Product managed = session2.merge(p);  // copies detached state
managed.setPrice(new BigDecimal("799"));

What is the key characteristic of a PERSISTENT entity in Hibernate 7?
In Hibernate 7, what is the ONLY way to re-integrate a detached entity's changes into an open session?

6. What is the biggest breaking change in Hibernate 7: detached entity reassociation removal?

The most impactful breaking change in Hibernate 7 is the complete removal of detached entity reassociation. Methods like session.update(), session.saveOrUpdate(), and session.lock() on detached entities are removed.

Removed reassociation operations
Removed methodReplacement
session.update(entity)session.merge(entity)
session.saveOrUpdate(entity)session.merge(entity)
session.lock(entity, LockMode)Load fresh: session.find(Class, id, LockMode)
session.refresh(detached)Only allowed on managed entities
hibernate.allow_refresh_detached_entity propertyRemoved entirely
// Hibernate 6 (worked but deprecated):
session.update(detachedProduct);  // REMOVED in Hibernate 7!

// Hibernate 7 - use merge():
Product managed = session.merge(detachedProduct);
managed.setPrice(new BigDecimal("50"));  // modify managed copy
session.getTransaction().commit();

// Adding detached child to managed parent:
// WRONG in Hibernate 7:
parent.addChild(detachedChild);  // throws EntityExistsException at flush!

// CORRECT:
Child managedChild = session.merge(detachedChild);
parent.addChild(managedChild);

What exception does Hibernate 7 throw at flush when you add a detached child to a managed parent collection?
Which Hibernate 7 operation correctly handles a detached entity whose state you want to persist?

7. What is the Session in Hibernate 7 and what are its core CRUD operations?

The Session is Hibernate's primary interface for database operations. It represents a unit of work and maintains the first-level cache. Key API changes in Hibernate 7:

Session method changes
Old method (removed)Hibernate 7 replacement
session.save(entity)session.persist(entity)
session.get(Class,id)session.find(Class,id)
session.delete(entity)session.remove(entity)
session.update(entity)session.merge(entity)
session.saveOrUpdate(entity)session.merge(entity)
session.beginTransaction();

// CREATE
Product p = new Product("Book", new BigDecimal("19.99"));
session.persist(p);  // replaces save()

// READ: returns null if not found
Product found = session.find(Product.class, 1L);  // replaces get()

// READ lazy proxy
Product ref = session.getReference(Product.class, 1L);

// UPDATE: automatic dirty checking - no explicit call needed
found.setPrice(new BigDecimal("24.99"));

// DELETE
session.remove(found);  // replaces delete()

// MERGE: integrate detached state
Product copy = session.merge(detached);

session.getTransaction().commit();

Which Hibernate 7 method loads an entity by PK returning null if not found?
What is the difference between session.find() and session.getReference()?

8. What is the Hibernate SessionFactory and how do you create one?

The SessionFactory is the central, thread-safe, immutable configuration object. It is expensive to create and should be instantiated once per application lifecycle.

Configuration config = new Configuration();
config.setProperty("hibernate.connection.url", "jdbc:postgresql://localhost:5432/mydb");
config.setProperty("hibernate.connection.username", "user");
config.setProperty("hibernate.connection.password", "secret");
config.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
config.setProperty("hibernate.hbm2ddl.auto", "validate");
config.setProperty("hibernate.show_sql", "true");

config.addAnnotatedClass(Product.class);
config.addAnnotatedClass(Order.class);

// Build once, reuse everywhere:
SessionFactory sf = config.buildSessionFactory();

// Usage:
try (Session session = sf.openSession()) {
    session.beginTransaction();
    // operations
    session.getTransaction().commit();
}

What is the correct pattern for using a Hibernate SessionFactory in production?
What does hibernate.hbm2ddl.auto=validate do?

9. What is HQL (Hibernate Query Language) in Hibernate 7?

HQL is Hibernate's object-oriented query language operating on entity objects rather than tables. Hibernate 7 adds new HQL functions including regexp, JSON/XML manipulation, and set-returning functions.

// Basic HQL - uses entity class name, not table name:
List<Product> all = session
    .createQuery("FROM Product", Product.class)
    .getResultList();

// WHERE with named parameter:
List<Product> active = session
    .createQuery("FROM Product WHERE status = :status", Product.class)
    .setParameter("status", ProductStatus.ACTIVE)
    .getResultList();

// Constructor expression (DTO projection):
List<ProductSummary> s = session
    .createQuery(
        "SELECT new com.example.ProductSummary(p.id, p.name, p.price) "
        + "FROM Product p WHERE p.price < :max",
        ProductSummary.class)
    .setParameter("max", new BigDecimal("100"))
    .getResultList();

// JOIN on association fields:
List<Order> orders = session
    .createQuery("FROM Order o JOIN o.customer c WHERE c.email = :email", Order.class)
    .setParameter("email", "alice@example.com")
    .getResultList();

// Pagination:
List<Product> page = session
    .createQuery("FROM Product ORDER BY createdAt DESC", Product.class)
    .setFirstResult(0).setMaxResults(20).getResultList();

// Hibernate 7 new: regexp operator
List<Product> matched = session
    .createQuery("FROM Product WHERE name regexp :pattern", Product.class)
    .setParameter("pattern", "^(Laptop|Phone)")
    .getResultList();

In HQL, what does the FROM clause reference?
What HQL feature maps query results directly to a DTO class?

10. What is JPQL vs HQL in Hibernate 7?

JPQL is the standardised query language from Jakarta Persistence. HQL is a strict superset with additional Hibernate-specific features.

JPQL vs HQL
AspectJPQLHQL
SpecificationJakarta Persistence 3.2 standardHibernate superset of JPQL
PortabilityWorks with any JPA providerHibernate-specific
FunctionsStandard functionsAll JPQL + regexp, ilike, array, JSON, XML (Hibernate 7)
Set operationsUNION/INTERSECT/EXCEPT (JP 3.2)Same as JPQL + more
// JPQL (standard):
EntityManager em = emf.createEntityManager();
List<Product> p = em
    .createQuery("SELECT p FROM Product p WHERE p.price < :max", Product.class)
    .setParameter("max", new BigDecimal("100"))
    .getResultList();

// HQL shorthand (Hibernate-specific):
List<Product> p2 = session
    .createQuery("FROM Product WHERE price < :max", Product.class)
    .setParameter("max", new BigDecimal("100"))
    .getResultList();

// HQL-only: regexp
List<Product> re = session
    .createQuery("FROM Product WHERE name regexp :pat", Product.class)
    .setParameter("pat", "^(Laptop|Phone)").getResultList();

// UNION (supported in both JPQL 3.2 and HQL):
List<Object[]> combined = session.createQuery(
    "SELECT p.id, p.name FROM Product p WHERE p.category = :cat "
    + "UNION "
    + "SELECT s.id, s.name FROM Service s WHERE s.category = :cat",
    Object[].class).setParameter("cat", "tech").getResultList();

What is the relationship between HQL and JPQL?
What set operations did Hibernate 6/7 add to HQL?

11. How does Hibernate 7 handle primary key generation strategies?

Primary key generation is controlled by @GeneratedValue. Hibernate 7 supports all four JPA strategies plus UUID as a first-class feature.

@GeneratedValue strategies
StrategyHow it worksBest for
IDENTITYDB auto-increment (SERIAL/AUTO_INCREMENT)Simple setups; disables JDBC batch inserts
SEQUENCEUses DB sequence; Hibernate batches allocationPostgreSQL, Oracle; supports batch inserts
TABLESimulates sequence with a special tablePortable but slow
AUTOHibernate picks best strategyQuick prototyping
UUIDGenerates UUID as PKDistributed systems
// IDENTITY:
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// SEQUENCE (recommended for batch inserts):
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_seq")
@SequenceGenerator(name="product_seq", sequenceName="product_id_seq", allocationSize=50)
private Long id;

// UUID (first-class in Hibernate 7):
@Id @GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

// Time-based UUID v7:
@Id @UuidGenerator(style = UuidGenerator.Style.TIME)
private UUID id;

Why does GenerationType.IDENTITY disable JDBC batch inserts in Hibernate 7?
Which GenerationType is recommended for PostgreSQL to maximise bulk insert performance?

12. What is the first-level cache (persistence context) in Hibernate 7?

The first-level cache is the per-Session in-memory cache for all entities loaded or persisted within an open Session. It is mandatory - every Session has its own first-level cache.

Session session = sf.openSession();
session.beginTransaction();

Product p1 = session.find(Product.class, 1L);  // DB hit
Product p2 = session.find(Product.class, 1L);  // CACHE HIT - no SQL!
Product p3 = session.find(Product.class, 1L);  // CACHE HIT

System.out.println(p1 == p2);  // true! Same object reference

// Evict specific entity:
session.detach(p1);  // p1 is now DETACHED
Product p4 = session.find(Product.class, 1L);  // DB hit again

// Clear entire cache:
session.clear();  // all entities become DETACHED

// Bulk processing pattern (prevent OutOfMemoryError):
for (int i = 0; i < 100_000; i++) {
    session.persist(products.get(i));
    if (i % 50 == 0) {
        session.flush();   // write to DB
        session.clear();   // free cache memory
    }
}

What happens when you call session.find(Product.class, 1L) twice in the same open Session?
Why call session.flush() then session.clear() periodically during bulk INSERT processing?

13. What is the second-level cache in Hibernate 7 and how does it work with StatelessSession?

The second-level cache is an optional cross-session application-wide cache. Hibernate 7 changes StatelessSession's behaviour: it now reads/writes the L2 cache by default (was bypassed in v6).

Cache level comparison
AspectFirst-level cacheSecond-level cache
ScopePer SessionPer SessionFactory (application lifetime)
MandatoryYesOptional
Shared across sessionsNoYes
ProviderBuilt-inInfinispan, Ehcache 3, Caffeine
// Enable L2 cache on an entity:
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country {
    @Id private Long id;
    private String name;
}

// Spring Boot 4 configuration:
// spring.jpa.properties.hibernate.cache.use_second_level_cache=true

// HIBERNATE 7: StatelessSession now uses L2 cache by default!
// To bypass (for bulk processing):
StatelessSession ss = sf.openStatelessSession();
ss.setCacheMode(CacheMode.IGNORE);  // bypass L2 cache

What is the key Hibernate 7 change in how StatelessSession interacts with the second-level cache?
What ConcurrencyStrategy would you use for entity read frequently and rarely updated?

14. What are lazy and eager fetching in Hibernate 7 and how do you avoid the N+1 problem?

Lazy fetching loads associations on demand. Eager fetching loads them immediately. Wrong strategy choice leads to the N+1 query problem.

// LAZY (default for @OneToMany):
@OneToMany(mappedBy="customer", fetch=FetchType.LAZY)
private List<Order> orders;

// N+1 PROBLEM:
// 1 query: SELECT * FROM customers
// N queries: SELECT * FROM orders WHERE customer_id=1 ... customer_id=N
List<Customer> customers = session.createQuery("FROM Customer", Customer.class).getResultList();
for (Customer c : customers) {
    c.getOrders().size();  // triggers N extra queries!
}

// SOLUTION 1: JOIN FETCH
List<Customer> customers = session
    .createQuery("FROM Customer c JOIN FETCH c.orders", Customer.class)
    .getResultList();  // 1 query with JOIN

// SOLUTION 2: @BatchSize
@OneToMany(mappedBy="customer")
@BatchSize(size=25)  // loads 25 collections in one IN query
private List<Order> orders;

// SOLUTION 3: EntityGraph
EntityGraph<Customer> graph = session.createEntityGraph(Customer.class);
graph.addAttributeNode("orders");
List<Customer> list = session.createSelectionQuery("FROM Customer", Customer.class)
    .applyFetchGraph(graph).getResultList();

What is the N+1 query problem in Hibernate?
What HQL keyword eliminates the N+1 problem by loading parent and association in a single JOIN?

15. How do you map one-to-many and many-to-one relationships in Hibernate 7?

Relationships are mapped using @OneToMany, @ManyToOne, etc. The owning side holds the foreign key column.

@Entity
public class Customer {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(
        mappedBy="customer",
        cascade=CascadeType.ALL,
        orphanRemoval=true,
        fetch=FetchType.LAZY
    )
    private List<Order> orders = new ArrayList<>();

    public void addOrder(Order o) {
        orders.add(o);
        o.setCustomer(this);  // keep both sides in sync!
    }
}

@Entity @Table(name="orders")
public class Order {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private BigDecimal total;

    @ManyToOne(fetch=FetchType.LAZY)  // explicit LAZY recommended
    @JoinColumn(name="customer_id", nullable=false)
    private Customer customer;  // owning side: holds FK
}

// Usage:
Customer c = new Customer("Alice");
c.addOrder(new Order(new BigDecimal("50")));
session.persist(c);  // cascades to orders

In a bidirectional @OneToMany/@ManyToOne relationship, which side holds the FK column?
What does CascadeType.ALL on @OneToMany mean?

16. What is the StatelessSession in Hibernate 7 and when should you use it?

StatelessSession has no first-level cache, no dirty checking, and no automatic state management. In Hibernate 7 it reaches near feature-parity with Session and is the preferred tool for bulk processing.

Session vs StatelessSession
AspectSessionStatelessSession
First-level cacheYesNo
Dirty checkingYesNo - must call update() explicitly
MemoryCan grow with large result setsMinimal
L2 cache (Hibernate 7)YesYes (new - was bypassed in v6)
Best forTransactional CRUDBulk ETL, batch imports, reporting
try (StatelessSession ss = sf.openStatelessSession()) {
    ss.beginTransaction();

    // Hibernate 7: must set batch size explicitly on StatelessSession!
    ss.setJdbcBatchSize(50);  // hibernate.jdbc.batch_size has NO effect here

    // New batch operations in Hibernate 7:
    ss.insertMultiple(products);   // batch inserts
    ss.updateMultiple(toUpdate);   // batch updates

    // Bypass L2 cache for bulk operations (new default is to use it):
    ss.setCacheMode(CacheMode.IGNORE);

    // Scrollable results for very large datasets:
    ScrollableResults<Product> scroll = ss
        .createQuery("FROM Product", Product.class)
        .scroll(ScrollMode.FORWARD_ONLY);
    while (scroll.next()) {
        Product p = scroll.get();
        p.setPrice(p.getPrice().multiply(new BigDecimal("0.9")));
        ss.update(p);  // explicit - no dirty checking
    }
    ss.getTransaction().commit();
}

Why is StatelessSession preferred over Session for bulk import operations in Hibernate 7?
In Hibernate 7, why must you call setJdbcBatchSize() explicitly on a StatelessSession?

17. What is the Criteria API in Hibernate 7 and what are SelectionSpecification and RestrictionSpecification?

Hibernate 7 introduces a new type-safe Criteria-like API: SelectionSpecification and RestrictionSpecification - simpler than the JPA Criteria API for common cases while remaining fully type-safe via the static metamodel.

// Static metamodel auto-generated by hibernate-processor:
// public abstract class Product_ {
//     public static volatile SingularAttribute<Product, Long> id;
//     public static volatile SingularAttribute<Product, String> name;
//     public static volatile SingularAttribute<Product, BigDecimal> price;
// }

// Hibernate 7: NEW SelectionSpecification API
var results = SelectionSpecification
    .create(Product.class)
    .restrict(Restriction.equal(Product_.status, ProductStatus.ACTIVE))
    .restrict(Restriction.contains(Product_.name, "book", false))
    .restrict(Restriction.greaterThan(Product_.price, new BigDecimal("10")))
    .sort(Order.desc(Product_.price))
    .createQuery(session)
    .setMaxResults(20)
    .getResultList();

// RestrictionSpecification: add restrictions to an EXISTING query
var priceFilter = RestrictionSpecification
    .of(Product.class)
    .where(Restriction.between(Product_.price, new BigDecimal("10"), new BigDecimal("100")));

var update = session.createMutationQuery("UPDATE Product SET discount = :disc");
priceFilter.applyTo(update);
update.setParameter("disc", new BigDecimal("5")).executeUpdate();

// Traditional JPA Criteria still works:
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Product> cq = cb.createQuery(Product.class);
Root<Product> root = cq.from(Product.class);
cq.where(cb.equal(root.get(Product_.status), ProductStatus.ACTIVE));
List<Product> r = session.createQuery(cq).getResultList();

What is the key advantage of Hibernate 7's SelectionSpecification API over JPA Criteria API?
What tool generates the static metamodel classes (like Product_)?

18. How does @Embeddable and @Embedded mapping work in Hibernate 7?

@Embeddable marks a class as a value type stored within the parent entity's table. Hibernate 7 adds @EmbeddedColumnNaming (incubating) to simplify prefix/suffix mapping for multiple embeddables of the same type.

@Embeddable
public class Address {
    @Column(name="street") private String street;
    @Column(name="city")   private String city;
    @Column(name="postcode", length=10) private String postcode;
}

@Entity
public class Customer {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String name;

    @Embedded
    private Address shippingAddress;  // columns: street, city, postcode

    // Hibernate 6 approach (verbose - one @AttributeOverride per field):
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="street",   column=@Column(name="billing_street")),
        @AttributeOverride(name="city",     column=@Column(name="billing_city")),
        @AttributeOverride(name="postcode", column=@Column(name="billing_postcode"))
    })
    private Address billingAddress;

    // Hibernate 7 NEW (incubating): much simpler!
    // @Embedded
    // @EmbeddedColumnNaming("billing_{column_name}")
    // private Address billingAddress;
    // Generates: billing_street, billing_city, billing_postcode
}

What is the difference between @Entity and @Embeddable in Hibernate 7?
What Hibernate 7 feature simplifies mapping two @Embeddable objects of the same type in one entity?

19. What are the new FindOptions in Jakarta Persistence 3.2 and Hibernate 7?

Jakarta Persistence 3.2 introduces FindOption, RefreshOption, and LockOption for fine-grained control over find/refresh/lock operations without separate methods for each combination. Hibernate 7 also adds session.findMultiple().

// Before JP 3.2: separate methods for different behaviours
// After: varargs options on find()
import jakarta.persistence.Timeouts;

// Find with pessimistic lock and no-wait timeout:
Book book = session.find(
    Book.class,
    isbn,
    LockModeType.PESSIMISTIC_WRITE,
    Timeouts.NO_WAIT  // fail immediately if locked
);

// Find bypassing second-level cache:
Book book2 = session.find(
    Book.class, isbn,
    CacheRetrieveMode.BYPASS
);

// session.findMultiple(): batch load multiple entities
List<Book> books = session.findMultiple(
    Book.class,
    List.of(isbn1, isbn2, isbn3)
);
// Loads all 3 in a single SELECT ... WHERE id IN (?,?,?)

// RefreshOption:
session.refresh(managedBook, LockModeType.PESSIMISTIC_READ);

// LockOption:
session.lock(managedBook, LockModeType.PESSIMISTIC_WRITE,
    Timeouts.of(5, TimeUnit.SECONDS));

What problem do FindOption/RefreshOption/LockOption solve in Jakarta Persistence 3.2?
What does session.findMultiple() provide that session.find() in a loop does not?

20. What is optimistic locking in Hibernate 7 and how do you implement it?

Optimistic locking uses a version column to detect concurrent update conflicts at commit time instead of locking the row. Hibernate 7 throws OptimisticLockException when the version has changed since the entity was loaded.

@Entity
public class Product {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String name;
    private BigDecimal price;

    @Version  // Hibernate manages automatically
    private Long version;
}

// How it works:
// Load:   SELECT id, name, price, version FROM products WHERE id=1
//         version=5
// Modify: product.setPrice(new BigDecimal("99"))
// Flush:  UPDATE products SET price=99, version=6 WHERE id=1 AND version=5
//         If another TX updated it: version!=5 -> OptimisticLockException!

// Handling conflicts:
for (int attempt = 0; attempt < 3; attempt++) {
    try (Session session = sf.openSession()) {
        session.beginTransaction();
        Product p = session.find(Product.class, productId);
        p.setPrice(p.getPrice().multiply(new BigDecimal("0.9")));
        session.getTransaction().commit();
        break;  // success
    } catch (OptimisticLockException e) {
        if (attempt == 2) throw e;
        Thread.sleep(50 * (attempt + 1));
    }
}

What does @Version on a Long field do in Hibernate 7?
When does Hibernate 7 throw OptimisticLockException?

21. What is pessimistic locking in Hibernate 7 and what are the improvements?

Pessimistic locking acquires a DB-level lock on a row when loaded. Hibernate 7 improves this with the Timeouts API from Jakarta Persistence 3.2.

// PESSIMISTIC_WRITE: SELECT ... FOR UPDATE
Product p = session.find(Product.class, id, LockModeType.PESSIMISTIC_WRITE);

// Hibernate 7: Timeouts API
import jakarta.persistence.Timeouts;

// Fail immediately if lock unavailable:
Product p2 = session.find(Product.class, id,
    LockModeType.PESSIMISTIC_WRITE, Timeouts.NO_WAIT);

// Wait up to 5 seconds:
Product p3 = session.find(Product.class, id,
    LockModeType.PESSIMISTIC_WRITE, Timeouts.of(5, TimeUnit.SECONDS));

// Lock an already-managed entity:
session.lock(managed, LockModeType.PESSIMISTIC_WRITE, Timeouts.NO_WAIT);

// Lock modes:
// PESSIMISTIC_READ  -> SELECT FOR SHARE
// PESSIMISTIC_WRITE -> SELECT FOR UPDATE

What SQL is generated by session.find(Product.class, id, LockModeType.PESSIMISTIC_WRITE)?
What does Timeouts.NO_WAIT do in a pessimistic lock in Hibernate 7?

22. What is the @ManyToMany relationship in Hibernate 7 and how do you map it?

A many-to-many relationship requires a join table. Each entity can be associated with multiple instances of the other.

@Entity
public class Student {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
    private String name;

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(
        name="student_course",
        joinColumns=@JoinColumn(name="student_id"),
        inverseJoinColumns=@JoinColumn(name="course_id")
    )
    private Set<Course> courses = new HashSet<>();

    public void enrollIn(Course c) {
        courses.add(c);
        c.getStudents().add(this);  // keep both sides in sync!
    }
}

@Entity
public class Course {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
    private String title;

    @ManyToMany(mappedBy="courses")  // inverse side
    private Set<Student> students = new HashSet<>();
}

// When you need extra columns on the join: use an explicit join entity!
@Entity public class Enrollment {
    @Id @GeneratedValue private Long id;
    @ManyToOne @JoinColumn(name="student_id") private Student student;
    @ManyToOne @JoinColumn(name="course_id")  private Course course;
    private LocalDate enrolledAt;  // impossible with @ManyToMany
    private String grade;
}

What does Hibernate 7 create in the database to represent a @ManyToMany relationship?
When should you replace @ManyToMany with an explicit join entity class?

23. What is Hibernate's flush behaviour and how does it affect SQL execution?

Flushing synchronises the in-memory persistence context with the database by sending pending SQL. Flush does NOT commit the transaction.

Hibernate flush modes
FlushModeWhen SQL sentUse case
AUTO (default)Before queries and at commitNormal transactional operations
COMMITOnly at commitRead-heavy operations
ALWAYSBefore every queryStrict consistency required
MANUALOnly explicit session.flush()Bulk operations
// AUTO flush mode (default):
Product p = new Product("Laptop", new BigDecimal("999"));
session.persist(p);  // INSERT scheduled, NOT sent yet

// Query triggers flush in AUTO mode:
Long count = session.createQuery("SELECT COUNT(p) FROM Product p", Long.class)
    .getSingleResult();  // INSERT flushed first so count is accurate

// Explicit flush:
session.flush();  // sends SQL but does NOT commit

// Check for pending changes:
session.isDirty();  // true if unflushed changes exist

// SQL ordering at flush: INSERT -> UPDATE -> DELETE
// Prevents FK constraint violations

What triggers an automatic flush in Hibernate 7 with DEFAULT flush mode?
Does calling session.flush() commit the database transaction?

24. What are named queries in Hibernate 7 and how are they type-safe with TypedQueryReference?

Named queries are pre-defined HQL/SQL queries. Hibernate 7 (Jakarta Persistence 3.2) adds TypedQueryReference for type-safe, compile-time references via the static metamodel.

@Entity
@NamedQuery(
    name="Product.findByCategory",
    query="FROM Product p WHERE p.category = :category ORDER BY p.price ASC"
)
public class Product {
    @Id private Long id;
    private String name;
    private String category;
}

// Traditional way (error-prone string reference):
List<Product> p = session
    .createNamedQuery("Product.findByCategory", Product.class)
    .setParameter("category", "electronics")
    .getResultList();
// Typo in "Product.findByCategory" = runtime exception!

// Jakarta Persistence 3.2 / Hibernate 7:
// TypedQueryReference in static metamodel:
// Product_: public static final TypedQueryReference<Product> QUERY_FIND_BY_CATEGORY;

List<Product> p2 = session
    .createQuery(Product_.QUERY_FIND_BY_CATEGORY)  // compile-time safe!
    .setParameter("category", "electronics")
    .getResultList();
// Renaming the named query = compile error, not runtime exception!

What problem does TypedQueryReference solve for named queries?
Where are @NamedQuery annotations typically placed in Hibernate 7?

25. What is the @Inheritance mapping in Hibernate 7 and what strategies are available?

Three strategies map a Java inheritance hierarchy to database tables, each with different performance and schema trade-offs.

Inheritance strategies
StrategySchemaProsCons
SINGLE_TABLEOne table for all subclassesSimple; best query performanceSparse NULLs; no NOT NULL on subtype columns
JOINEDOne table per classNormalised; subtype constraints possibleJOIN per query; slower polymorphic queries
TABLE_PER_CLASSIndependent table per concrete classNo JOINs for single-type queriesExpensive UNION for polymorphic queries
// SINGLE_TABLE (most common):
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="payment_type", discriminatorType=DiscriminatorType.STRING)
public abstract class Payment {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
    private BigDecimal amount;
}

@Entity @DiscriminatorValue("CREDIT_CARD")
public class CreditCardPayment extends Payment {
    private String cardNumber;
}

@Entity @DiscriminatorValue("BANK_TRANSFER")
public class BankTransferPayment extends Payment {
    private String iban;
}

// JOINED:
@Entity @Inheritance(strategy=InheritanceType.JOINED)
public abstract class Vehicle {
    @Id @GeneratedValue private Long id;
    private String registration;
}
@Entity @Table(name="cars") public class Car extends Vehicle { private int doors; }

Which Hibernate inheritance strategy stores all subclass fields in one table using a discriminator column?
What is the trade-off of the JOINED inheritance strategy?

26. What is the @Filter and auto-enabled filters feature in Hibernate 7?

Hibernate Filters are parameterised WHERE clause fragments applied to a Session. Hibernate 7 adds auto-enabled filters that activate automatically without explicit session.enableFilter() calls.

@FilterDef(
    name="activeFilter",
    parameters=@ParamDef(name="isActive", type=Boolean.class)
)
@Filter(name="activeFilter", condition="is_active = :isActive")
@Entity
public class Product {
    @Id private Long id;
    private String name;
    private boolean isActive;
}

// Enable for this session:
session.enableFilter("activeFilter").setParameter("isActive", true);
// All Product queries now silently include: AND is_active = true
List<Product> active = session.createQuery("FROM Product", Product.class).getResultList();
session.disableFilter("activeFilter");

// HIBERNATE 7: auto-enabled filter for multi-tenancy
@FilterDef(
    name="tenantFilter",
    parameters=@ParamDef(name="tenantId", type=Long.class),
    autoEnabled=true  // no session.enableFilter() needed!
)
@Filter(name="tenantFilter", condition="tenant_id = :tenantId")
@Entity public class Order { ... }
// FilterDefContributor SPI resolves tenantId from ThreadLocal automatically

What is the advantage of Hibernate 7's auto-enabled filters?
At what scope do Hibernate filters apply when enabled?

27. What is key-based pagination in Hibernate 7 and how does it differ from offset pagination?

Traditional offset pagination (LIMIT N OFFSET M) gets slower on deep pages. Key-based pagination uses a WHERE clause on the last key value, making each page O(1) regardless of depth.

// OFFSET PAGINATION (gets slower at depth):
List<Product> page1000 = session
    .createQuery("FROM Product ORDER BY id ASC", Product.class)
    .setFirstResult(19_980)  // DB must scan and skip 19,980 rows!
    .setMaxResults(20)
    .getResultList();

// HIBERNATE 7: Key-based pagination (O(1) at any depth)
import org.hibernate.query.KeyedPage;
import org.hibernate.query.KeyedResultList;

// First page:
KeyedResultList<Product> page = session
    .createQuery("FROM Product", Product.class)
    .getKeyedResultList(
        KeyedPage.firstPage(20, Order.asc(Product_.id))
    );
List<Product> products = page.getResultList();

// Next page (use key from previous result):
if (page.getNextPage() != null) {
    KeyedResultList<Product> next = session
        .createQuery("FROM Product", Product.class)
        .getKeyedResultList(page.getNextPage());
}
// Generated SQL: WHERE id > :lastId ORDER BY id ASC LIMIT 20

Why is key-based pagination more efficient than offset for deep pages?
What type does Hibernate 7's key-based pagination return instead of a plain List?

28. What is Jakarta Data 1.0 and how does it integrate with Hibernate 7?

Jakarta Data 1.0 is a new specification in Jakarta EE 11 providing a standardised type-safe repository model. Hibernate 7 provides a complete implementation via hibernate-repositories module.

import jakarta.data.repository.*;

@Repository
public interface ProductRepository extends CrudRepository<Product, Long> {

    // Method name derivation:
    List<Product> findByStatus(ProductStatus status);
    List<Product> findByPriceLessThan(BigDecimal maxPrice);
    long countByStatus(ProductStatus status);

    // @Find: type-safe field query
    @Find
    List<Product> findByCategory(
        @By(Product_.CATEGORY) String category,
        @OrderBy(Product_.PRICE) Sort.Direction dir
    );

    // @Query: JPQL
    @Query("FROM Product WHERE status = :status AND price < :maxPrice")
    List<Product> findCheapActive(
        @Param("status") ProductStatus status,
        @Param("maxPrice") BigDecimal maxPrice
    );

    // Key-based pagination:
    Page<Product> findByCategory(String category, PageRequest page);
}

// Usage - inject like any Spring bean:
@Autowired ProductRepository repo;
List<Product> active = repo.findByStatus(ProductStatus.ACTIVE);

What makes Jakarta Data 1.0 repositories different from manually implementing DAO classes?
What annotation on a Jakarta Data repository method accepts JPQL queries?

29. What is the @NaturalId feature in Hibernate 7 and what is @NaturalIdClass?

A natural ID is a business-meaningful unique identifier distinct from the surrogate PK. Hibernate 7 adds @NaturalIdClass for composite natural IDs.

@Entity
public class Book {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;         // surrogate PK (internal)

    @NaturalId               // business identifier (external)
    @Column(unique=true, nullable=false)
    private String isbn;

    private String title;
}

// Optimised lookup (uses L2 cache):
Book book = session.byNaturalId(Book.class)
    .using("isbn", "978-0-13-468599-1").load();

// @NaturalIdClass: COMPOSITE natural IDs (NEW in Hibernate 7)
public class EmployeeNaturalId {
    String companyCode;
    String employeeNumber;
    // equals() and hashCode() required
}

@Entity
@NaturalIdClass(EmployeeNaturalId.class)  // NEW in Hibernate 7
public class Employee {
    @Id @GeneratedValue private Long id;
    @NaturalId String companyCode;
    @NaturalId String employeeNumber;
    private String name;
}

// Lookup by composite natural ID:
Employee emp = session.byNaturalId(Employee.class)
    .using("companyCode", "ACME")
    .using("employeeNumber", "EMP-001").load();

What is the main advantage of using @NaturalId over a plain JPQL WHERE clause?
What new Hibernate 7 feature enables composite (multi-field) natural IDs?

30. How does Hibernate 7 support vector data types for AI/ML applications?

Hibernate 7 (especially 7.2+) adds native support for vector data types used in AI embeddings, enabling semantic search alongside relational data.

import org.hibernate.annotations.Array;
import org.hibernate.type.SqlTypes;

@Entity
public class Document {
    @Id @GeneratedValue private Long id;
    private String content;

    // Float32 vector (e.g. OpenAI text-embedding-3 embeddings):
    @JdbcTypeCode(SqlTypes.VECTOR)
    @Array(length=1536)  // number of dimensions
    private float[] embedding;

    // Binary vector (Hibernate 7.2+):
    @JdbcTypeCode(SqlTypes.VECTOR_BINARY)
    @Array(length=24)
    private byte[] binaryVector;

    // Half-precision float16 (Hibernate 7.2+):
    @JdbcTypeCode(SqlTypes.VECTOR_FLOAT16)
    @Array(length=1536)
    private float[] halfPrecisionEmbedding;
}

// Vector similarity search (pgvector required):
List<Object[]> similar = session
    .createNativeQuery(
        "SELECT d.id, d.content, d.embedding <=> :queryVec AS distance "
        + "FROM document d ORDER BY distance ASC LIMIT 10", Object[].class)
    .setParameter("queryVec", queryEmbedding)
    .getResultList();

// HQL distance functions (Hibernate 7.1+):
List<Document> results = session
    .createQuery("FROM Document d ORDER BY cosine_distance(d.embedding, :vec) ASC", Document.class)
    .setParameter("vec", queryEmbedding).setMaxResults(10).getResultList();

What Hibernate 7 annotations are used to map a float array as a database vector column?
What is the practical use case for Hibernate 7's vector type support?

31. What are the key removed APIs in Hibernate 7 and how do you migrate?

Hibernate 7 removes all APIs deprecated in Hibernate 6.x. Anything deprecated in 6.x is hard-deleted in 7.0 with no fallback.

Key API removals in Hibernate 7
RemovedReplacement
session.save()session.persist()
session.get()session.find()
session.delete()session.remove()
session.update()session.merge()
session.saveOrUpdate()session.merge()
session.lock(detached)Load fresh with lock: session.find(Class, id, LockMode)
session.refresh(detached)Only on managed entities
hibernate.allow_refresh_detached_entityRemoved entirely
Configuration.addClass()Configuration.addAnnotatedClass()
hbm.xml mapping filesAnnotation-based mapping or orm.xml
Ehcache 2.x integrationEhcache 3.x, Caffeine, or Infinispan
// Automated migration:
// mvn rewrite:run -Drewrite.activeRecipes=org.openrewrite.hibernate.MigrateToHibernate70

// Manual: detached entity handling
// BEFORE:
session.update(detachedOrder);       // REMOVED!
detachedOrder.setStatus("DONE");
// AFTER:
Order managed = session.merge(detachedOrder);
managed.setStatus("DONE");

What is the Hibernate 7 replacement for the removed session.save() method?
What happened to hbm.xml mapping file support in Hibernate 7?

32. What is @SQLRestriction and @SQLJoinTableRestriction in Hibernate 7?

Hibernate 7 adds @SQLRestriction (replacing removed @Where) to apply a permanent SQL WHERE clause to an entity or collection mapping.

import org.hibernate.annotations.SQLRestriction;

// Soft-delete: only ever load non-deleted records
@Entity
@SQLRestriction("deleted_at IS NULL")  // applied to ALL queries
public class Product {
    @Id private Long id;
    private String name;
    private LocalDateTime deletedAt;

    public void softDelete() { this.deletedAt = LocalDateTime.now(); }
}
// session.find(Product.class, id) -> only finds non-deleted products
// 'FROM Product' HQL -> only returns non-deleted products

// On a collection:
@OneToMany(mappedBy="category")
@SQLRestriction("deleted_at IS NULL")  // only active products in collection
private List<Product> activeProducts;

// @SQLJoinTableRestriction: restrict on join table for @ManyToMany
@ManyToMany
@JoinTable(name="student_course")
@SQLJoinTableRestriction("enrolled_at > CURRENT_DATE - INTERVAL '1 year'")
private List<Course> recentCourses;

// NOTE: @Where (old annotation) was REMOVED in Hibernate 7
// @Where(clause="deleted_at IS NULL")  <- REMOVED
// @SQLRestriction("deleted_at IS NULL") <- USE THIS

What did @SQLRestriction replace in Hibernate 7?
What is the benefit of @SQLRestriction("deleted_at IS NULL") on an entity?

33. How does Hibernate 7 handle schema validation and generation (hbm2ddl)?

Hibernate can validate or generate the DB schema from entity mappings. Controlled by hibernate.hbm2ddl.auto.

hbm2ddl.auto values
ValueBehaviourUse in
noneNo schema actionProduction (use Flyway/Liquibase)
validateValidates entity mappings match schema; fails on mismatchProduction safety check
updateAdds missing columns/tables; never dropsDevelopment (risky in production)
createDrops and recreates all tables on startupDevelopment/testing
create-dropCreates on startup; drops on SessionFactory closeUnit tests
# Recommended production setup:
spring:
  jpa:
    hibernate:
      ddl-auto: none       # Hibernate does NOT touch schema
  flyway:
    enabled: true          # Flyway manages schema with versioned migrations
    locations: classpath:db/migration

# Development:
spring:
  jpa:
    hibernate:
      ddl-auto: create-drop  # fresh schema each run

# Flyway migration files:
# db/migration/V1__create_products_table.sql
# db/migration/V2__add_category_to_products.sql

What does hibernate.hbm2ddl.auto=validate do at startup?
What is the recommended approach for managing schema in a production Hibernate 7 application?

34. What are Hibernate 7's improvements to multi-tenancy support?

Hibernate 7 enhances multi-tenancy with better integration with auto-enabled filters for discriminator-based tenancy.

Multi-tenancy strategies
StrategyIsolationUse case
DATABASEHighest - one DB per tenantRegulated industries; highest cost
SCHEMAHigh - one schema per tenantGood balance; PostgreSQL/Oracle
DISCRIMINATORLowest - tenant_id columnSaaS with many small tenants; lowest cost
// DISCRIMINATOR (most common in Hibernate 7)
@FilterDef(
    name="tenantFilter",
    parameters=@ParamDef(name="tenantId", type=String.class),
    autoEnabled=true  // Hibernate 7: auto-enabled!
)
@Filter(name="tenantFilter", condition="tenant_id = :tenantId")
@Entity
public class Order {
    @Id private Long id;
    private String tenantId;  // discriminator column
    private BigDecimal total;
}

// FilterDefContributor SPI: auto-resolves tenantId from ThreadLocal
public class TenantFilterContributor implements FilterDefContributor {
    @Override
    public void contribute(FilterDefTarget target) {
        target.registerFilterDefinition(
            FilterDefinition.of("tenantFilter",
                Map.of("tenantId", TenantContext::getCurrentTenantId))
        );
    }
}

// DATABASE strategy: supply different connections per tenant
public class TenantConnectionProvider implements MultiTenantConnectionProvider<String> {
    @Override
    public Connection getConnection(String tenantId) {
        return dataSourceMap.get(tenantId).getConnection();
    }
}

Which multi-tenancy strategy uses a tenant_id column in shared tables?
How do Hibernate 7 auto-enabled filters improve multi-tenancy?

35. What is the @Check constraint and @ColumnDefault annotation in Hibernate 7?

Hibernate 7 provides DDL-level annotations for database constraints and default values applied during schema generation.

@Entity
@Check(name="price_positive", constraints="price > 0")  // table-level check
public class Product {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
    private String name;

    @Column(nullable=false)
    @Check(name="stock_non_negative", constraints="stock >= 0")  // column-level
    private int stock;

    @Column(precision=10, scale=2)
    private BigDecimal price;

    @ColumnDefault("'ACTIVE'")  // DEFAULT 'ACTIVE' in DDL
    @Column(nullable=false)
    private String status;

    @ColumnDefault("CURRENT_TIMESTAMP")
    @Generated(EventType.INSERT)  // re-read from DB after INSERT
    private LocalDateTime createdAt;
}

// Generated DDL:
// CREATE TABLE product (
//   id BIGINT NOT NULL,
//   stock INTEGER NOT NULL CHECK (stock >= 0),
//   price NUMERIC(10,2),
//   status VARCHAR(255) DEFAULT 'ACTIVE',
//   created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
//   CONSTRAINT price_positive CHECK (price > 0)
// )

What is the difference between @ColumnDefault and a Java field initializer in Hibernate 7?
What does @Generated(EventType.INSERT) tell Hibernate 7 to do after an INSERT?

36. What is @BatchSize and how does it solve the N+1 problem differently from JOIN FETCH?

@BatchSize loads lazy-loaded collections or proxies in batches using IN clauses rather than one-by-one. Unlike JOIN FETCH it works correctly with pagination.

@Entity
public class Customer {
    @Id private Long id;
    private String name;

    @OneToMany(mappedBy="customer", fetch=FetchType.LAZY)
    @BatchSize(size=25)  // load 25 collections at once
    private List<Order> orders;
}

// Without @BatchSize:
// 1 query: SELECT * FROM customers LIMIT 100
// 100 queries: SELECT * FROM orders WHERE customer_id=1 ... customer_id=100
// Total: 101 queries

// With @BatchSize(size=25):
// 1 query: SELECT * FROM customers LIMIT 100
// 4 queries: SELECT * FROM orders WHERE customer_id IN (1..25)
//             SELECT * FROM orders WHERE customer_id IN (26..50)
//             SELECT * FROM orders WHERE customer_id IN (51..75)
//             SELECT * FROM orders WHERE customer_id IN (76..100)
// Total: 5 queries!

// Global default:
# spring.jpa.properties.hibernate.default_batch_fetch_size=100

// @BatchSize on entity for proxy loading:
@Entity @BatchSize(size=20)
public class Product { ... }

What SQL technique does @BatchSize use to load multiple lazy collections efficiently?
Why is @BatchSize preferred over JOIN FETCH when implementing pagination?

37. What is Hibernate 7's @Struct mapping for database composite types?

Hibernate 7 adds @Struct for mapping Java records to database composite/structured types (native types in PostgreSQL, Oracle, DB2) stored as a single column value.

import org.hibernate.annotations.Struct;

@Embeddable
@Struct(name="address_type")  // maps to the DB composite type
public record AddressType(
    String street,
    String city,
    String postcode,
    String countryCode
) {}

@Entity
public class Customer {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id;
    private String name;

    @Column(name="shipping_address")  // single column of type address_type!
    private AddressType shippingAddress;
}

// PostgreSQL DDL:
// CREATE TYPE address_type AS (
//   street       VARCHAR(255),
//   city         VARCHAR(100),
//   postcode     VARCHAR(10),
//   country_code VARCHAR(2)
// );
// CREATE TABLE customer (
//   id               BIGINT PRIMARY KEY,
//   name             VARCHAR(255),
//   shipping_address address_type  -- single composite column!
// );

// HQL querying the struct:
List<Customer> london = session
    .createQuery("FROM Customer c WHERE c.shippingAddress.city = :city", Customer.class)
    .setParameter("city", "London").getResultList();
// Generated: WHERE (shipping_address).city = 'London'

What database feature does Hibernate 7's @Struct annotation map to?
What is the advantage of @Struct over plain @Embedded in Hibernate 7?

38. What are Hibernate 7's logging improvements for SQL and parameter binding?

Hibernate 7 replaces the deprecated use_sql_comments property with a cleaner logging hierarchy. SQL parameter binding logging is now available natively without a JDBC proxy driver.

# Hibernate 7 logging configuration:
logging:
  level:
    # SQL statement logging:
    org.hibernate.SQL: DEBUG            # shows the SQL

    # SQL parameter values (NEW - no P6Spy proxy needed!):
    org.hibernate.orm.jdbc.bind: TRACE  # logs actual parameter values
    # Output example:
    # binding parameter (1:VARCHAR) <- [alice@example.com]
    # binding parameter (2:BIGINT)  <- [42]

    # Result set extraction:
    org.hibernate.orm.jdbc.extract: TRACE

spring:
  jpa:
    show-sql: false   # deprecated - use logging.level.org.hibernate.SQL
    properties:
      hibernate:
        format_sql: true
        generate_statistics: true
        # REMOVED in Hibernate 7:
        # use_sql_comments: true  <- use logging.level instead

// Hibernate statistics:
Statistics stats = sf.getStatistics();
stats.setStatisticsEnabled(true);
System.out.println("Queries: " + stats.getQueryExecutionCount());
System.out.println("L2 hits: " + stats.getSecondLevelCacheHitCount());
stats.logSummary();

How do you enable SQL parameter value logging in Hibernate 7 without a JDBC proxy?
What Hibernate 7 config property was removed in favour of the org.hibernate.SQL logging category?

39. How does Hibernate 7 work with Spring Boot 4 - what is auto-configured?

In Spring Boot 4, Hibernate 7 is the default JPA provider auto-configured transparently when spring-boot-starter-data-jpa is on the classpath.

<!-- spring-boot-starter-data-jpa includes:
     - hibernate-core 7.x
     - spring-data-jpa
     - HikariCP connection pool
     - jakarta.persistence-api 3.2 -->

# Complete application.yml for Hibernate 7 in Spring Boot 4:
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: ${DB_USER}
    password: ${DB_PASSWORD}
    hikari:
      maximum-pool-size: 20
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false
    open-in-view: false  # CRITICAL: disable OSIV in production!
    properties:
      hibernate:
        format_sql: true
        default_batch_fetch_size: 100
        jdbc:
          batch_size: 50
          order_inserts: true
          order_updates: true

logging:
  level:
    org.hibernate.SQL: DEBUG
    org.hibernate.orm.jdbc.bind: TRACE

What does spring.jpa.open-in-view=false prevent in Spring Boot 4 + Hibernate 7?
What does hibernate.jdbc.batch_size=50 with hibernate.jdbc.order_inserts=true achieve?

40. What are the key Hibernate 7 vs Hibernate 6 differences interviewers ask about?

The most common comparison question in enterprise Java interviews. Here is a structured summary of all major changes.

Hibernate 6 vs Hibernate 7
DimensionHibernate 6Hibernate 7
GA releaseJune 2022May 20, 2025
Jakarta Persistence3.13.2 (complete)
Jakarta DataNot supported1.0 (complete)
LicenseLGPL for EnversAll modules Apache Software License v2
Detached reassociationDeprecated (still worked)COMPLETELY REMOVED (merge() only)
StatelessSession L2 cacheBypassedUses L2 cache by default
hbm.xml supportDeprecatedREMOVED
Ehcache 2.xDeprecatedREMOVED (use Ehcache 3/Caffeine)
@NaturalIdClassNot availableNEW: composite natural IDs
@EmbeddedColumnNamingNot availableNEW (incubating): prefix/suffix for embeddables
Vector typesNot availableNEW: VECTOR, VECTOR_BINARY, VECTOR_FLOAT16
@SQLRestrictionNot available (used @Where)NEW: replaces @Where
Auto-enabled filtersNot availableNEW: FilterDef autoEnabled
SelectionSpecificationNot availableNEW type-safe query builder
Key-based paginationPreview (6.5)Full support
FindOptions / TimeoutsNot availableNEW: Jakarta Persistence 3.2 API
TypedQueryReferenceNot availableNEW: type-safe named query refs
@StructPreviewFull support
Spring Boot versionSpring Boot 3.xSpring Boot 4.x
What is the most impactful breaking change for teams migrating from Hibernate 6 to Hibernate 7?
What major new specification does Hibernate 7 implement that Hibernate 6 did not support at all?
«
»

Comments & Discussions