Skip to content

Commit 0eeb77f

Browse files
committed
DATAJPA-1446 - Clear JpaMetamodel CACHE when application context is closed.
1 parent 54fe0ae commit 0eeb77f

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import javax.persistence.metamodel.ManagedType;
2222
import javax.persistence.metamodel.Metamodel;
2323

24+
import org.springframework.beans.factory.DisposableBean;
2425
import org.springframework.data.jpa.provider.PersistenceProvider;
2526
import org.springframework.data.jpa.util.JpaMetamodel;
2627
import org.springframework.data.mapping.PersistentPropertyPaths;
@@ -38,10 +39,12 @@
3839
* @author Oliver Gierke
3940
* @author Christoph Strobl
4041
* @author Mark Paluch
42+
* @author Sylvère Richard
4143
* @since 1.3
4244
*/
4345
public class JpaMetamodelMappingContext
44-
extends AbstractMappingContext<JpaPersistentEntityImpl<?>, JpaPersistentProperty> {
46+
extends AbstractMappingContext<JpaPersistentEntityImpl<?>, JpaPersistentProperty>
47+
implements DisposableBean {
4548

4649
private final Metamodels models;
4750
private final PersistenceProvider persistenceProvider;
@@ -90,7 +93,7 @@ protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
9093

9194
/**
9295
* We customize the lookup of {@link PersistentPropertyPaths} by also traversing properties that are embeddables.
93-
*
96+
*
9497
* @see org.springframework.data.mapping.context.AbstractMappingContext#findPersistentPropertyPaths(java.lang.Class,
9598
* java.util.function.Predicate)
9699
*/
@@ -100,7 +103,7 @@ public <T> PersistentPropertyPaths<T, JpaPersistentProperty> findPersistentPrope
100103
return doFindPersistentPropertyPaths(type, predicate, it -> it.isEmbeddable());
101104
}
102105

103-
/*
106+
/*
104107
* (non-Javadoc)
105108
* @see org.springframework.data.mapping.context.AbstractMappingContext#hasPersistentEntityFor(java.lang.Class)
106109
*/
@@ -109,7 +112,16 @@ public boolean hasPersistentEntityFor(Class<?> type) {
109112
return super.hasPersistentEntityFor(type) || models.isMetamodelManagedType(type);
110113
}
111114

112-
/**
115+
/*
116+
* (non-Javadoc)
117+
* @see org.springframework.beans.factory.DisposableBean#destroy()
118+
*/
119+
@Override
120+
public void destroy() throws Exception {
121+
JpaMetamodel.clearCache();
122+
}
123+
124+
/**
113125
* A wrapper for a set of JPA {@link Metamodel} instances to simplify lookups of {@link JpaMetamodel} instances and
114126
* managed type checks.
115127
*
@@ -125,7 +137,7 @@ private Metamodels(Set<Metamodel> metamodels) {
125137

126138
/**
127139
* Returns the {@link JpaMetamodel} for the given type.
128-
*
140+
*
129141
* @param type must not be {@literal null}.
130142
* @return
131143
*/
@@ -139,7 +151,7 @@ public JpaMetamodel getMetamodel(TypeInformation<?> type) {
139151

140152
/**
141153
* Returns whether the given type is managed by one of the underlying {@link Metamodel} instances.
142-
*
154+
*
143155
* @param type must not be {@literal null}.
144156
* @return
145157
*/
@@ -149,7 +161,7 @@ public boolean isMetamodelManagedType(TypeInformation<?> type) {
149161

150162
/**
151163
* Returns whether the given type is managed by one of the underlying {@link Metamodel} instances.
152-
*
164+
*
153165
* @param type must not be {@literal null}.
154166
* @return
155167
*/

src/main/java/org/springframework/data/jpa/util/JpaMetamodel.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
package org.springframework.data.jpa.util;
1717

1818
import java.util.Collection;
19-
import java.util.HashMap;
2019
import java.util.Map;
2120
import java.util.Optional;
21+
import java.util.concurrent.ConcurrentHashMap;
2222

2323
import javax.persistence.metamodel.EntityType;
2424
import javax.persistence.metamodel.ManagedType;
@@ -34,10 +34,11 @@
3434
*
3535
* @author Oliver Gierke
3636
* @author Mark Paluch
37+
* @author Sylvère Richard
3738
*/
3839
public class JpaMetamodel {
3940

40-
private static final Map<Metamodel, JpaMetamodel> CACHE = new HashMap<>(4);
41+
private static final Map<Metamodel, JpaMetamodel> CACHE = new ConcurrentHashMap<>(4);
4142

4243
private final Metamodel metamodel;
4344

@@ -63,6 +64,10 @@ public static JpaMetamodel of(Metamodel metamodel) {
6364
return CACHE.computeIfAbsent(metamodel, JpaMetamodel::new);
6465
}
6566

67+
public static void clearCache() {
68+
CACHE.clear();
69+
}
70+
6671
/**
6772
* Returns whether the given type is managed by the backing JPA {@link Metamodel}.
6873
*
@@ -78,7 +83,7 @@ public boolean isJpaManaged(Class<?> type) {
7883

7984
/**
8085
* Returns whether the attribute of given name and type is the single identifier attribute of the given entity.
81-
*
86+
*
8287
* @param entity must not be {@literal null}.
8388
* @param name must not be {@literal null}.
8489
* @param attributeType must not be {@literal null}.
@@ -98,7 +103,7 @@ public boolean isSingleIdAttribute(Class<?> entity, String name, Class<?> attrib
98103
/**
99104
* Returns the {@link SingularAttribute} representing the identifier of the given {@link EntityType} if it contains a
100105
* singular one.
101-
*
106+
*
102107
* @param entityType must not be {@literal null}.
103108
* @return
104109
*/

src/test/java/org/springframework/data/jpa/util/JpaMetamodelUnitTests.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030

3131
/**
3232
* Unit tests for {@link JpaMetamodel}.
33-
*
33+
*
3434
* @author Oliver Gierke
35+
* @author Sylvère Richard
3536
*/
3637
@RunWith(MockitoJUnitRunner.class)
3738
public class JpaMetamodelUnitTests {
@@ -47,4 +48,13 @@ public void skipsEntityTypesWithoutJavaTypeForIdentifierLookup() {
4748

4849
assertThat(JpaMetamodel.of(metamodel).isSingleIdAttribute(Object.class, "id", Object.class)).isFalse();
4950
}
51+
52+
@Test //DATAJPA-1446
53+
public void cacheIsEffectiveUnlessCleared() {
54+
JpaMetamodel model1 = JpaMetamodel.of(metamodel);
55+
assertThat(model1).isEqualTo(JpaMetamodel.of(metamodel));
56+
57+
JpaMetamodel.clearCache();
58+
assertThat(model1).isNotEqualTo(JpaMetamodel.of(metamodel));
59+
}
5060
}

0 commit comments

Comments
 (0)