Skip to content

Commit 2901ff0

Browse files
committed
HHH-19843 Get persister from session factory if session is not available
1 parent f79de81 commit 2901ff0

File tree

3 files changed

+129
-6
lines changed

3 files changed

+129
-6
lines changed

hibernate-core/src/main/java/org/hibernate/boot/beanvalidation/BeanValidationEventListener.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
1414
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
1515
import org.hibernate.engine.spi.SessionFactoryImplementor;
16+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1617
import org.hibernate.event.spi.PreCollectionUpdateEvent;
1718
import org.hibernate.event.spi.PreCollectionUpdateEventListener;
1819
import org.hibernate.event.spi.PreDeleteEvent;
@@ -50,15 +51,18 @@ public class BeanValidationEventListener
5051
private final HibernateTraversableResolver traversableResolver;
5152
private final Validator validator;
5253
private final GroupsPerOperation groupsPerOperation;
54+
private final SessionFactoryImplementor sessionFactory;
5355

5456
public BeanValidationEventListener(
55-
ValidatorFactory factory, Map<String, Object> settings, ClassLoaderService classLoaderService) {
56-
traversableResolver = new HibernateTraversableResolver();
57-
validator =
57+
ValidatorFactory factory, Map<String, Object> settings, ClassLoaderService classLoaderService,
58+
SessionFactoryImplementor sessionFactory) {
59+
this.traversableResolver = new HibernateTraversableResolver();
60+
this.validator =
5861
factory.usingContext()
5962
.traversableResolver( traversableResolver )
6063
.getValidator();
61-
groupsPerOperation = GroupsPerOperation.from( settings, new ClassLoaderAccessImpl( classLoaderService ) );
64+
this.groupsPerOperation = GroupsPerOperation.from( settings, new ClassLoaderAccessImpl( classLoaderService ) );
65+
this.sessionFactory = sessionFactory;
6266
}
6367

6468
@Override
@@ -110,11 +114,21 @@ public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
110114
final Object entity = castNonNull( event.getCollection().getOwner() );
111115
validate(
112116
entity,
113-
event.getSession().getEntityPersister( event.getAffectedOwnerEntityName(), entity ),
117+
getEntityPersister( event.getSession(), event.getAffectedOwnerEntityName(), entity ),
114118
GroupsPerOperation.Operation.UPDATE
115119
);
116120
}
117121

122+
private EntityPersister getEntityPersister(SharedSessionContractImplementor session, String entityName, Object entity) {
123+
if ( session != null ) {
124+
return session.getEntityPersister( entityName, entity );
125+
}
126+
return entityName == null
127+
? sessionFactory.getMappingMetamodel().getEntityDescriptor( entity.getClass().getName() )
128+
: sessionFactory.getMappingMetamodel().getEntityDescriptor( entityName )
129+
.getSubclassEntityPersister( entity, sessionFactory );
130+
}
131+
118132
private <T> void validate(
119133
T object,
120134
EntityPersister persister,

hibernate-core/src/main/java/org/hibernate/boot/beanvalidation/TypeSafeActivator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private static void setupListener(
151151
final var classLoaderService = serviceRegistry.requireService( ClassLoaderService.class );
152152
final var cfgService = serviceRegistry.requireService( ConfigurationService.class );
153153
final var listener =
154-
new BeanValidationEventListener( validatorFactory, cfgService.getSettings(), classLoaderService );
154+
new BeanValidationEventListener( validatorFactory, cfgService.getSettings(), classLoaderService, sessionFactory );
155155
final var listenerRegistry = sessionFactory.getEventListenerRegistry();
156156
listenerRegistry.addDuplicationStrategy( DuplicationStrategyImpl.INSTANCE );
157157
listenerRegistry.appendListeners( EventType.PRE_INSERT, listener );
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.annotations.beanvalidation;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.JoinColumn;
10+
import jakarta.persistence.ManyToOne;
11+
import jakarta.persistence.OneToMany;
12+
import jakarta.persistence.Table;
13+
import jakarta.validation.ConstraintViolationException;
14+
import jakarta.validation.constraints.Size;
15+
import org.hibernate.cfg.AvailableSettings;
16+
import org.hibernate.testing.orm.junit.DomainModel;
17+
import org.hibernate.testing.orm.junit.Jira;
18+
import org.hibernate.testing.orm.junit.ServiceRegistry;
19+
import org.hibernate.testing.orm.junit.SessionFactory;
20+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
21+
import org.hibernate.testing.orm.junit.Setting;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.Test;
24+
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
31+
@SessionFactory
32+
@DomainModel(annotatedClasses = {
33+
CollectionActionsValidationStatelessTest.Author.class,
34+
CollectionActionsValidationStatelessTest.Book.class,
35+
})
36+
@ServiceRegistry(settings = @Setting(name = AvailableSettings.JAKARTA_VALIDATION_MODE, value = "auto"))
37+
@Jira("https://hibernate.atlassian.net/browse/HHH-19843")
38+
public class CollectionActionsValidationStatelessTest {
39+
40+
@Test
41+
void smoke(SessionFactoryScope scope) {
42+
scope.inStatelessTransaction( session -> {
43+
final ConstraintViolationException e = assertThrows( ConstraintViolationException.class, () -> {
44+
ArrayList<Book> books = new ArrayList<>();
45+
Author author = new Author( 1L, "first", "last", books );
46+
Book book = new Book( 10L, "", author );
47+
books.add( book );
48+
49+
session.upsertMultiple( List.of( author ) );
50+
} );
51+
assertThat( e.getConstraintViolations() ).hasSize( 1 );
52+
} );
53+
}
54+
55+
@AfterEach
56+
public void tearDown(SessionFactoryScope scope) {
57+
scope.getSessionFactory().getSchemaManager().truncate();
58+
}
59+
60+
@Table(name = "author")
61+
@Entity
62+
static class Author {
63+
64+
public Author() {
65+
}
66+
67+
public Author(long id, String firstName, String lastName, List<Book> books) {
68+
this.firstName = firstName;
69+
this.lastName = lastName;
70+
this.books = books;
71+
this.id = id;
72+
}
73+
74+
@Id
75+
Long id;
76+
77+
String firstName;
78+
79+
String lastName;
80+
81+
@OneToMany
82+
@JoinColumn(name = "bookId")
83+
@Size(min = 10)
84+
List<Book> books;
85+
86+
}
87+
88+
@Table(name = "book")
89+
@Entity
90+
static class Book {
91+
92+
public Book() {
93+
}
94+
95+
public Book(long id, String title, Author author) {
96+
this.id = id;
97+
this.title = title;
98+
this.author = author;
99+
}
100+
101+
@Id
102+
Long id;
103+
104+
String title;
105+
106+
@ManyToOne
107+
Author author;
108+
}
109+
}

0 commit comments

Comments
 (0)