5

我想实现的是:当我删除类别时,它的所有相关文章都可以删除,当我删除文章时,它也可以在它的相关类别中删除。

我设置了映射关系@ManyToOne,和@OneToMany(cascade = CascadeType.ALL, mappedBy = " category")下面的代码一样,但是我在做单元测试的时候,出现了几个问题,它不起作用。这是我的代码:

@Entity
public class Article extends Model {
    @Id
    public Long id;     

    @Constraints.Required       
    public String title;

    @Constraints.Required
    @Lob
    @Basic(fetch = FetchType.LAZY)
    public String content;

    public boolean published = false;

    @Formats.DateTime(pattern="yyyy-MM-dd")
    public Date publishDate;

    @ManyToMany(cascade = CascadeType.REMOVE)
    @Column(nullable = true)
    public List<Tag> tags = new ArrayList<Tag>();

    @ManyToOne
    @Column(nullable = true)
    public Category category;

    public static Finder<Long, Article> finder = new Finder<Long, Article>(Long.class, Article.class);

    public Article(String title, String content, Tag[] tags) {
        this.title = title;
        this.content = content;
        this.publishDate = new Date();
        this.category = null;
        if(tags != null)
            for(Tag t : tags)
                this.tags.add(t);
    }

    public static List<Article> all() {
        return finder.orderBy("publishDate desc").findList();
    }

    public static Article create(String title, String content, Tag[] tags) {
        Article article = new Article(title, content, tags);
        article.save();
        article.saveManyToManyAssociations("tags");
        return article;
    }

    public static void delete(Long id) {
        finder.ref(id).delete();
    }

    public static void setCategory(Article article, Category c) {
        if(article.category != null)
            Category.removeArticle(c, article);
        article.category = c;   
        Category.addArticle(c, article);
        article.update();
    }
}

这是类别类:

@Entity
public class Category extends Model {
    @Id
    public Long id; 

    @Required
    public String name;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
    Set<Article> articles;

    public static Finder<Long, Category> finder = new Finder<Long, Category>(Long.class, Category.class);

    public Category(String name) {
        this.name = name;
    }

    public static List<Category> all() {
         return finder.all();
    }

    public static Category create(String name) {
        Category category = new Category(name);
        category.articles = new HashSet<Article>();
        category.save();
        return category;
    }

    public static String rename(Long id, String newName) {
        Category category = finder.ref(id);
        category.name = newName;
        category.update();
        return newName;
    }

    public static void delete(Long id) {
        Category c = finder.ref(id);
        c.delete(); 
    }

    public static void addArticle(Category c, Article article) {
        if(! c.articles.contains(article)) {
            article.category = c;
            c.articles.add(article);
            article.update();
        }
    }

    public static void removeArticle(Category c, Article article) {
        if(c.articles.contains(article)) {
            Article.delete(article.id);
            c.articles.remove(article);
        }
    }

    public static Map<String,String> options() {
        LinkedHashMap<String,String> options = new LinkedHashMap<String,String>();
        for(Category c: Category.finder.orderBy("name asc").findList()) {
            options.put(c.id.toString(), c.name);
        }
        return options;
    }
}

这是我的测试:

@Test
public void categoryTest() {
    Category c1 = Category.create("Play");
    Category c2 = Category.create("SSH");
    Category c3 = Category.create("Python");
    Category c4 = Category.create("web");

    String newName = Category.rename(c3.id, "Django");

    Category.delete(c2.id);

    List<Category> list = Category.all();
    assertEquals(3, list.size());

    Map<String, String> map = Category.options();


    Article a1 = Article.create("Hello", "Hello world, My Blog!", null);
    Article a2 = Article.create("My Blog", "It's build by play framework", null);
    Article a3 = Article.create("Play", "Install Play", null);

    Category.addArticle(c1, a1);
    Category.addArticle(c1, a2);
    Category.addArticle(c3, a3);

    Category.delete(c3.id);
    Category.removeArticle(c1, a1);

    assertEquals(2, list.size());
    assertEquals("Play", list.get(0).name);

    //assertEquals("Django", map.get("3"));
    assertEquals(1, Article.all().size());

    assertEquals(1, c1.articles.size());
    assertEquals(false, c1.articles.contains(a1));
}

下面的资产不能通过。

assertEquals(2, list.size()); 

这意味着现在不能删除类别,但是

Category.delete(c2.id); 

作品!

assertEquals(1, Article.all().size()); 

以上资产不能通过。这意味着类别不能删除它的相关文章。我应该怎么做才能解决这个问题?

4

1 回答 1

1

In above code there is only one assertion that do not pass. This is:

assertEquals(2, list.size()); 

Why it is happening?

Let's look at the following code:

List<Category> list = Category.all();
assertEquals(3, list.size());
Category.delete(c3.id);
assertEquals(2, list.size());

In first line we take all categories and there are three of them.
In third line we delete one of categories. This category is properly deleted but list of categories computed in first line has still three elements. This is because this list does not represent the current state of database. It still holds result computed in first line of above code.
To make second assertion work properly we have to add following line between line 3 and 4:

list = Category.all();

Above code will compute current list of categories and assign it to variable `list'.

于 2015-01-11T01:04:11.643 回答