Как бы я отобразил отношения родитель / потомок в одном объекте с JPA - PullRequest
8 голосов
/ 09 декабря 2010

После прочтения этого поста JPID объекта отношения с картой JPA Я пытался применить это к своему коду, но у меня это не сработало.

Это код, который у меня есть в моем объекте

@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), и он заботится об инкапсуляции.Заранее благодарен за любую помощь

Ответы [ 3 ]

6 голосов
/ 09 декабря 2010

Это не проблема сопоставления родительского и дочернего элементов в одном классе.- Проблема заключается в том, что вам необходимо поддерживать оба конца двунаправленных отношений вручную.

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

КСТАТИ: установка его только на одной стороне (той, которая отвечает за сохранение отношений вбаза данных), сохранение и перезагрузка сущности будет работать и в некоторых случаях.(И вы найдете этот подвох во многих старых уроках).Но на мой взгляд это плохая практика.(В вашем тестовом случае потребуется очистить кэш перед перезагрузкой родительского элемента после сохранения дочернего элемента.)

3 голосов
/ 09 декабря 2010

Код, указанный в вашем вопросе, ничего не добавляет к subCategories.Он только инициализирует его с пустым списком.Я думаю, вам нужно что-то вроде

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

Итак, как я правильно понимаю (и прочитал) ваш код, Hibernate не (не может) извлечь подкатегории, потому что он остается пустым после вызова new Category(sportCat, "Hockey", false).save();

0 голосов
/ 09 декабря 2010

Возможно, вы ожидали, что этого будет достаточно, чтобы добавить родительскую сущность к ребенку, но, как я видел, Hibernate требует, чтобы вы поддерживали оба конца отношения один ко многим.

Другими словами, вы должны добавить дочернюю категорию в список категорий родителей.

Это описано здесь: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir

А также здесь (с дополнительной проблемой кеширования): Hibernate @OneToMany с отношениями mappedBy (родитель-потомок) и проблемой кэширования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...