开发者

How would I map a parent/child relation on same object with JPA

After reading this post JPA map relation entity parentID I tried applying this to my code but this didn't work for me.

This is the code I have in my Object

@Entity
public class Category extends Model {
开发者_JAVA技巧
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;

}

Now this is the test I run

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

}

This line of the test always fail.

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

Based on the setup I have for my relations, Hibernate can't retrieve the subcategory and I don't know why. Now I really really hope this is not something stupid on my part because I'm going to have shoot myself (Even if it's late and I'm tired). By the way don't mind the public variables in the code, I'm using play!(playframework) and it takes care of encapsulation. Thanks in advance for any help


It is not a problem of mapping parent and child to the same class. - The problem is that you need to maintain both ends of the bi-directional-relationship by hand.

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

BTW: Setting it only on one side (the one which is responsible to store the relationship in the database), store and reload the entity will work in some cases too. (And you will find this dirty trick in many old tutorials). But in my opinion it is bad practice. (In your test case, it would require to clean the cache before you reload the parent after the child is saved.)


The code that is shown in your question doesn't add anything to subCategories. It only initialize it with an empty list. I think you need something like

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

So, as I understand (and read) your code correctly, Hibernate doesn't (cannot) retrieve the subcategories because it's stays empty after calling new Category(sportCat, "Hockey", false).save();


You were probably expecting to be enough to add the parent entity to the child, but from what I've seen, Hibernate requires you to maintain both ends of a one-to-many relationship.

In other words, you have to add the child Category to the parent's list of categories.

It's described here: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir

And also here (with an extra caching issue): Hibernate @OneToMany with mappedBy (parent-child) relationship and cache problem

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜