Задать вопрос

Как добавить сущность в коллекцию со связью One-To-Many, не извлекая всю коллекцию из БД?

Добрый день. Начал разбираться с JPA-Hibernate. На один свой вопрос так и не смог найти ответа в просторах сети. Вообще то вопроса два. И так, по порядку.

Имеется две сущности:
1)
@Entity
public class Category implements Serializable {
    @Id
    String categoryId;

    String name;

    @OneToMany
    List<SubCategory> subCategories = new ArrayList<SubCategory>();


2)
@Entity
public class SubCategory {
    @Id
    String subCategoryId;

    String subCategoryName;


Все шло гладко, пока не начал писать CrUD операции для сущности SubCategory, а в частности создание новой категории:

@Transactional
@Repository ("subCategoryDao")
public class JpaSubCategoryDaoImpl implements SubCategoryDao {

    @PersistenceContext
    EntityManager em;

    public SubCategory createSubCategory(SubCategory subCategory, String categoryId) {
        Category category = em.getReference(Category.class, categoryId);
        category.getSubCategories().add(subCategory);
        em.persist(subCategory);

        return subCategory;
    }


Здесь появились вопросы. Сущность создается, ложится в БД и другим методом возможно ее извлечь.
НО!!!

Взглянем на вывод sql при обращении к методу.
При добавлении самой первой подкатегории получаем:
Hibernate: 
    select
        category0_.categoryId as category1_0_0_,
        category0_.name as name2_0_0_ 
    from
        Category category0_ 
    where
        category0_.categoryId=?
Hibernate: 
    select
        subcategor0_.Category_categoryId as Category1_1_0_,
        subcategor0_.subCategories_subCategoryId as subCateg2_1_0_,
        subcategor1_.subCategoryId as subCateg1_3_1_,
        subcategor1_.subCategoryName as subCateg2_3_1_ 
    from
        Category_SubCategory subcategor0_ 
    inner join
        SubCategory subcategor1_ 
            on subcategor0_.subCategories_subCategoryId=subcategor1_.subCategoryId 
    where
        subcategor0_.Category_categoryId=?

Hibernate: 
    insert 
    into
        SubCategory
        (subCategoryName, subCategoryId) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        Category_SubCategory
        (Category_categoryId, subCategories_subCategoryId) 
    values
        (?, ?)


То есть, хибернейт ретривит все сущности из коллекции, перед добавлением новой.

Теперь, если мы решим положить в коллекцию еще одну сущность вывод будет следующим:
Hibernate: 
    select
        category0_.categoryId as category1_0_0_,
        category0_.name as name2_0_0_ 
    from
        Category category0_ 
    where
        category0_.categoryId=?
Hibernate: 
    select
        subcategor0_.Category_categoryId as Category1_1_0_,
        subcategor0_.subCategories_subCategoryId as subCateg2_1_0_,
        subcategor1_.subCategoryId as subCateg1_3_1_,
        subcategor1_.subCategoryName as subCateg2_3_1_ 
    from
        Category_SubCategory subcategor0_ 
    inner join
        SubCategory subcategor1_ 
            on subcategor0_.subCategories_subCategoryId=subcategor1_.subCategoryId 
    where
        subcategor0_.Category_categoryId=?

Hibernate: 
    insert 
    into
        SubCategory
        (subCategoryName, subCategoryId) 
    values
        (?, ?)
Hibernate: 
    delete 
    from
        Category_SubCategory 
    where
        Category_categoryId=?
Hibernate: 
    insert 
    into
        Category_SubCategory
        (Category_categoryId, subCategories_subCategoryId) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        Category_SubCategory
        (Category_categoryId, subCategories_subCategoryId) 
    values
        (?, ?)


То есть, хибернейт отчищает JoinTable "Category_SubCategory" от всех данных, относящихся к выбранной категории, и заново записывает туда старые сущности по одной и добавляет новую.

И чем больше сущностей я добавляю, тем больше sql запросов добавляется.

Вопросы:

1) Можно ли добавлять сущности SubCategory в БД, но при этом не доставать все сущности, которые находятся в коллекции Category (т.к. гепотетически их могут быть тысячи и больше)?
2) Если нет, то можно ли, хотя бы, просто добавлять сущности к уже существующим табицам (что бы хибернейт не отчищал таблицу Category_SubCategory и заполнял ее по новой, а просто добавлял новую строчку) ?


Если эти опции не доступны, то как мне оптимизировать данные операции? Возможно отрефакторить классы сущностей?

Это мой первый вопрос в интернете. Так что, если инфы не достаточно, то обязательно апну его, только скажите.
  • Вопрос задан
  • 1084 просмотра
Подписаться 1 Оценить Комментировать
Решения вопроса 1
@DmitriyLamzin Автор вопроса
После некоторого количества медитации:

На первый мой вопрос ответ - нет. Коллекция будет всегда доставаться, как только к ней попытаться обратиться. Выход хорошо описан здесь.

Второй вопрос. Если все же делать через ассоциацию One to Many. То нужно делать не через JoinTable, что по умолчанию, а через @JoinColumn. Тогда sql для любой итерации добавления объекта будет выглядеть так:
Hibernate:
insert
into
SubCategory
(subCategoryName, subCategoryId)
values
(?, ?)
Hibernate:
update
SubCategory
set
subCategories_categoryId=?
where
subCategoryId=?
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@goshan_p
Точно не скажу, так как сам начинающий и не задавался этим вопросом. Но есть предположение, опробуете? У SubCategory должно быть поле ссылающееся на родителя - Category categoryId c аннотацией "@ManyToOne(orphanRemoval=true)". При создании сущности указываете родителя и делаете persist сущности при том не вызывая родителя никак. Проверьте, самому стало интересно) Правда пока нет возможности опробывать
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы