JPA с Hibernate 3 - переполнение стека ManyToMany и множественные ошибки - PullRequest
5 голосов
/ 21 октября 2010

Я сталкиваюсь с проблемами при получении данных для сущностей, имеющих двунаправленное отношение «многие ко многим».Если я использую List для хранения сущностей, я не могу одновременно извлечь несколько сумок.Если я изменю свой код на использование Set, я получу сообщение об ошибке переполнения стека.

Подробности:

  • Spring 3.0.3
  • Hibernate-core: 3.5.1-Final
  • Hibernate-аннотации: 3.5.1-Final
  • Hibernate-Common-Annotations: 3.2.0-Final
  • hibernate-entitymanager: 3.5.1-Final
  • База данных Mysql
  • Junit 4

У пользователя много банковских счетов;У банковского счета может быть много пользователей

User.java

@ManyToMany(fetch = FetchType.EAGER, mappedBy="user") 
private List<BankAccount> bankAccounts = new ArrayList<BankAccount>();

BankAccount.java

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_bankaccount", 
           joinColumns = @JoinColumn(name="bank_account_id"), 
           inverseJoinColumns = @JoinColumn(name = "user_id")
)
private List<User> user = new ArrayList<User>();

Таблицы БД

Users
user_id PK

Bankaccount
bank_account_id PK

user_bankaccount
bank_account_id PK ( references bankaccount.bank_account_id )
user_id PK ( references user.user_id )

выпуски

  1. когда я пытаюсь получить все данные пользователей (getAllUsers) с помощью тестового примера JUnit, я не могу получить несколько пакетов одновременно с ошибкой.
  2. Если я использую Set иHashSet вместо List и ArrayList соответственно, я получаю ошибку stackoverflow.

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

Ответы [ 3 ]

2 голосов
/ 21 октября 2010

(оставим пока атрибут fetch в стороне). Ваше сопоставление совершенно правильно и является правильным способом сопоставления двунаправленных отношений «многие ко многим». Из спецификации JPA 2.0:

2.10.4 Двунаправленные отношения ManyToMany

...

Пример:

@Entity
public class Project {
    private Collection<Employee> employees;

    @ManyToMany
    public Collection<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Collection<Employee> employees) {
        this.employees = employees;
    }
    ...
}

@Entity
public class Employee {
    private Collection<Project> projects;

    @ManyToMany(mappedBy="employees")
    public Collection<Project> getProjects() {
        return projects;
    }
    public void setProjects(Collection<Project> projects) {
        this.projects = projects;
    }
    ...
}

В этом примере:

  • Сущность Project ссылается на коллекцию Сущностей Employee.
  • Entity Employee ссылается на коллекцию Entity Project.
  • Субъект Project является владельцем отношений.

...

При этом я не уверен в поведении при использовании EAGER выборки с обеих сторон (это приведет к бесконечному циклу?), Спецификация JPA довольно размыта по этому поводу, и я не могу найти четкого упоминания о том, что это запрещено. Но держу пари, что это часть проблемы.

Но в конкретном случае Hibernate я бы ожидал, что Hibernate сможет обрабатывать циклы, как упомянуто в этом комментарии от Эммануила Бернарда:

LAZY или EAGER должны быть ортогональны проблеме бесконечного цикла в кодовой базе. Hibernate знает, как обрабатывать циклические графы

Как ни странно, я недавно ответил на очень похожий вопрос (очень близкая проблема). Может быть намек на то, что что-то не так в Hibernate (мое понимание вышеизложенного комментария состоит в том, что использование EAGER для извлечения с обеих сторон должно работать).

Таким образом, я завершу свой ответ таким же образом: , если вы можете предоставить контрольный пример, позволяющий воспроизвести проблему , откройте проблему Jira.

2 голосов
/ 08 июля 2019

Я сталкивался с подобной проблемой, и основной причиной является код генерации Lombok, как Vjeetje упомянул выше.Мой код использует аннотацию @Data, которая генерирует методы hashCode и ToString с взаимозависимыми полями, и эта структура приводит к зависанию Hibernate.Поэтому следует избегать вызовов бесконечного цикла, в моем случае я просто добавил параметры исключения, такие как @EqualsAndHashCode (exclude = "зависимый_лист") и @ToString (exclude = "зависимый_ список").Это решает проблему переполнения стека.

1 голос
/ 21 октября 2010

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

...