2010-12-09 48 views
6

Après avoir lu cet article JPA map relation entity parentID J'ai essayé d'appliquer ceci à mon code mais cela n'a pas fonctionné pour moi.Comment mapper une relation parent/enfant sur le même objet avec JPA

C'est le code que j'ai dans mon objet

@Entity 
public class Category extends Model { 

public static final int EASY = 1; 
public static final int MEDIUM = 2; 
public static final int HARD = 3; 
public static final int VERRY_HARD = 4; 

public String name; 
public String fullName; 
public boolean active; 
public Date createdOn; 
public int difficulty; 

@ManyToOne 
@JoinColumn(name = "FK_PARENT_CATEGORY") 
public Category parentCategory; 

@OneToMany(mappedBy="parentCategory", cascade = CascadeType.ALL) 
public List<Category> subCategories; 

public Category(Category parentCategory, String name, boolean active) { 
    this.name = name; 
    this.active = active; 
    this.parentCategory = parentCategory; 
    this.subCategories = new ArrayList<Category>(); 
    this.createdOn = new Date(); 
    this.difficulty = Category.EASY; 
    this.fullName = name; 
    if (parentCategory != null) 
     this.fullName = parentCategory.fullName + "/" + this.fullName; 

} 

Maintenant, c'est le test que je lance

@Test 
public void testParentAndSubCategories() { 

    //Create the parent category 
    new Category(null, "Sport", true).save(); 
    Category sportCat = Category.find("byName", "Sport").first(); 

    //Test the newly created parent category state 
    assertNotNull(sportCat); 
    assertEquals("Sport", sportCat.name); 
    assertEquals(true, sportCat.active); 
    assertEquals("Sport", sportCat.fullName); 
    assertNull(sportCat.parentCategory); 
    assertEquals(0, sportCat.subCategories.size()); 

    //Create the subCategory 
    new Category(sportCat, "Hockey", false).save(); 
    Category hockeyCat = Category.find("byName", "Hockey").first(); 

    // Test the newly created sub category 
    assertNotNull(hockeyCat); 
    assertEquals("Hockey", hockeyCat.name); 
    assertEquals(false, hockeyCat.active); 
    assertEquals("Sport/Hockey", hockeyCat.fullName); 
    assertNotNull(hockeyCat.parentCategory); 
    assertEquals("Sport", hockeyCat.parentCategory.name); 
    assertEquals(0, sportCat.subCategories.size()); 

    //Fetch new values for parent category 
    sportCat = Category.find("byName", "Sport").first(); 

    // Test updated parent category 
    assertEquals(1, sportCat.subCategories.size()); 
    assertEquals("Hockey", sportCat.subCategories.get(0).name); 

} 

Cette ligne du test échouent toujours.

// Test updated parent category 
    assertEquals(1, sportCat.subCategories.size()); 

Sur la base de la configuration que j'ai pour mes relations, Hibernate ne peut pas récupérer la sous-catégorie et je ne sais pas pourquoi. Maintenant j'espère vraiment que ce n'est pas stupide de ma part parce que je vais me tirer dessus (même s'il est tard et que je suis fatigué). En passant, ne vous occupez pas des variables publiques dans le code, j'utilise play! (Playframework) et il s'occupe de l'encapsulation. Merci d'avance pour toute aide

Répondre

5

Il est pas un problème de parent de la cartographie et de l'enfant à la même classe. - Le problème est que vous devez maintenir les deux extrémités de la relation bidirectionnelle à la main.

child.setParent(parent) 
parent.addChild(child) 

BTW: Réglage uniquement sur un côté (celui qui est responsable de stocker la relation dans la base de données), de stocker et de recharger l'entité fonctionnera dans certains cas aussi. (Et vous trouverez ce truc sale dans de nombreux anciens tutoriels). Mais à mon avis c'est une mauvaise pratique. (Dans votre cas de test, il faudrait nettoyer le cache avant de recharger le parent après l'enregistrement de l'enfant.)

+0

C'est exactement ce que j'ai fait. J'ai ajouté une méthode pour ajouter une sous-catégorie à une catégorie parente. J'ai modifié mon test en conséquence et cela fonctionne exactement comme je le veux maintenant. Merci beaucoup Ralph. Et merci à tous les autres pour leurs réponses. – Alain

2

Le code qui est indiqué dans votre question n'ajoute rien à subCategories. Il l'initialise uniquement avec une liste vide. Je pense que vous avez besoin de quelque chose comme

if (parentCategory != null) { 
    parentCategory.subCategories.add(this); 
} 

Donc, si je comprends (et lu) votre code correctement, Hibernate ne (ne peut pas) récupérer les sous-catégories, car il est reste vide après avoir appelé new Category(sportCat, "Hockey", false).save();

0

Vous étiez probablement m'attendant à être assez pour ajouter l'entité parent à l'enfant, mais d'après ce que j'ai vu, Hibernate vous demande de maintenir les deux extrémités d'une relation un-à-plusieurs. En d'autres termes, vous devez ajouter la catégorie enfant à la liste des catégories du parent.

Il est décrit ici: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir

Et ici (avec un problème de mise en cache supplémentaire): Hibernate @OneToMany with mappedBy (parent-child) relationship and cache problem