2010-12-09 16 views
6

Después de leer esta publicación JPA map relation entity parentID Intenté aplicar esto a mi código, pero esto no funcionó.Cómo correlacionar una relación padre/hijo en el mismo objeto con JPA

Este es el código que tengo en mi objeto

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

} 

Ahora bien, esta es la prueba corro

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

} 

Esta línea de la prueba siempre fracasan.

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

Sobre la base de la configuración que tengo por mis relaciones, Hibernate no puede recuperar la subcategoría y yo no sé por qué. Ahora realmente espero que esto no sea algo estúpido de mi parte porque me voy a haber disparado a mí mismo (incluso si es tarde y estoy cansado). Por cierto, no me importan las variables públicas en el código, estoy usando play! (Playframework) y se encarga de la encapsulación. Gracias de antemano por cualquier ayuda

Respuesta

5

No es un problema de los padres y el niño asignación a la misma clase. - El problema es que necesitas mantener los dos extremos de la relación bidireccional a mano.

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

Por cierto: Si se establece sólo en un lado (el que se encarga de almacenar la relación en la base de datos), almacenar y recargar la entidad trabajará en algunos casos también. (Y encontrarás este sucio truco en muchos tutoriales antiguos). Pero en mi opinión, es una mala práctica. (En su caso de prueba, sería necesario limpiar el caché antes de volver a cargar el elemento principal después de guardar el elemento secundario).

+0

Esto es exactamente lo que hice. Agregué un método para agregar una subcategoría a una categoría principal. Modifiqué mi prueba en consecuencia y funciona exactamente como quiero ahora. Muchas gracias Ralph. Y gracias a todos los demás por sus respuestas. – Alain

2

El código que se muestra en su pregunta no agrega nada al subCategories. Solo lo inicializa con una lista vacía. Creo que se necesita algo así como

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

Así, según entiendo (y leído) el código correctamente, Hibernate no lo hace (no se puede) recuperar las subcategorías, ya que este permanece vacía después de llamar new Category(sportCat, "Hockey", false).save();

0

Probablemente se encontraba esperando ser suficiente para agregar la entidad padre al niño, pero por lo que he visto, Hibernate requiere que mantengas ambos extremos de una relación de uno a muchos.

En otras palabras, debe agregar la categoría secundaria a la lista de categorías principal.

Es descrito aquí: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir

Y también aquí (con una edición extra de almacenamiento en caché): Hibernate @OneToMany with mappedBy (parent-child) relationship and cache problem

Cuestiones relacionadas