# Unexpected association fetch triggered by JSR-303 (Bean Validation) integration

**URL:** <https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101>\
**Category:** Hibernate ORM\
**Created:** [February 21, 2025, 4:33am UTC](https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101 "2025-02-21T04:33:28Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kamii0909](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/kamii0909/32/3860_2.png) [@Kamii0909](https://discourse.hibernate.org/u/Kamii0909)\
**Post date:** [February 21, 2025, 4:33am UTC](https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101/1 "2025-02-21T04:33:28Z")

</div>

Validation of lazy association through PreUpdateEvent by Hibernate and JSR 303 integration might trigger additional fetches.

Full reproducer: [GitHub - Kamii0909/test-case-template-hibernate-orm-6](https://github.com/Kamii0909/test-case-template-hibernate-orm-6)  
Fail for 6.x up to latest.

Specifically, `@Size(max = 3) @ElementCollection private List<Long> lazyCols` will be fetched. Is this intended? JPA states that: `Attributes that have not been loaded must not be loaded`, so I would assume this is a bug. This behavior is not observed with bytecode enhancement, which is at least consistency issue.

This behavior is caused by `Hibernate.isPropertyInitialized(Object entity, String propertyName)` quickly bailing out (return true) for non-bytecode enhanced entity, and HibernateTraversableResolver reliance on this method to skip validation:

```auto
public boolean isReachable(...) {
return Hibernate.isInitialized( traversableObject ) 
    && Hibernate.isPropertyInitialized( traversableObject, traversableProperty.getName() );
}

```

Turning on byte-code enhancement is a quick hack since bytecode enhanced entities are treated differently by `isPropertyInitialized` and properly checked, but all bytecode enhancement options are deprecated in recent Hibernate versions, both runtime or through build tool integrations. Entity returned by `getReferenceById` is a proper HibernateProxy in all configurations, so `isPropertyInitialized` will work, but since you can’t update that, no validation will be triggered anyway.

A fix could be:

- Properly implementing `Hibernate.isPropertyInitialized` even for non-enhanced or proxied entities. This might prompt some reflection and could upset AoT environment, which is backward compatibility concern. And as a side effect, client can’t customize property access strategy.
- Introduce additional `Hibernate.isPropertyInitialized` overload that additionally accepts `Supplier<Object> property` of some sort, which HibernateTraversableResolver could pass the actual uninitialized PersistentCollection to. This left the property access strategy (reflection/getter…) to the caller. I don’t think the current TraversableResolver interface even has enough information for HibernateTraversableResolver to provide such information.
- Same as above, but let HibernateTraversableResolver additionally check for `Hibernate.isInitialized(getProperty(entity, "propertyName"))`. Still facing the same implementation issue as above, but can keep the wildly used public API `org.hibernate.Hibernate` the same.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [February 24, 2025, 5:21pm UTC](https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101/2 "2025-02-24T17:21:41Z")

</div>

As far as I can see, the reason this is only implemented for bytecode enhanced entities is the fact that no session factory and hence metadata to access entity state is available for non-enhanced entities.  
If you want a portable and working solution that also support non-enhanced entities, you will have to use `PersistenceUnitUtil`, which you can acquire through `jakarta.persistence.EntityManagerFactory#getPersistenceUnitUtil`. That has methods `isLoaded` and since JPA 3.2/ORM 7.0 also `load` methods which you can use for this purpose.

---

<div class="post-metadata">

**Author:** ![Kamii0909](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/kamii0909/32/3860_2.png) [@Kamii0909](https://discourse.hibernate.org/u/Kamii0909)\
**Post date:** [February 25, 2025, 3:47am UTC](https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101/3 "2025-02-25T03:47:11Z")

</div>

My issue is with HibernateTraversableResolver lax implemention of `isReachable` triggering unneccessary fetches. Should I make a PR to address it with your suggestion? Replacing `Hibernate.xxx` with corresponding `PersistenceUnitUtil` should work.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [February 25, 2025, 10:36am UTC](https://discourse.hibernate.org/t/unexpected-association-fetch-triggered-by-jsr-303-bean-validation-integration/11101/4 "2025-02-25T10:36:33Z")

</div>

> [@Kamii0909](#):
>
> Should I make a PR to address it with your suggestion?

Yeah, that sounds good to me.
