Лучший способ использовать JPA с отношениями - PullRequest
0 голосов
/ 01 августа 2011

Когда у меня есть сущность со связями, я не знаю, какой лучший способ сохранить изменения в БД.

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

public class Permessitemporanei implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID_permesso")
    private Integer iDpermesso;
    @Column(name = "Stato_permesso")
    private Integer statopermesso;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "iDpermesso")
    private Collection<Accessiconpermesso> accessiconpermessoCollection;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "iDpermesso")
    private Ingressiconpermesso  ingressiconpermesso;

Как вы можете видеть, он связан с двумя другими объектами с отношениями OneToMany и OneToOne.Я использую Glassfish с jta, поэтому транзакции и entityManagers управляются контейнером.

В то время у меня есть отсоединенный (терминология JPA) экземпляр Permessitemporanei в памяти.Я должен сохранить следующие изменения в базе данных: 1- должно быть удалено связанное ingressiconpermesso 2 - должно быть создано новое ingressiconpermesso 3 - поле statopermesso должно быть обновлено 4 - новое Accessiconpermesso должно быть добавлено в коллекцию accessiconpermessoCollection

Какой лучший способ сделать это?Возможно, я могу сделать все необходимые изменения в экземпляре Permessitemporanei и объединить его, но у меня было много проблем с этим, и я начал думать, что это не правильная сторона отношений, чтобы продолжать изменения.Для меня более естественно сохранять объект за раз, поэтому исключая все эти каскад = CascadeType.ALL.

Предположим, мой экземпляр Permessitemporanei называется 'permesso';мой код выглядит примерно так:

  1. getEntityManager (). remove (permesso.ingressiconpermesso);
  2. getEntityManager (). persist (новый Ingressiconpermesso);
  3. getEntityManager (). merge (permesso) // как только его поле statopermesso было обновлено;
  4. getEntityManager (). perist (новый Accessiconpermesso);

Очевидно, таким образом я долженвручную добавьте в память «permesso» все изменения, которые я внес в базу данных.

Есть ли лучший подход?

Кстати, все отношения JPA, которые я видел, являются двунаправленными.Могу ли я сделать их однонаправленными?Другими словами, можно ли безопасно удалить код:

@ OneToMany (cascade = CascadeType.ALL, mappedBy = "iDpermesso") частная коллекция accessiconpermessoCollection;

из объекта Permessitemporanei, сохранив его насубъект Accessiconpermesso или я нарушаю JPA?

Спасибо, Филиппо

1 Ответ

3 голосов
/ 01 августа 2011

Мне нравится подходить к сложным обновлениям сущностей:

  1. Начать новую транзакцию.
  2. Внесите все изменения, которые я хочу внести в мои объекты в памяти.
  3. Скажите EntityManager, что я сделал, когда закончил.
  4. Совершить транзакцию.

Но обо всем по порядку, вам, вероятно, будет гораздо проще, если вы начнете с неотсоединенного экземпляра Permessitemporanei:

Permessitemporanei persistentInstance = em.find(Permessitemporanei.class, detachedInstance.getId());

Затем выполните все изменения в памяти, сообщите EntityManager и совершите транзакцию:

//begin a transaction
em.getTransaction().begin();

//remember the old Ingressiconpermesso instance
Ingressiconpermesso oldIngression = persistentInstance.getIngressiconpermesso();

//create a new Ingressiconpermesso instance
Ingressiconpermesso newIngression = new Ingressiconpermesso();
//call newIngression.set...() methods here

//associate the new Ingressiconpermesso with the Permessitemporanei 
persistentInstance.setIngressiconpermesso(newIngression);

//update statopermesso
persistentInstance.setStatopermesso(7); //replace '7' with whatever the real value is

//add a new Accessiconpermesso
Accessiconpermesso accession = new Accessiconpermesso();
//call accession.set...() methods here

//associate the Accessiconpermesso with the Permessitemporanei
accession.setPermissitemporanei(persistentInstance);

//now tell the EntityManager what we did
em.remove(oldIngression);        //delete the old Ingressiconpermesso 
em.persist(newIngression);       //add the new Ingressiconpermesso 
em.persist(accession);           //add the Accessiconpermesso
em.merge(persistentInstance);    //update the Permessitemporanei

//commit the transaction
em.getTransaction().commit();

Чтобы ответить на другой вопрос, нет, как правило, вам не нужно аннотировать обе стороны отношений. Вы можете удалить аннотацию @OneToMany, если хотите, и она не должна ничего ломать (насколько это касается JPA, в любом случае ... у вас вполне может быть код приложения, который основан на том, что Collection присутствует и правильно заполнен, и удаление отображения JPA, конечно, нарушит любой такой код). Тем не менее, я не думаю, что вы получите что-то, удалив его, поэтому я бы рекомендовал оставить его в покое.

...