Skip to content

Commit

Permalink
fix SO on queries when references vanish
Browse files Browse the repository at this point in the history
fixes #2382
  • Loading branch information
evanchooly committed Jun 22, 2023
1 parent 39f40a8 commit 481295f
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,12 @@ public Object encode(Object value) {
});
return writer.getDocument().get("ref");
} catch (ReferenceException e) {
return value;
if (getPropertyModel().getAnnotation(Reference.class).ignoreMissing()) {
return null;
} else {
throw e;
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ private Object invoke(Method method, Object[] args) throws InvocationTargetExcep
Object target = reference.get();
if (target == null) {
throw new ReferenceException(Sofia.missingReferencedEntity(reference.getType()));
} else {
return method.invoke(target, args);
}
return method.invoke(target, args);
} else {
return method.invoke(reference.getIds(), args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DocumentState extends ValueState<Map<String, Object>> {
@Override
public String toString() {
StringJoiner joiner = new StringJoiner(", ", "{", finished != null ? "}" : "");
values.forEach(v -> joiner.add(v.toString()));
values.forEach(v -> joiner.add(String.valueOf(v)));
return joiner.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SingleValue extends ValueState<Object> {

@Override
public String toString() {
return value.toString();
return String.valueOf(value);
}

@Override
Expand Down
122 changes: 122 additions & 0 deletions core/src/test/java/dev/morphia/test/mapping/lazy/TestLazyIdOnly.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package dev.morphia.test.mapping.lazy;

import java.util.List;
import java.util.Objects;

import dev.morphia.Datastore;
import dev.morphia.annotations.Reference;
import dev.morphia.mapping.lazy.proxy.ReferenceException;
import dev.morphia.test.mapping.ProxyTestBase;
import dev.morphia.test.models.TestEntity;

import org.testng.annotations.Test;

import static dev.morphia.query.filters.Filters.eq;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertThrows;

@Test(groups = "references")
public class TestLazyIdOnly extends ProxyTestBase {

@Test
public void testQueryAfterReferentIsGone() {
checkForProxyTypes();

RootEntity root = new RootEntity();
root.setBar("foo");
final ReferencedEntity reference = new ReferencedEntity();
reference.setFoo("bar");

root.setDontIgnoreMissing(reference);
root.setIgnoreMissing(reference);

final Datastore datastore = getDs();
datastore.save(List.of(reference, root));

root = datastore.find(RootEntity.class).filter(eq("_id", root.getId())).first();

ReferencedEntity p = root.dontIgnoreMissing;

assertIsProxy(p);
assertNotFetched(p);

datastore.delete(reference);

root = datastore.find(RootEntity.class).first();
assertNotNull(root);

assertThrows(ReferenceException.class, () -> {
datastore.find(RootEntity.class).filter(eq("dontIgnoreMissing", p)).first();
});

datastore.find(RootEntity.class).filter(eq("ignoreMissing", p)).first();

ReferencedEntity r = root.dontIgnoreMissing;
assertThrows(ReferenceException.class, () -> {
r.getFoo();
});
}

public static class ReferencedEntity extends TestEntity {
private String foo;

public String getFoo() {
return foo;
}

public void setFoo(String string) {
foo = string;
}

@Override
public int hashCode() {
return Objects.hash(id, foo);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ReferencedEntity)) {
return false;
}
ReferencedEntity that = (ReferencedEntity) o;
return Objects.equals(id, that.id) && Objects.equals(foo, that.foo);
}
}

public static class RootEntity extends TestEntity {
@Reference(idOnly = true, lazy = true, ignoreMissing = false)
private ReferencedEntity dontIgnoreMissing;
@Reference(idOnly = true, lazy = true , ignoreMissing = true )
private ReferencedEntity ignoreMissing;

private String bar;

public String getBar() {
return bar;
}

public void setBar(String bar) {
this.bar = bar;
}

public ReferencedEntity getDontIgnoreMissing() {
return dontIgnoreMissing;
}

public void setDontIgnoreMissing(ReferencedEntity dontIgnoreMissing) {
this.dontIgnoreMissing = dontIgnoreMissing;
}

public ReferencedEntity getIgnoreMissing() {
return ignoreMissing;
}

public void setIgnoreMissing(ReferencedEntity ignoreMissing) {
this.ignoreMissing = ignoreMissing;
}
}
}

0 comments on commit 481295f

Please sign in to comment.