Skip to content

Commit d360807

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

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* @author Oliver Gierke
3939
* @author Christoph Strobl
4040
* @author Mark Paluch
41+
* @author Sylvère Richard
4142
* @since 1.3
4243
*/
4344
public class JpaMetamodelMappingContext
@@ -90,7 +91,7 @@ protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
9091

9192
/**
9293
* We customize the lookup of {@link PersistentPropertyPaths} by also traversing properties that are embeddables.
93-
*
94+
*
9495
* @see org.springframework.data.mapping.context.AbstractMappingContext#findPersistentPropertyPaths(java.lang.Class,
9596
* java.util.function.Predicate)
9697
*/
@@ -100,7 +101,7 @@ public <T> PersistentPropertyPaths<T, JpaPersistentProperty> findPersistentPrope
100101
return doFindPersistentPropertyPaths(type, predicate, it -> it.isEmbeddable());
101102
}
102103

103-
/*
104+
/*
104105
* (non-Javadoc)
105106
* @see org.springframework.data.mapping.context.AbstractMappingContext#hasPersistentEntityFor(java.lang.Class)
106107
*/
@@ -125,7 +126,7 @@ private Metamodels(Set<Metamodel> metamodels) {
125126

126127
/**
127128
* Returns the {@link JpaMetamodel} for the given type.
128-
*
129+
*
129130
* @param type must not be {@literal null}.
130131
* @return
131132
*/
@@ -139,7 +140,7 @@ public JpaMetamodel getMetamodel(TypeInformation<?> type) {
139140

140141
/**
141142
* Returns whether the given type is managed by one of the underlying {@link Metamodel} instances.
142-
*
143+
*
143144
* @param type must not be {@literal null}.
144145
* @return
145146
*/
@@ -149,7 +150,7 @@ public boolean isMetamodelManagedType(TypeInformation<?> type) {
149150

150151
/**
151152
* Returns whether the given type is managed by one of the underlying {@link Metamodel} instances.
152-
*
153+
*
153154
* @param type must not be {@literal null}.
154155
* @return
155156
*/

src/main/java/org/springframework/data/jpa/repository/config/JpaMetamodelMappingContextFactoryBean.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.context.ApplicationContext;
3232
import org.springframework.context.ApplicationContextAware;
3333
import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext;
34+
import org.springframework.data.jpa.util.JpaMetamodel;
3435
import org.springframework.data.util.StreamUtils;
3536
import org.springframework.lang.Nullable;
3637

@@ -66,6 +67,11 @@ public Class<?> getObjectType() {
6667
return JpaMetamodelMappingContext.class;
6768
}
6869

70+
@Override
71+
protected void destroyInstance(JpaMetamodelMappingContext instance) throws Exception {
72+
JpaMetamodel.clearCache();
73+
}
74+
6975
/*
7076
* (non-Javadoc)
7177
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()

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)