如何使用 JPA 在同一对象上映射父/子关系
阅读这篇文章后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) 并且它负责封装。预先感谢您的任何帮助
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 {
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这不是将父子映射到同一个类的问题。 - 问题是您需要手动维护双向关系的两端。
顺便说一句:仅在一侧(负责在数据库中存储关系的一侧)设置它,存储和重新加载实体在某些情况下也将起作用。 (你会在许多旧教程中发现这个肮脏的把戏)。但在我看来这是不好的做法。 (在您的测试用例中,在保存子级后重新加载父级之前,需要清理缓存。)
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.
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.)
您的问题中显示的代码不会向
subCategories
添加任何内容。它仅使用空列表对其进行初始化。我认为你需要类似的东西,所以,正如我正确理解(并阅读)你的代码一样,Hibernate 不会(无法)检索子类别,因为它在调用 new Category(sportCat, "Hockey", false) 后保持为空。保存();
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 likeSo, 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();
您可能期望将父实体添加到子实体中就足够了,但从我所见,Hibernate 要求您维护一对多关系的两端。
换句话说,您必须将子类别添加到父类别的列表中。
这里描述的是:
http:// docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir
还有这里(有额外的缓存问题):
Hibernate @OneToMany 具有mappedBy(父子)关系和缓存问题
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