DATAJPA-904 - Guard against null values from JPA's ManagedType.getJavaType().

Some persistence providers (Hibernate *cough*) return null for a ManagedType's JavaType, which we perviously didn't expect in the implementation of JpaPersistentPropertyImpl.isEntity().

We now eagerly extract all managed types from the Metamodel and gracefully skip nulls so that we don't have to look up the types repeatedly.
This commit is contained in:
Oliver Gierke
2016-06-08 10:17:51 +02:00
parent 5c24fae1e5
commit 0768bc4696
2 changed files with 41 additions and 11 deletions

View File

@@ -88,10 +88,10 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
UPDATEABLE_ANNOTATIONS = Collections.unmodifiableSet(annotations);
}
private final Metamodel metamodel;
private final Boolean usePropertyAccess;
private final TypeInformation<?> associationTargetType;
private final boolean updateable;
private final Set<Class<?>> managedTypes;
/**
* Creates a new {@link JpaPersistentPropertyImpl}
@@ -109,10 +109,10 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
Assert.notNull(metamodel, "Metamodel must not be null!");
this.metamodel = metamodel;
this.usePropertyAccess = detectPropertyAccess();
this.associationTargetType = isAssociation() ? detectAssociationTargetType() : null;
this.updateable = detectUpdatability();
this.managedTypes = getManagedTypes(metamodel);
}
/*
@@ -156,14 +156,7 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
*/
@Override
public boolean isEntity() {
for (ManagedType<?> type : metamodel.getManagedTypes()) {
if (type.getJavaType().equals(getActualType())) {
return true;
}
}
return false;
return managedTypes.contains(getActualType());
}
/*
@@ -303,4 +296,27 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
return true;
}
/**
* Returns all types managed by the given {@link Metamodel}.
*
* @param metamodel must not be {@literal null}.
* @return
*/
private static Set<Class<?>> getManagedTypes(Metamodel metamodel) {
Set<ManagedType<?>> managedTypes = metamodel.getManagedTypes();
Set<Class<?>> types = new HashSet<Class<?>>(managedTypes.size());
for (ManagedType<?> managedType : metamodel.getManagedTypes()) {
Class<?> type = managedType.getJavaType();
if (type != null) {
types.add(type);
}
}
return Collections.unmodifiableSet(types);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package org.springframework.data.jpa.mapping;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.Collections;
@@ -28,6 +29,7 @@ import javax.persistence.Embedded;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;
import org.junit.Before;
@@ -184,6 +186,18 @@ public class JpaPersistentPropertyImplUnitTests {
assertThat(getProperty(WithReadOnly.class, "updatable").isWritable(), is(true));
}
/**
* @see DATAJPA-904
*/
@Test
public void isEntityWorksEvenWithManagedTypeWithNullJavaType() {
ManagedType<?> managedType = mock(ManagedType.class);
doReturn(Collections.singleton(managedType)).when(model).getManagedTypes();
assertThat(getProperty(Sample.class, "other").isEntity(), is(false));
}
private JpaPersistentProperty getProperty(Class<?> ownerType, String propertyName) {
JpaPersistentEntity<?> entity = context.getPersistentEntity(ownerType);