88import java .util .HashSet ;
99import java .util .Map ;
1010import java .util .Set ;
11- import java .util .concurrent .ConcurrentHashMap ;
1211
12+ import org .hibernate .SessionFactory ;
13+ import org .hibernate .SessionFactoryObserver ;
1314import org .hibernate .boot .internal .ClassLoaderAccessImpl ;
1415import org .hibernate .boot .registry .classloading .spi .ClassLoaderService ;
1516import org .hibernate .engine .spi .SessionFactoryImplementor ;
2930
3031import jakarta .validation .ConstraintViolation ;
3132import jakarta .validation .ConstraintViolationException ;
32- import jakarta .validation .TraversableResolver ;
3333import jakarta .validation .Validator ;
3434import jakarta .validation .ValidatorFactory ;
3535
36- import static jakarta .validation .Validation .buildDefaultValidatorFactory ;
3736import static org .hibernate .internal .util .collections .CollectionHelper .setOfSize ;
3837
3938/**
4443 */
4544//FIXME review exception model
4645public class BeanValidationEventListener
47- implements PreInsertEventListener , PreUpdateEventListener , PreDeleteEventListener , PreUpsertEventListener {
46+ implements PreInsertEventListener , PreUpdateEventListener , PreDeleteEventListener , PreUpsertEventListener ,
47+ SessionFactoryObserver {
4848
4949 private static final CoreMessageLogger LOG = Logger .getMessageLogger (
5050 MethodHandles .lookup (),
5151 CoreMessageLogger .class ,
5252 BeanValidationEventListener .class .getName ()
5353 );
5454
55- private ValidatorFactory factory ;
56- private final ConcurrentHashMap < EntityPersister , Set < String >> associationsPerEntityPersister = new ConcurrentHashMap <>() ;
55+ private HibernateTraversableResolver traversableResolver ;
56+ private Validator validator ;
5757 private GroupsPerOperation groupsPerOperation ;
58- boolean initialized ;
59-
60- /**
61- * Constructor used in an environment where validator factory is injected (JPA2).
62- *
63- * @param factory The {@code ValidatorFactory} to use to create {@code Validator} instance(s)
64- * @param settings Configured properties
65- */
66- public BeanValidationEventListener (
67- ValidatorFactory factory , Map <String ,Object > settings , ClassLoaderService classLoaderService ) {
68- init ( factory , settings , classLoaderService );
69- }
7058
71- public void initialize (Map <String ,Object > settings , ClassLoaderService classLoaderService ) {
72- if ( !initialized ) {
73- init ( buildDefaultValidatorFactory (), settings , classLoaderService );
74- }
59+ public BeanValidationEventListener (
60+ ValidatorFactory factory , Map <String , Object > settings , ClassLoaderService classLoaderService ) {
61+ traversableResolver = new HibernateTraversableResolver ();
62+ validator = factory .usingContext ()
63+ .traversableResolver ( traversableResolver )
64+ .getValidator ();
65+ groupsPerOperation = GroupsPerOperation .from ( settings , new ClassLoaderAccessImpl ( classLoaderService ) );
7566 }
7667
77- private void init (ValidatorFactory factory , Map <String ,Object > settings , ClassLoaderService classLoaderService ) {
78- this .factory = factory ;
79- groupsPerOperation = GroupsPerOperation .from ( settings , new ClassLoaderAccessImpl ( classLoaderService ) );
80- initialized = true ;
68+ @ Override
69+ public void sessionFactoryCreated (SessionFactory factory ) {
70+ SessionFactoryImplementor implementor = factory .unwrap ( SessionFactoryImplementor .class );
71+ implementor
72+ .getMappingMetamodel ()
73+ .forEachEntityDescriptor ( entityPersister -> traversableResolver .addPersister ( entityPersister , implementor ) );
8174 }
8275
8376 public boolean onPreInsert (PreInsertEvent event ) {
@@ -129,10 +122,6 @@ private <T> void validate(
129122 if ( object == null || persister .getRepresentationStrategy ().getMode () != RepresentationMode .POJO ) {
130123 return ;
131124 }
132- TraversableResolver tr = new HibernateTraversableResolver ( persister , associationsPerEntityPersister , sessionFactory );
133- Validator validator = factory .usingContext ()
134- .traversableResolver ( tr )
135- .getValidator ();
136125 final Class <?>[] groups = groupsPerOperation .get ( operation );
137126 if ( groups .length > 0 ) {
138127 final Set <ConstraintViolation <T >> constraintViolations = validator .validate ( object , groups );
@@ -153,7 +142,7 @@ private <T> void validate(
153142 builder .append ( toString ( groups ) );
154143 builder .append ( "\n List of constraint violations:[\n " );
155144 for ( ConstraintViolation <?> violation : constraintViolations ) {
156- builder .append ( "\t " ).append ( violation .toString () ).append ("\n " );
145+ builder .append ( "\t " ).append ( violation .toString () ).append ( "\n " );
157146 }
158147 builder .append ( "]" );
159148
0 commit comments