Skip to content

Commit 6212831

Browse files
committed
Merge branch '6.1.x'
2 parents 5cd4b87 + f6b608e commit 6212831

File tree

3 files changed

+137
-32
lines changed

3 files changed

+137
-32
lines changed

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java

+39-22
Original file line numberDiff line numberDiff line change
@@ -188,39 +188,56 @@ private void contributeCallbackHints(RuntimeHints hints, Class<?> managedClass)
188188

189189
@SuppressWarnings("unchecked")
190190
private void contributeHibernateHints(RuntimeHints hints, @Nullable ClassLoader classLoader, Class<?> managedClass) {
191-
Class<? extends Annotation> embeddableInstantiatorClass = loadEmbeddableInstantiatorClass(classLoader);
192-
if (embeddableInstantiatorClass == null) {
193-
return;
194-
}
195191
ReflectionHints reflection = hints.reflection();
196-
registerInstantiatorForReflection(reflection,
197-
AnnotationUtils.findAnnotation(managedClass, embeddableInstantiatorClass));
198-
ReflectionUtils.doWithFields(managedClass, field -> {
199-
registerInstantiatorForReflection(reflection,
200-
AnnotationUtils.findAnnotation(field, embeddableInstantiatorClass));
201-
registerInstantiatorForReflection(reflection,
202-
AnnotationUtils.findAnnotation(field.getType(), embeddableInstantiatorClass));
203-
});
204-
}
205192

206-
@SuppressWarnings("NullAway")
207-
private void registerInstantiatorForReflection(ReflectionHints reflection, @Nullable Annotation annotation) {
208-
if (annotation == null) {
209-
return;
193+
Class<? extends Annotation> embeddableInstantiatorClass = loadClass("org.hibernate.annotations.EmbeddableInstantiator", classLoader);
194+
if (embeddableInstantiatorClass != null) {
195+
registerForReflection(reflection,
196+
AnnotationUtils.findAnnotation(managedClass, embeddableInstantiatorClass), "value");
197+
ReflectionUtils.doWithFields(managedClass, field -> {
198+
registerForReflection(reflection,
199+
AnnotationUtils.findAnnotation(field, embeddableInstantiatorClass), "value");
200+
registerForReflection(reflection,
201+
AnnotationUtils.findAnnotation(field.getType(), embeddableInstantiatorClass), "value");
202+
});
203+
ReflectionUtils.doWithMethods(managedClass, method -> registerForReflection(reflection,
204+
AnnotationUtils.findAnnotation(method, embeddableInstantiatorClass), "value"));
205+
}
206+
207+
Class<? extends Annotation> valueGenerationTypeClass = loadClass("org.hibernate.annotations.ValueGenerationType", classLoader);
208+
if (valueGenerationTypeClass != null) {
209+
ReflectionUtils.doWithFields(managedClass, field -> registerForReflection(reflection,
210+
AnnotationUtils.findAnnotation(field, valueGenerationTypeClass), "generatedBy"));
211+
ReflectionUtils.doWithMethods(managedClass, method -> registerForReflection(reflection,
212+
AnnotationUtils.findAnnotation(method, valueGenerationTypeClass), "generatedBy"));
213+
}
214+
215+
Class<? extends Annotation> idGeneratorTypeClass = loadClass("org.hibernate.annotations.IdGeneratorType", classLoader);
216+
if (idGeneratorTypeClass != null) {
217+
ReflectionUtils.doWithFields(managedClass, field -> registerForReflection(reflection,
218+
AnnotationUtils.findAnnotation(field, idGeneratorTypeClass), "value"));
219+
ReflectionUtils.doWithMethods(managedClass, method -> registerForReflection(reflection,
220+
AnnotationUtils.findAnnotation(method, idGeneratorTypeClass), "value"));
210221
}
211-
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(annotation).get("value");
212-
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
213222
}
214223

215224
@Nullable
216-
private static Class<? extends Annotation> loadEmbeddableInstantiatorClass(@Nullable ClassLoader classLoader) {
225+
private static Class<? extends Annotation> loadClass(String className, @Nullable ClassLoader classLoader) {
217226
try {
218-
return (Class<? extends Annotation>) ClassUtils.forName(
219-
"org.hibernate.annotations.EmbeddableInstantiator", classLoader);
227+
return (Class<? extends Annotation>) ClassUtils.forName(className, classLoader);
220228
}
221229
catch (ClassNotFoundException ex) {
222230
return null;
223231
}
224232
}
233+
234+
@SuppressWarnings("NullAway")
235+
private void registerForReflection(ReflectionHints reflection, @Nullable Annotation annotation, String attribute) {
236+
if (annotation == null) {
237+
return;
238+
}
239+
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(annotation).get(attribute);
240+
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
241+
}
225242
}
226243
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.orm.jpa.hibernate.domain;
18+
19+
import java.time.Instant;
20+
21+
import jakarta.persistence.Entity;
22+
import jakarta.persistence.Id;
23+
import org.hibernate.annotations.CreationTimestamp;
24+
25+
@Entity
26+
public class Book {
27+
28+
@Id
29+
private Long id;
30+
31+
private String title;
32+
33+
@CreationTimestamp
34+
private Instant createdOn;
35+
36+
public Book() {
37+
}
38+
39+
public Long getId() {
40+
return id;
41+
}
42+
43+
public void setId(Long id) {
44+
this.id = id;
45+
}
46+
47+
public String getTitle() {
48+
return title;
49+
}
50+
51+
public void setTitle(String title) {
52+
this.title = title;
53+
}
54+
55+
public Instant getCreatedOn() {
56+
return createdOn;
57+
}
58+
59+
public void setCreatedOn(Instant createdOn) {
60+
this.createdOn = createdOn;
61+
}
62+
}

spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java

+36-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121

2222
import javax.sql.DataSource;
2323

24+
import org.hibernate.tuple.CreationTimestampGeneration;
2425
import org.junit.jupiter.api.Test;
2526

2627
import org.springframework.aot.hint.MemberCategory;
@@ -30,7 +31,6 @@
3031
import org.springframework.context.ApplicationContextInitializer;
3132
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3233
import org.springframework.context.annotation.Bean;
33-
import org.springframework.context.annotation.Configuration;
3434
import org.springframework.context.aot.ApplicationContextAotGenerator;
3535
import org.springframework.context.support.GenericApplicationContext;
3636
import org.springframework.core.io.ResourceLoader;
@@ -64,7 +64,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
6464
@Test
6565
void processEntityManagerWithPackagesToScan() {
6666
GenericApplicationContext context = new AnnotationConfigApplicationContext();
67-
context.registerBean(EntityManagerWithPackagesToScanConfiguration.class);
67+
context.registerBean(JpaDomainConfiguration.class);
6868
compile(context, (initializer, compiled) -> {
6969
GenericApplicationContext freshApplicationContext = toFreshApplicationContext(
7070
initializer);
@@ -75,14 +75,14 @@ void processEntityManagerWithPackagesToScan() {
7575
EmployeeLocationConverter.class.getName());
7676
assertThat(persistenceManagedTypes.getManagedPackages()).isEmpty();
7777
assertThat(freshApplicationContext.getBean(
78-
EntityManagerWithPackagesToScanConfiguration.class).scanningInvoked).isFalse();
78+
JpaDomainConfiguration.class).scanningInvoked).isFalse();
7979
});
8080
}
8181

8282
@Test
83-
void contributeHints() {
83+
void contributeJpaHints() {
8484
GenericApplicationContext context = new AnnotationConfigApplicationContext();
85-
context.registerBean(EntityManagerWithPackagesToScanConfiguration.class);
85+
context.registerBean(JpaDomainConfiguration.class);
8686
contributeHints(context, hints -> {
8787
assertThat(RuntimeHintsPredicates.reflection().onType(DriversLicense.class)
8888
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
@@ -108,6 +108,15 @@ void contributeHints() {
108108
});
109109
}
110110

111+
@Test
112+
void contributeHibernateHints() {
113+
GenericApplicationContext context = new AnnotationConfigApplicationContext();
114+
context.registerBean(HibernateDomainConfiguration.class);
115+
contributeHints(context, hints ->
116+
assertThat(RuntimeHintsPredicates.reflection().onType(CreationTimestampGeneration.class)
117+
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(hints));
118+
}
119+
111120

112121
@SuppressWarnings("unchecked")
113122
private void compile(GenericApplicationContext applicationContext,
@@ -135,10 +144,25 @@ private void contributeHints(GenericApplicationContext applicationContext, Consu
135144
result.accept(generationContext.getRuntimeHints());
136145
}
137146

138-
@Configuration(proxyBeanMethods = false)
139-
public static class EntityManagerWithPackagesToScanConfiguration {
147+
public static class JpaDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
148+
149+
@Override
150+
protected String packageToScan() {
151+
return "org.springframework.orm.jpa.domain";
152+
}
153+
}
140154

141-
private boolean scanningInvoked;
155+
public static class HibernateDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
156+
157+
@Override
158+
protected String packageToScan() {
159+
return "org.springframework.orm.jpa.hibernate.domain";
160+
}
161+
}
162+
163+
public abstract static class AbstractEntityManagerWithPackagesToScanConfiguration {
164+
165+
protected boolean scanningInvoked;
142166

143167
@Bean
144168
public DataSource mockDataSource() {
@@ -156,7 +180,7 @@ public HibernateJpaVendorAdapter jpaVendorAdapter() {
156180
public PersistenceManagedTypes persistenceManagedTypes(ResourceLoader resourceLoader) {
157181
this.scanningInvoked = true;
158182
return new PersistenceManagedTypesScanner(resourceLoader)
159-
.scan("org.springframework.orm.jpa.domain");
183+
.scan(packageToScan());
160184
}
161185

162186
@Bean
@@ -169,6 +193,8 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource da
169193
return entityManagerFactoryBean;
170194
}
171195

196+
protected abstract String packageToScan();
197+
172198
}
173199

174200
}

0 commit comments

Comments
 (0)