Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ public void write(final Object source, final CouchbaseDocument target) {
typeMapper.writeType(type, target);
}

writeInternal(source, target, type);
writeInternal(source, target, type, true);
if (target.getId() == null) {
throw new MappingException("An ID property is needed, but not found/could not be generated on this entity.");
}
Expand All @@ -416,7 +416,8 @@ public void write(final Object source, final CouchbaseDocument target) {
* @param typeHint the type information for the source.
*/
@SuppressWarnings("unchecked")
protected void writeInternal(final Object source, CouchbaseDocument target, final TypeInformation<?> typeHint) {
protected void writeInternal(final Object source, CouchbaseDocument target, final TypeInformation<?> typeHint,
boolean withId) {
if (source == null) {
return;
}
Expand All @@ -437,7 +438,7 @@ protected void writeInternal(final Object source, CouchbaseDocument target, fina
}

CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
writeInternal(source, target, entity);
writeInternal(source, target, entity, withId);
addCustomTypeKeyIfNecessary(typeHint, source, target);
}

Expand Down Expand Up @@ -471,9 +472,10 @@ private String convertToString(Object propertyObj) {
* @param source the source object.
* @param target the target document.
* @param entity the persistent entity to convert from.
* @param withId one of the top-level properties is the id for the document
*/
protected void writeInternal(final Object source, final CouchbaseDocument target,
final CouchbasePersistentEntity<?> entity) {
final CouchbasePersistentEntity<?> entity, boolean withId) {
if (source == null) {
return;
}
Expand All @@ -483,7 +485,7 @@ protected void writeInternal(final Object source, final CouchbaseDocument target
}

final ConvertingPropertyAccessor<Object> accessor = getPropertyAccessor(source);
final CouchbasePersistentProperty idProperty = entity.getIdProperty();
final CouchbasePersistentProperty idProperty = withId ? entity.getIdProperty() : null;
final CouchbasePersistentProperty versionProperty = entity.getVersionProperty();

GeneratedValue generatedValueInfo = null;
Expand Down Expand Up @@ -525,7 +527,7 @@ public void doWithPersistentProperty(final CouchbasePersistentProperty prop) {
}

if (!conversions.isSimpleType(propertyObj.getClass())) {
writePropertyInternal(propertyObj, target, prop);
writePropertyInternal(propertyObj, target, prop, false);
} else {
writeSimpleInternal(propertyObj, target, prop.getFieldName());
}
Expand All @@ -552,7 +554,7 @@ public void doWithAssociation(final Association<CouchbasePersistentProperty> ass
Class<?> type = inverseProp.getType();
Object propertyObj = accessor.getProperty(inverseProp, type);
if (null != propertyObj) {
writePropertyInternal(propertyObj, target, inverseProp);
writePropertyInternal(propertyObj, target, inverseProp, false);
}
}
});
Expand All @@ -568,7 +570,7 @@ public void doWithAssociation(final Association<CouchbasePersistentProperty> ass
*/
@SuppressWarnings("unchecked")
private void writePropertyInternal(final Object source, final CouchbaseDocument target,
final CouchbasePersistentProperty prop) {
final CouchbasePersistentProperty prop, boolean withId) {
if (source == null) {
return;
}
Expand Down Expand Up @@ -617,7 +619,7 @@ private void writePropertyInternal(final Object source, final CouchbaseDocument
CouchbasePersistentEntity<?> entity = isSubtype(prop.getType(), source.getClass())
? mappingContext.getRequiredPersistentEntity(source.getClass())
: mappingContext.getRequiredPersistentEntity(type);
writeInternal(source, propertyDoc, entity);
writeInternal(source, propertyDoc, entity, false);
target.put(name, propertyDoc);
}

Expand Down Expand Up @@ -660,7 +662,7 @@ private CouchbaseDocument writeMapInternal(final Map<Object, Object> source, fin
} else {
CouchbaseDocument embeddedDoc = new CouchbaseDocument();
TypeInformation<?> valueTypeInfo = type.isMap() ? type.getMapValueType() : ClassTypeInformation.OBJECT;
writeInternal(val, embeddedDoc, valueTypeInfo);
writeInternal(val, embeddedDoc, valueTypeInfo, false);
target.put(simpleKey, embeddedDoc);
}
} else {
Expand Down Expand Up @@ -706,7 +708,7 @@ private CouchbaseList writeCollectionInternal(final Collection<?> source, final
} else {

CouchbaseDocument embeddedDoc = new CouchbaseDocument();
writeInternal(element, embeddedDoc, componentType);
writeInternal(element, embeddedDoc, componentType, false);
target.put(embeddedDoc);
}

Expand Down Expand Up @@ -937,7 +939,7 @@ public <R> R getPropertyValue(final CouchbasePersistentProperty property) {
String expression = property.getSpelExpression();
Object value = expression != null ? evaluator.evaluate(expression) : source.get(property.getFieldName());

if (property.isIdProperty()) {
if (property.isIdProperty() && parent == null) {
return (R) source.getId();
}
if (value == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading