DATACOUCH-620 - Fix nested object id/@Id issue.

Only treat the id (or @Id) field in top-level objects as the id.
This commit is contained in:
mikereiche
2020-10-01 16:24:59 -07:00
parent 946e835b72
commit 2a06578145
6 changed files with 360 additions and 12 deletions

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2020 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
*
* https://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.couchbase.domain;
import org.springframework.data.annotation.Id;
import java.lang.reflect.Field;
/**
* Course entity for tests
*
* @author Michael Reiche
*/
public class Course {
@Id private final String id;
private final String userId;
private final String room;
public Course(String id, String userId, String room) {
this.id = id;
this.userId = userId;
this.room = room;
}
public String getId() {
return id;
}
public String toString() {
StringBuffer sb = new StringBuffer("Course(");
sb.append("id=");
sb.append(id);
sb.append(", userId=");
sb.append(userId);
sb.append(", room=");
sb.append(room);
sb.append(")");
return sb.toString();
}
@Override
public boolean equals(Object that) throws RuntimeException {
if (this == that)
return true;
if (that == null || getClass() != that.getClass())
return false;
for (Field f : getClass().getFields()) {
if (!same(f, this, that))
return false;
}
for (Field f : getClass().getDeclaredFields()) {
if (!same(f, this, that))
return false;
}
return true;
}
private static boolean same(Field f, Object a, Object b) {
Object thisField = null;
Object thatField = null;
try {
f.get(a);
f.get(b);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (thisField == null && thatField == null) {
return true;
}
if (thisField == null && thatField != null) {
return false;
}
if (!thisField.equals(thatField)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2020 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
*
* https://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.couchbase.domain;
import java.lang.reflect.Field;
/**
* Submission entity for tests
*
* @author Michael Reiche
*/
public class Submission {
private final String id;
private final String userId;
private final String talkId;
private final String status;
private final long number;
public Submission(String id, String userId, String talkId, String status, long number) {
this.id = id;
this.userId = userId;
this.talkId = talkId;
this.status = status;
this.number = number;
}
public String getId() {
return id;
}
public String toString() {
StringBuffer sb = new StringBuffer("Submission(");
sb.append("id=");
sb.append(id);
sb.append(", userId=");
sb.append(userId);
sb.append(", talkId=");
sb.append(talkId);
sb.append(", status=");
sb.append(status);
sb.append(", number=");
sb.append(number);
sb.append(")");
return sb.toString();
}
@Override
public boolean equals(Object that) throws RuntimeException {
if (this == that)
return true;
if (that == null || getClass() != that.getClass())
return false;
for (Field f : getClass().getFields()) {
if (!same(f, this, that))
return false;
}
for (Field f : getClass().getDeclaredFields()) {
if (!same(f, this, that))
return false;
}
return true;
}
private static boolean same(Field f, Object a, Object b) {
Object thisField = null;
Object thatField = null;
try {
f.get(a);
f.get(b);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (thisField == null && thatField == null) {
return true;
}
if (thisField == null && thatField != null) {
return false;
}
if (!thisField.equals(thatField)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2012-2020 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
*
* https://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.couchbase.domain;
import lombok.Data;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.couchbase.core.index.CompositeQueryIndex;
import org.springframework.data.couchbase.core.mapping.Document;
import java.lang.reflect.Field;
import java.util.List;
/**
* UserSubmission entity for tests
*
* @author Michael Reiche
*/
@Data
@Document
@TypeAlias("user")
@CompositeQueryIndex(fields = { "id", "username", "email" })
public class UserSubmission {
private String id;
private String username;
private String email;
private String password;
private List<String> roles;
private Address address;
private int credits;
private List<Submission> submissions;
private List<Course> courses;
public void setSubmissions(List<Submission> submissions) {
this.submissions = submissions;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
@Override
public boolean equals(Object that) throws RuntimeException {
if (this == that)
return true;
if (that == null || getClass() != that.getClass())
return false;
for (Field f : getClass().getFields()) {
if (!same(f, this, that))
return false;
}
for (Field f : getClass().getDeclaredFields()) {
if (!same(f, this, that))
return false;
}
return true;
}
private static boolean same(Field f, Object a, Object b) {
Object thisField = null;
Object thatField = null;
try {
f.get(a);
f.get(b);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (thisField == null && thatField == null) {
return true;
}
if (thisField == null && thatField != null) {
return false;
}
if (!thisField.equals(thatField)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2012-2020 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
*
* https://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.couchbase.domain;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
/**
* UserSubmission Repository for tests
*
* @author Michael Reiche
*/
@Repository
public interface UserSubmissionRepository extends PagingAndSortingRepository<UserSubmission, String> {
}

View File

@@ -19,6 +19,7 @@ package org.springframework.data.couchbase.repository;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -27,10 +28,14 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.domain.Course;
import org.springframework.data.couchbase.domain.Library;
import org.springframework.data.couchbase.domain.LibraryRepository;
import org.springframework.data.couchbase.domain.Submission;
import org.springframework.data.couchbase.domain.User;
import org.springframework.data.couchbase.domain.UserRepository;
import org.springframework.data.couchbase.domain.UserSubmission;
import org.springframework.data.couchbase.domain.UserSubmissionRepository;
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests;
import org.springframework.data.couchbase.util.ClusterType;
@@ -49,6 +54,7 @@ public class CouchbaseRepositoryKeyValueIntegrationTests extends ClusterAwareInt
@Autowired UserRepository userRepository;
@Autowired LibraryRepository libraryRepository;
@Autowired UserSubmissionRepository userSubmissionRepository;
@Test
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
@@ -89,6 +95,31 @@ public class CouchbaseRepositoryKeyValueIntegrationTests extends ClusterAwareInt
assertFalse(userRepository.existsById(library.getId()));
}
@Test
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
void saveAndFindByWithNestedId() {
UserSubmission user = new UserSubmission();
user.setId(UUID.randomUUID().toString());
user.setSubmissions(
Arrays.asList(new Submission(UUID.randomUUID().toString(), user.getId(), "tid", "status", 123)));
user.setCourses(Arrays.asList(new Course(UUID.randomUUID().toString(), user.getId(), "581")));
// this currently fails when using mocked in integration.properties with status "UNKNOWN"
assertFalse(userRepository.existsById(user.getId()));
userSubmissionRepository.save(user);
Optional<UserSubmission> found = userSubmissionRepository.findById(user.getId());
assertTrue(found.isPresent());
found.ifPresent(u -> assertEquals(user, u));
assertTrue(userRepository.existsById(user.getId()));
assertEquals(user.getSubmissions().get(0).getId(), found.get().getSubmissions().get(0).getId());
assertEquals(user.getCourses().get(0).getId(), found.get().getCourses().get(0).getId());
assertEquals(user, found.get());
userSubmissionRepository.delete(user);
}
@Configuration
@EnableCouchbaseRepositories("org.springframework.data.couchbase")
static class Config extends AbstractCouchbaseConfiguration {