Browse Source

DATACMNS-511 - Improve equals(…) and hashCode() in TypeVariableTypeInformation.

The equals(…) and hashCode() methods of TypeVariableTypeInformation previously tried to evaluate the unresolved context of the type variable. This can cause issues in recursive type definitions as set up in the according test case. We now implement the methods based on the resolved type to makes sure we break the recursive lookup of PersistentEntity instances in AbstractMappingContext.

The erroneous lookup was actually caused by unresolved base types being added to the mapping context within the JPA project as the JPA meta-model also returns those types as managed types.

Related pull request: #84.
1.8.x
Oliver Gierke 12 years ago
parent
commit
314aad7caa
  1. 35
      src/main/java/org/springframework/data/util/TypeVariableTypeInformation.java
  2. 67
      src/test/java/org/springframework/data/util/DataCmns511Tests.java

35
src/main/java/org/springframework/data/util/TypeVariableTypeInformation.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2014 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.
@ -55,8 +55,7 @@ class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> { @@ -55,8 +55,7 @@ class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
/*
* (non-Javadoc)
*
* @see org.springframework.data.document.mongodb.TypeDiscovererTest.TypeDiscoverer#getType()
* @see org.springframework.data.util.TypeDiscoverer#getType()
*/
@Override
public Class<T> getType() {
@ -92,38 +91,40 @@ class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> { @@ -92,38 +91,40 @@ class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.util.TypeDiscoverer#equals(java.lang.Object)
*/
* (non-Javadoc)
* @see org.springframework.data.util.ParentTypeAwareTypeInformation#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
if (obj == this) {
return true;
}
if (!(obj instanceof TypeVariableTypeInformation)) {
return false;
}
TypeVariableTypeInformation<?> that = (TypeVariableTypeInformation<?>) obj;
return nullSafeEquals(this.owningType, that.owningType) && nullSafeEquals(this.variable, that.variable);
return getType().equals(that.getType());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.util.TypeDiscoverer#hashCode()
*/
* (non-Javadoc)
* @see org.springframework.data.util.ParentTypeAwareTypeInformation#hashCode()
*/
@Override
public int hashCode() {
int result = super.hashCode();
int result = 17;
result += 31 * nullSafeHashCode(this.owningType);
result += 31 * nullSafeHashCode(this.variable);
result += 31 * nullSafeHashCode(getType());
return result;
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/

67
src/test/java/org/springframework/data/util/DataCmns511Tests.java

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
/*
* Copyright 2014 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
/**
* Unit tests to reproduce issues reported in DATACMNS-511.
*
* @author Oliver Gierke
*/
public class DataCmns511Tests {
/**
* @see DATACMNS-511
*/
@Test
@SuppressWarnings("rawtypes")
public void detectsEqualTypeVariableTypeInformationInstances() {
TypeInformation<AbstractRole> firstRoleType = ClassTypeInformation.from(AbstractRole.class);
TypeInformation<?> firstCreatedBy = firstRoleType.getProperty("createdBy");
TypeInformation<?> secondRoleType = firstCreatedBy.getProperty("roles").getActualType();
TypeInformation secondCreatedBy = secondRoleType.getProperty("createdBy");
TypeInformation<?> thirdRoleType = secondCreatedBy.getProperty("roles").getActualType();
TypeInformation thirdCreatedBy = thirdRoleType.getProperty("createdBy");
assertThat(secondCreatedBy, is(thirdCreatedBy));
assertThat(secondCreatedBy.hashCode(), is(thirdCreatedBy.hashCode()));
}
static class AbstractRole<USER extends AbstractUser<USER, ROLE>, ROLE extends AbstractRole<USER, ROLE>> extends
AuditingEntity<USER> {
String name;
}
static abstract class AbstractUser<USER extends AbstractUser<USER, ROLE>, ROLE extends AbstractRole<USER, ROLE>> {
Set<ROLE> roles = new HashSet<ROLE>();
}
static abstract class AuditingEntity<USER extends AbstractUser<USER, ?>> {
USER createdBy;
USER lastModifiedBy;
}
}
Loading…
Cancel
Save