2013-03-16 6 views
5

Chcę zrozumieć, że: po usunięciu kategorii wszystkie powiązane artykuły można usunąć, a po usunięciu artykułu można również usunięte w powiązanej kategorii.Graj w frameworku 2.1 i Ebean: @ManyToOne i @OneToMany, Problemy z CRUD i kaskadą

Ustawiłem relację mapowania @ManyToOne i @OneToMany(cascade = CascadeType.ALL, mappedBy = " category") tak jak poniższy kod, ale kiedy robiłem test jednostkowy, pojawiło się kilka problemów, to nie działa. To jest mój kod:

@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(); 
    } 
} 

i jest to klasa Kategoria:

@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; 
    } 
} 

To moja próba:

@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)); 
} 

Poniżej assetion nie może przejść.

assertEquals(2, list.size()); 

Oznacza to kategoria może”być już usunięte, ale

Category.delete(c2.id); 

działa!

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

Powyższy składnik aktywów nie może przejść. Oznacza to, że kategoria nie może usuwać powiązanych artykułów. Co należy zrobić, aby rozwiązać ten problem?

Odpowiedz

1

W powyższym kodzie jest tylko jedno twierdzenie, które nie przechodzi. Jest to:

assertEquals(2, list.size()); 

Dlaczego tak się dzieje? wygląd

Let pod następującym kodzie:

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

W pierwszej linii bierzemy wszystkie kategorie i tam są trzy z nich.
W trzecim wierszu usuwamy jedną z kategorii. Ta kategoria została poprawnie usunięta, ale lista kategorii wyliczona w pierwszej linii ma jeszcze trzy elementy. Wynika to z tego, że ta lista nie odzwierciedla bieżącego stanu bazy danych. Nadal utrzymuje wynik obliczony w pierwszym wierszu powyższego kodu.
Aby drugą pracę twierdzenie właściwie musimy dodać następującą linię pomiędzy linią 3 i 4:

powyższy kod będzie obliczyć aktualną listę kategorii i przypisać ją do zmiennej `listy”.