我将所有内容简化为一个TestCase:
public class StandaloneTestCase {
protected static LocalServiceTestHelper helper = null;
protected static Objectify ds = null;
@BeforeClass
public static void setUp() {
LocalDatastoreServiceTestConfig config = new LocalDatastoreServiceTestConfig();
helper = new LocalServiceTestHelper(config);
helper.setUp();
ds = ObjectifyService.ofy();
ObjectifyService.register(Post.class);
ObjectifyService.register(Profile.class);
}
@Test
public void test() {
Profile p = new Profile();
p.setEmail("user1@email.com");
p.setPassword("user1pwd");
p.setRegistrationDate(new Date(0L));
p.setSex("Male");
p.setName("Name1");
p.setSurname("Surname1");
p.setFullName("Name1 Nick1 Surname1");
Key<Profile> pKey = ds.save().entity(p).now();
Profile pro = ds.load().type(Profile.class).filter("name", "Name1").first().get();
Assert.assertEquals(0, ds.load().key(pro.getRef().getKey()).get().getFriends().size());
Post newPost = new Post();
newPost.setDate(new Date());
newPost.setTitle("New Post p1");
newPost.setDescription("New Descr p1");
newPost.setAuthor(pro.getRef());
ds.save().entity(newPost).now();
Ref<Post> postRef = newPost.getRef();
pro.getDiary().addFirst(postRef);
pro.getMessages().addFirst(postRef);
ds.save().entity(pro).now();
newPost.getReceivers().addAll(pro.getFriends());
Collection<Profile> friends = ds.load().refs(pro.getFriends()).values();
for (Profile friend : friends) {
friend.getMessages().addFirst(newPost.getRef());
}
ds.save().entities(friends).now();
ds.save().entity(newPost).now();
Assert.assertEquals(1, ds.load().key(pro.getKey()).get().getDiary().size());
Assert.assertEquals(1, ds.load().key(pro.getKey()).get().getMessages().size());
Assert.assertEquals(newPost.getRef(), ds.load().key(pro.getKey()).get().getDiary().get(0));
// BIG FAT WARNING
Assert.assertEquals(newPost, ds.load().key(pro.getKey()).get().getDiary().get(0).get());
}
@AfterClass
public static void tearDown() {
ds.clear();
helper.tearDown();
}
}
//
@Entity
class Identifable<T> {
@Id
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return equals((Identifable<?>) obj);
}
public boolean equals(Identifable<?> other) {
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
@Entity @Cache
class Post extends Identifable<Post> {
@Index(IfNotNull.class)
@Load
@Parent
private Ref<Profile> author = null;
@Index(IfNotNull.class)
private Date date = null;
@Index(IfNotNull.class)
private String title = null;
private String description = null;
@Index(IfNotEmpty.class)
@Load
private Set<Ref<Profile>> receivers = new HashSet<Ref<Profile>>();
public Set<Ref<Profile>> getReceivers() {
return receivers;
}
public Ref<Profile> getAuthor() {
return author;
}
public void setAuthor(Ref<Profile> author) {
this.author = author;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Post [author=" + author + ", date=" + date + ", title=" + title
+ ", description=" + description + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Post other = (Post) obj;
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
public Key<Post> getKey() {
return Key.create(Post.class, getId());
}
public Ref<Post> getRef() {
return Ref.create(getKey(), this);
}
}
//
@Entity @Cache
class Profile extends Identifable<Profile> {
@Index
private String email = null;
@Index
private String password = null;
private Date registrationDate = null;
@Index(IfNotNull.class)
private String name = null;
@Index(IfNotNull.class)
private String surname = null;
@Index(IfNotNull.class)
private String fullName = null;
@Index
private String sex = null;
@Index
private Date dateOfBirth = null;
@Index(IfNotEmpty.class)
@Load
private LinkedList<Ref<Post>> diary = new LinkedList<Ref<Post>>();
@Index(IfNotEmpty.class)
@Load
private Set<Ref<Profile>> friends = new HashSet<Ref<Profile>>();
@Index(IfNotEmpty.class)
@Load
private LinkedList<Ref<Post>> messages = new LinkedList<Ref<Post>>();
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(Date registrationDate) {
this.registrationDate = registrationDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Set<Ref<Profile>> getFriends() {
return friends;
}
public LinkedList<Ref<Post>> getDiary() {
return diary;
}
public LinkedList<Ref<Post>> getMessages() {
return messages;
}
@Override
public String toString() {
return "Profile [email=" + email + ", password=" + password
+ ", registrationDate=" + registrationDate + ", name=" + name
+ ", surname=" + surname + ", fullName=" + fullName + ", sex="
+ sex + ", dateOfBirth=" + dateOfBirth + ", diary=" + diary
+ ", friends=" + friends + ", messages=" + messages + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((dateOfBirth == null) ? 0 : dateOfBirth.hashCode());
result = prime * result + ((diary == null) ? 0 : diary.hashCode());
result = prime * result + ((email == null) ? 0 : email.hashCode());
result = prime * result + ((friends == null) ? 0 : friends.hashCode());
result = prime * result
+ ((fullName == null) ? 0 : fullName.hashCode());
result = prime * result
+ ((messages == null) ? 0 : messages.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((password == null) ? 0 : password.hashCode());
result = prime
* result
+ ((registrationDate == null) ? 0 : registrationDate.hashCode());
result = prime * result + ((sex == null) ? 0 : sex.hashCode());
result = prime * result + ((surname == null) ? 0 : surname.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Profile other = (Profile) obj;
if (dateOfBirth == null) {
if (other.dateOfBirth != null)
return false;
} else if (!dateOfBirth.equals(other.dateOfBirth))
return false;
if (diary == null) {
if (other.diary != null)
return false;
} else if (!diary.equals(other.diary))
return false;
if (email == null) {
if (other.email != null)
return false;
} else if (!email.equals(other.email))
return false;
if (friends == null) {
if (other.friends != null)
return false;
} else if (!friends.equals(other.friends))
return false;
if (fullName == null) {
if (other.fullName != null)
return false;
} else if (!fullName.equals(other.fullName))
return false;
if (messages == null) {
if (other.messages != null)
return false;
} else if (!messages.equals(other.messages))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (registrationDate == null) {
if (other.registrationDate != null)
return false;
} else if (!registrationDate.equals(other.registrationDate))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
if (surname == null) {
if (other.surname != null)
return false;
} else if (!surname.equals(other.surname))
return false;
return true;
}
public Key<Profile> getKey() {
return Key.create(Profile.class, getId());
}
public Ref<Profile> getRef() {
return Ref.create(getKey(), this);
}
}
我使用 Objectify 4.0a4 和 App Engine SDK 1.7.2 如果您尝试@Parent
从author
Post
现场移除测试是可以的。
这可能不是 Objectify 错误(很确定),可能是我的概念错误。