JPA: Eclipselink не сохраняет двунаправленные отношения в базе данных - PullRequest
1 голос
/ 22 октября 2010

Моя модель домена в приложении Java EE 6 содержит двунаправленные отношения, подобные следующим:

@Entity
public  class Users implements PrimaryKeyHolder<String>, Serializable {
  @Id
  private String username;

  @ManyToMany(mappedBy= "users")
  private List<Category> categories;

  public List<Category> getCategories() {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }
    return Collections.unmodifiableList(categories);
  }

  public void addCategory(Category category) {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }

    categories.add(category);
    if (!category.getUsers().contains(this)) {
        category.addUser(this);
    }
  }

  public void removeCategory(Category category) {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }

    categories.remove(category);
    if (category.getUsers().contains(this)) {
        category.removeUser(this);
    }
  }

  public void setCategories(Collection<Category> categories) {
    if (this.categories == null) {
        this.categories = new ArrayList<Category>();
    }

    for (Iterator<Category> it = this.categories.iterator(); it.hasNext();) {
        Category category = it.next();
        it.remove();
        if (category.getUsers().contains(this)) {
            category.removeUser(this);
        }
    }

    for (Category category : categories) {
        addCategory(category);
    }
  }
}

@Entity
public class Category implements PrimaryKeyHolder<Long>, Serializable {
  @Id
  private Long id;

  @ManyToMany
  private List<User> users;

  public List<User> getUsers() {
    if (users == null) {
        users = new ArrayList<User>();
    }
    return Collections.unmodifiableList(users);
  }

  protected void addUser(User user) {
    if (users == null) {
        users = new ArrayList<User>();
    }
    users.add(user);
  }

  protected void removeUser(User user) {
    if (users == null) {
        users = new ArrayList<User>();
    }
    users.remove(user);
  }
}

ОБНОВЛЕНИЕ : я добавил код управления отношениями.Отношения устанавливаются только на стороне пользователя, поэтому методы добавления / удаления защищены в классе Категория.Я устанавливаю категории для пользователя через setCategories.

. Eclipselink правильно генерирует таблицу соединений CATEGORY_USERS.Тем не менее, он не сохраняет никакой информации в нем (он только кэширует информацию).Например, когда я выполняю операцию поиска в менеджере сущностей (например, в пользователе), он возвращает полный граф объектов (включая отношение категории).Но когда я смотрю на таблицы, информация не обновляется (даже если транзакции зафиксированы).Я также вставил операцию очистки в мой код, но безуспешно.Основная информация (например, столбцы String, Integer и т. Д.) Корректно сохраняется и обновляется.После перевода уровня журнала в FINE я вижу, что никакие операторы SQL не выполняются для отношений и таблицы соединений соответственно.Но я вижу операторы SQL для однонаправленных отношений.

Моя модель данных покрыта обширными модульными тестами, которые все проходят успешно.Я в основном делаю ту же операцию, что и в контейнере, фиксирую транзакцию, перезагружаю сущности из БД и проверяю, правильно ли установлены отношения, какие они есть (я использую базу данных дерби в памяти для тестирования).

Мой сервер приложений - Glassfish v3.1-b17.

Любая помощь приветствуется.Спасибо, Тео

Ответы [ 3 ]

3 голосов
/ 22 октября 2010

Убедитесь, что вы устанавливаете обе стороны отношений. Спецификация требует, чтобы приложение устанавливало обе стороны отношения, поскольку в JPA нет ведения отношения.

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

После бесконечных часов попыток я наконец-то нашел решение: я просто изменил сторону владения отношениями, то есть я поместил атрибут mappedBy в сущность категории следующим образом:

@ManyToMany(mappedBy= "categories")
private List<User> users;

Объяснение дляэто можно найти здесь

0 голосов
/ 25 октября 2010

Четыре очка:

1.- Если у вас есть ошибка, проще найти решение, изолирующее их в примере (или модульном тесте), который воспроизводит ошибку. В вашем случае вы могли бы сделать пример с более простыми методами получения и установки (например, , исключив использование unmodifiableList и другие ненужные методы для тестирования, на самом деле выдают ).

2.- Я советую вам использовать pojos для модели , без какой-либо логики. Итак, удалите логику из pojos.

3.- Мы используем eclipselink и у нас нет проблем с сохранением отношений. Таким образом, более вероятно, что ошибка будет в вашем коде.

4.- Проверка отношения аннотирования с "cascade = javax.persistence.CascadeType.ALL"

Извинения за мой плохой английский: (* ​​1016 *

...