2014-01-08 4 views
2

У меня есть два объекта: событие и пользователь. Оба имеют ссылки друг на друга:Hibernate - удалить запрос из @ManyToMany

@Entity 
@Table(name = "Event") 
public class Event implements Serializable { 

    //some fields 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "Event_User", 
     joinColumns = @JoinColumn(name = "event_id", nullable = false, updatable = false), 
     inverseJoinColumns = @JoinColumn(name = "user_id", nullable = false, updatable = false)) 
    List<User> attendingUsers = new ArrayList<User>(); 

    //Getters and Setters 
} 

@Entity 
@Table(name = "User") 
public class User implements Serializable { 
    //Attributes 

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "attendingUsers") 
    private List<Event> attendingEvents = new ArrayList<Event>(); 

    //Getters and Setters 
} 

Хорошо, теперь у меня есть ситуации, когда я хочу, чтобы пользователи смогли Unattend события. До сих пор я пробовал несколько вещей, но похоже, что только запрос будет работать. Причина, по которой я хочу использовать запрос, заключается в следующем: я не могу использовать Hibernate.initialize(event.getAttendingUsers()), и поэтому event.getAttendingUsers().clean() этого не сделает.

Мой запрос выглядит это так далеко:

@Transactional(propagation= Propagation.REQUIRED, readOnly=false) 
@Service("eventService") 
public class EventService implements IEventService { 

     public void unattend(Event e, User u){ 
     Query query = sessionFactory.getCurrentSession().createQuery(
       "SELECT u FROM User AS u LEFT JOIN FETCH u.attendingEvents AS ae WHERE ae.id = :id"); 
     query.setParameter("id", e.getId()); 
     List<User> attendingUsers = (List<User>)query.list(); 

     if(attendingUsers.contains(u)){ 
      Query delete = sessionFactory.getCurrentSession().createQuery(
        "DELETE FROM u.attendingEvents AS ae WHERE ae.id = :event_id" 
        ); 
      delete.setParameter("event_id", e.getId()); 
      delete.executeUpdate(); 

      attendingUsers.remove(u); 
      e.setAttendingUsers(attendingUsers); 
      update(e); 
     } 
} 

Однако, это приводит к org.hibernate.hql.internal.ast.QuerySyntaxException: u.attendingEvents is not mapped [DELETE FROM u.attendingEvents AS ae WHERE ae.id = :event_id] Exception. Однако я не знаю, как сопоставить его, не удаляя событие (я хочу только удалить записи из таблицы join: event_user.Если я попытаюсь удалить из event_user напрямую, я также получаю то же исключение, что event_user is not mapped.

Любые идеи, как я мог бы решить эту проблему

EDIT:? Когда я пытаюсь использовать «простой», как я в конечном итоге, как это:

08.01.2014 17:03:02 org.apache.catalina.core.StandardWrapperValve invoke SCHWERWIEGEND: Servlet.service() for servlet [appServlet] in context with path [/tripitude] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ac.tuwien.ase08.tripitude.entity.Event.attendingUsers, could not initialize proxy - no Session] with root cause org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ac.tuwien.ase08.tripitude.entity.Event.attendingUsers, could not initialize proxy - no Session

Мой код:

@Transactional 
public void unattend(Event e, User u){ 
     try{ 
      Hibernate.initialize(e.getAttendingUsers()); 
     } catch(Exception ex){} 

     e.getAttendingUsers().remove(u); 

ответ

2

Запросов не требуется. Все, что вам нужно сделать, это удалить пользователя из списка использования события, которое вы хотите отключить. Для того, чтобы ваш график объекта когерентным, вы должны также удалить событие из событий пользователя, но Hibernate не будет заботиться о нем, потому что это обратная сторона ассоциации:

public void unattend(Event e, User u){ 
    // mandatory: 
    e.getUsers().remove(u); 
    // optional: 
    u.getEvents().remove(e); 
} 

выше предполагает u и e конечно, прикрепленные сущности. Если это не так, то в транзакции начните с получения их по идентификатору из базы данных и вызовите вышеуказанный метод с возвращенными объектами.

+0

Спасибо, я надеялся, что это так просто, однако это не сработает для меня. Если я только пытаюсь получить доступ к посетителям, посещающим с помощью 'e.getAttendingUsers()', я получаю исключение NullPointerException. Но я знаю, что мне нужно сначала их инициализировать, см. Мое редактирование для того, что произойдет, пожалуйста:/ – Cr0w3

+0

Как я уже сказал в своем ответе: не работайте с объектами, исходящими от я не знаю, где. Получите событие по идентификатору из базы данных с помощью session.find(), получите идентификатор пользователя по базе данных с помощью session.find(), а затем выполните работу с этими двумя прикрепленными объектами. Все это внутри транзакционной службы. –

+0

Спасибо, ты мне очень помог :) Мне пришлось сначала найти как событие, так и пользователя по id, а затем 'Hibernate.initialize (e.getAttendingUsers)' И 'Hibernate.initialize (u.getAttendingEvents)'. После этого я смог удалить :) – Cr0w3

Смежные вопросы