Почему мой managerbean не удаляет организации, послав мою организацию?

По какому-то разуму, попробовав удалять организацию с

public void remove(Notification notification){
    try {
        em.merge(notification);
        em.remove(notification);
    } catch (Exception e) {
        System.out.println("No se pudo remover la notificación "+e.getMessage());
    }
}

он посылает мне эту ошибку

Entity must be managed to call remove: 4, try merging the detached and try the remove again.

но несмотря на то, что, в использует:

public void remove(Notification notification){
    try {


        em.merge(em.find(Notification.class, notification.getId()));
        em.remove(em.find(Notification.class, notification.getId()));
    } catch (Exception e) {
        System.out.println("No se pudo remover la notificación "+e.getMessage());
    }
}

Мне хотелось бы знать, почему происходит это, так как я понимаю, что

(em.find(Notification.class, notification.getId())

он был бы должен возвращать ту же организацию, которая послала его с

em.remove(notification);

Просто я не нахожу его почувствованным. Я надеюсь, что они помогают мне понимать. почему он происходит.

1
задан 06.01.2017, 22:00
0 ответов

Метод EntityManager#merge возврати инстанцию, ассоциируемую с контекстом, он не будет изменять инстанцию, которую ты посылаешь как параметр. Для того, чтобы твой код функционировал, это должный быть быть так:

Notification mergedNotification = em.merge(notificacion);
//luego de la línea anterior:
//notification sigue siendo el mismo objeto del parámetro sin modificaciones
//mergedNotification es una nueva instancia de la clase Notification
//que está asociada al contexto de JPA (nivel 1 de caché, para ser precisos)
//ahora lo puedes remover
em.remove(mergedNotification);

Преимущество этого метода состоит в том, что он полезный, когда ты хочешь сделать уничтожение объектов в водопаде. Но глаз, будь осторожен с результатом приложения в этом случае. Считай, что, когда ты используешь EntityManager#merge будь должен регистрировать объект в базе данных из-за INSERT или UPDATE и реализовывать другие добавочные операции (p.e. отражение), что затрагивает результат приложения, пальто, если объект - очень тяжелый p.e., если есть у поля blob, что обладает изображением или файлом. Если говорится о единственной организации главным образом без связей, или если ты хочешь реализовать массовую операцию (известные лучше Вашему термину на английском bulk operation), лучшее в условиях результата состояло бы в том, чтобы использовать API Criteria с кодом, как останься:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaDelete<Notification> query = cb.createCriteriaDelete(Notification.class);
Root<Notification> root = query.from(Notification.class);
query.where(cb.equal(root.get("id"), notification.getId()));

int result = entityManager.createQuery(query).executeUpdate();

Также ты мог бы добиваться этого с JPQL, но API у Criteria есть преимущество, от которого он может получать класс как параметр, что облегчает создавать более характерный метод, чтобы обобщать код наверху, например:

interface Entidad<T> {
    T getId();
    void setId(T id);
}

public class Notification implements Entidad<Integer> {
    /* definición de la clase */
    Integer id;
    //getter y setter..
}

class DaoGenerico {
    EntityManager em;
    public DaoGenerico(EntityManager em) {
        this.em = em;
    }
    public <E extends Entidad<?>> void borraMedianteApiCriteria(Class<E> claseEntidad, E entidad) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaDelete<E> query = cb.createCriteriaDelete(claseEntidad);
        Root<E> root = query.from(claseEntidad);
        query.where(cb.equal(root.get("id"), entidad.getId());
        em.createQuery(query).executeUpdate();
    }
}
1
ответ дан 03.12.2019, 17:51
  • 1
    Он не así если организация не в persistent context, использовав .merge организацию, она добавлена к persistent context и Ваше состояние перенесено в ту же организацию с тем же идентификатором, если он состоит в том, что он был загружен ранее, ничто из этого не сохраняются в основание, если ты не делаешь flush... –  06.01.2017, 22:53
  • 2
    Это находится в especificació n JPA, aquí есть статья, которая обобщает spitballer.blogspot.com/2010/04/… –  06.01.2017, 23:05
  • 3
    @Carlos сейчас, когда я читаю лучше твой комментарий, я не понимаю часть, которую ты говоришь " он не así ". Наоборот, которого ты выдвигаешь, что я говорю, что организация Notification notification из pará метр не está присоединенная с контекстом, поэтому использовав merge, он ассоциируется с контекстом и возвращает эту присоединенную организацию, будьте из-за insert или update. Та pará метр поддерживает Ваше такое состояние каковым. Это flush он другой петь. –  06.01.2017, 23:28
  • 4
    Я имею в виду часть, о которой ты упоминаешь, что он приносит объект основания в этом трэде stackoverflow, ты на английском можешь видеть больше деталей stackoverflow.com/questions/4509086/… –  06.01.2017, 23:31
  • 5
    @CarlosLucero ох ok, это был часть исправления этих слов. Он не значит, что ответ был плохой per. Исправленный. –  06.01.2017, 23:34

В hibernate организации могут быть в любом из этих состояний.

  • New (transient): an entity is new if it существуешь just been instantiated using the new operator, and it is not associated with в persistence context. It ты существуешь не persistent representation in the он был датирован and не identifier оцените ты существуешь been assigned.

  • Managed (persistent): в managed entity instance is an instance with в persistent identity that is currently associated with в persistence context.

  • Detached: the entity instance is an instance with в persistent identity that is не longer associated with в persistence context, usually because the persistence context was closed or the instance was evicted from the context.

  • Переместите: в removed entity instance is an instance with в persistent identity, associated with в persistence context, but scheduled for removal from the он был датирован.

Одинокий Hibernate может работать с организациями Managed, чтобы мочь манипулировать Вашим состоянием и переносить эти действия основание посредством SQL, противоположный случай не позволит тебе, следовательно организация Detached, которая вне persistent context, не могут сохраняться или изменять в основании, для этого ты должен возвращать твою организацию обратно в persisten context и обращать твою организацию Detached в Managed.

В твоем случае организация 'освободила', что он прибывает как параметр, о методе в бывшая разъединенная persistence context следовательно не управляли (Detached) из-за, это разум, из-за которого он не позволяет тебе удалять ее.

Сделав

em.find(Notification.class, notification.getId())

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

сделав

em.merge(libro); // libro pasa al persistence context y se convierte en un managed entity
em.remove(libro);

ты добавляешь, что разъединенная организация (Detached) 'освободила' persistence context посредством метода .merge () следовательно сейчас переходят к тому, чтобы управлять об этой разъединенной организации (Detached) (Managed), по этой причине сейчас ты можешь удалять.

Сейчас в твоем следующем примере, этом фрагменте кода.

em.merge(em.find(Notification.class, notification.getId()));
em.remove(em.find(Notification.class, notification.getId()));

ты можешь упрощать это как

Notificacion notificacion = em.find(Notification.class, notification.getId());
em.remove(notificacion);

Однако это в SQL переводится в следующее.

SELECT * FROM notificacion WHERE id = :id
DELETE FROM notificacion WHERE id = :id

Первый select необходим в hibernate, так как ты так получаешь управляемую организацию (Managed), чтобы мочь удалять ее потом с em.remove, но если ты только нуждаешься в идентификации, чтобы мочь удалять организацию в SQL тогда технически первый select, - расточительность.

Другой способ удалять разъединенную организацию - такой.

Libro entity = getEntityManager().getReference(Libro.class, libro.getId());
getEntityManager().remove(entity);

В этом случае getReference верьте в организацию proxy и он не загружает состояние (данные) о книге базы данных. (только ты можешь звонить в методы set этого объекта proxy).

Это намного лучше, так как, не загрузив данные об основании, это только делает delete и не первый select.

DELETE FROM libro WHERE id = :id
0
ответ дан 03.12.2019, 17:51