在以一对多关系替换父项后删除孤立

时间:2014-08-21 21:18:29

标签: java google-app-engine transactions google-cloud-datastore jdo

我将School个实体持有PersistenceManager数据存储区。 SchoolStudent s具有一对多的关系:

@PersistenceCapable
public class School implements Serializable {
    ...
    @Persistent(mappedBy = "school") @Element(dependent = "true") private Set<Student> students = new HashSet<Student>();
    ...
    @PrimaryKey private String key;

    School(String name, Level level) {
        this.name = Objects.requireNonNull(name);
        this.level = Objects.requireNonNull(level);
        this.key = name + "_" + level;
    }
    ...
}

@PersistenceCapable
public class Student implements Serializable {
    ...
    @PrimaryKey private Key key;

    Student(String name, School school, int grade) {
        this.name = Objects.requireNonNull(name);
        this.grade = Objects.requireNonNull(grade);
        this.school = Objects.requireNonNull(school);
        key = KeyFactory.createKey(this.school.getKey(), this.getClass().getSimpleName(), name + "_" + grade + "_" + school.getName());
    }
    ...
}

说我坚持使用SchoolStudent来保持School school = new School("foo", Level.MIDDLE); Student s1 = new Student("A", school, 6); Student s2 = new Student("B", school, 6); Student s3 = new Student("C", school, 6); school.addStudent(s1); school.addStudent(s2); school.addStudent(s3); PMF.get().getPersistenceManager().makePersistent(school);

School school = new School("foo", Level.MIDDLE); // Will have the same primary key as the first!
Student s1 = new Student("A", school, 6);
Student s2 = new Student("B", school, 6);
Student s3 = new Student("D", school, 6); // Note the change! C -> D
// Some code that makes s1 and s2 different from their previous state
school.addStudent(s1);
school.addStudent(s2);
school.addStudent(s3);
PMF.get().getPersistenceManager().makePersistent(school);

后来,

School

由于PrimaryKey每次都会有"foo_middle"(即Student),所以第二次持久操作会覆盖第一次。只有 1 School foo

幸运的是, Student A Student B 的更新版本已经替换了数据存储区中的旧版本,因为它们的主键是相同的。但是,数据存储区中将有 4 School个实体,因为 Student C 未销毁。这种不一致性在我的应用程序的一个特定视图中变得相关。我怎样才能最有效地摆脱这个孤儿?

这是我尝试/考虑的内容:

  1. 在添加新集之前,明确删除所有Student个实体(此操作将cascade并销毁它所拥有的所有School),而不是让GAE处理替换。这是有问题的,因为(1)在读/写方面成本较高(2)删除和重新添加需要保持独立,严格地在另一个之后,所以新的Student不要&# 39;也被删除。这可以用交易来实现吗?
  2. 在保留第二个School并针对school.getStudents()进行检查之前,通过查询显式删除所有孤立的Student。这种方法与它相关的成本很高,并且增加了很多复杂性。
  3. 另一种可能性是以这样的方式设计对象,以便我可以查询所有未成为孤儿的School。然后,我可以固定的间隔删除孤儿,只是为了保持较低的存储成本。但是,我还没有看到如何实现这样的结果,同时仍然保留Student和{{1}}来替换保留的旧实例(通过使用相同的主键)。

1 个答案:

答案 0 :(得分:1)

学生'C'没有死的事实,你只是在重写foo_middle而不是摧毁它。数据库的工作方式是找到重复的ID时,它会覆盖现有的ID。当你添加学生'A'和'B'时,你会看到这一点。数据库不会杀死任何原件只是替换其余数据(ID除外)。根据您的使用情况,您有2个选项:

1)如果删除的次数少于一半,则可以添加更新/更新日期字段,在更新后,您只需查询所有日期在当前之前的人,然后删除它们。

2)如果您要删除超过一半的祖先查询,那么请清除所有学生。