8

阅读这篇文章JPA 映射关系实体 parentID后,我尝试将其应用于我的代码,但这对我不起作用。

这是我的对象中的代码

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

}

现在这是我运行的测试

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

}

这行测试总是失败。

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

根据我的关系设置,Hibernate 无法检索子类别,我不知道为什么。现在我真的很希望这不是我的愚蠢,因为我要自己开枪(即使已经很晚了,我很累)。顺便说一句,不要介意代码中的公共变量,我使用的是 play!(playframework),它负责封装。提前感谢您的帮助

4

3 回答 3

6

将父子映射到同一个类不是问题。- 问题是您需要手动维护双向关系的两端。

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

顺便说一句:仅在一侧(负责将关系存储在数据库中的一侧)设置它,在某些情况下也可以存储和重新加载实体。(你会在许多旧教程中发现这个肮脏的把戏)。但在我看来,这是不好的做法。(在您的测试用例中,需要在保存子节点后重新加载父节点之前清理缓存。)

于 2010-12-09T11:23:36.800 回答
3

您的问题中显示的代码不会向subCategories. 它只用一个空列表初始化它。我认为你需要类似的东西

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

因此,正如我正确理解(并阅读)您的代码一样,Hibernate 不会(无法)检索子类别,因为它在调用后保持为空new Category(sportCat, "Hockey", false).save();

于 2010-12-09T05:27:19.367 回答
0

您可能期望将父实体添加到子实体就足够了,但据我所知,Hibernate 要求您保持一对多关系的两端。

换句话说,您必须将子类别添加到父类别的列表中。

它在这里描述:http: //docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir

还有这里(有一个额外的缓存问题): Hibernate @OneToMany with mappedBy (parent-child) 关系和缓存问题

于 2010-12-09T08:31:46.377 回答