2011-02-05 12 views
6

Używam interfejsu JPA do hibernacji, a ja napisałem prosty kod, aby załadować encję z bazy danych, a następnie usunąć (usunąć) ją. Wszystkie moje połączenia scalające do wstawiania i aktualizowania encji działają doskonale, ale gdy próbuję usunąć encję, Hibernate nie usuwa jej z bazy danych i nie jest zgłaszany wyjątek. Podaję odpowiedni kod poniżej:Usuwanie obiektu JPA/Hibernuj nie działa

Podstawowa metoda:

/** 
* Accept an invite that was sent to you. 
* 
* @param inviteId 
* @return XML model of the EventMember. 
*/ 
@RequestMapping(value="/invites/accept.rest") 
public ModelAndView acceptInvite(@RequestParam final long inviteId) { 
    final EventInvite invite = eventInviteDAO.find(EventInvite.class, eventInviteId); 

    EventMember eventMember = new EventMember(); 
    eventMember.setEvent(invite.getEvent()); 
    eventMember.setUser(invite.getUser()); 
    eventMember = eventMemberDAO.store(eventMember); 

    eventInviteDAO.remove(invite); 

    return getXMLModelAndView("eventMember", eventMember); 
} 

klasa AbstractJpaDao (dziedziczone przez wszystkie klasy DAO):

public abstract class AbstractJpaDao<T> implements JpaDao<T> { 
    abstract public EntityManager getEntityManager(); 

    public <T> T find(Class<T> entityClass, Object primaryKey) { 
     return getEntityManager().find(entityClass, primaryKey); 
    } 

    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED) 
    public T store(final T objectToPersist) { 
     T result = getEntityManager().merge(objectToPersist); 
     return result; 
    } 

    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED) 
    public void remove(final T objectToDelete) { 
     getEntityManager().remove(objectToDelete); 
    } 
} 

klasa domeny EventInvite:

@Entity 
@Table(name = "TEventInvite") 
public class EventInvite implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Column(name = "EventInviteID", nullable = false) 
    @Basic(fetch = FetchType.EAGER) 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private long eventInviteId; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumns({ @JoinColumn(name = "EventID", referencedColumnName = "EventID", nullable = false) }) 
    private Event event; 

    @Column(name = "Email") 
    @Basic(fetch = FetchType.EAGER) 
    private String email; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(name = "CreateDate", nullable = false) 
    @Basic(fetch = FetchType.EAGER) 
    private Calendar createDate; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumns({ @JoinColumn(name = "UserID", referencedColumnName = "UserID") }) 
    private User user; 

    public void setEventInviteId(long eventInviteId) { 
     this.eventInviteId = eventInviteId; 
    } 

    public long getEventInviteId() { 
     return this.eventInviteId; 
    } 

    public Event getEvent() { 
     return event; 
    } 

    public void setEvent(Event event) { 
     this.event = event; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getEmail() { 
     return this.email; 
    } 

    public void setCreateDate(Calendar createDate) { 
     this.createDate = createDate; 
    } 

    public Calendar getCreateDate() { 
     return this.createDate; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public User getUser() { 
     return user; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result 
       + ((createDate == null) ? 0 : createDate.hashCode()); 
     result = prime * result + ((email == null) ? 0 : email.hashCode()); 
     result = prime * result + ((event == null) ? 0 : event.hashCode()); 
     result = prime * result + ((user == null) ? 0 : user.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     EventInvite other = (EventInvite) obj; 
     if (createDate == null) { 
      if (other.createDate != null) 
       return false; 
     } else if (!createDate.equals(other.createDate)) 
      return false; 
     if (email == null) { 
      if (other.email != null) 
       return false; 
     } else if (!email.equals(other.email)) 
      return false; 
     if (event == null) { 
      if (other.event != null) 
       return false; 
     } else if (!event.equals(other.event)) 
      return false; 
     if (user == null) { 
      if (other.user != null) 
       return false; 
     } else if (!user.equals(other.user)) 
      return false; 
     return true; 
    } 

} 

Jakieś pomysły na temat problemu lub jak go usunąć?

+0

kod jest mylące, ponieważ swoim '' eventMemberDAO' AbstractJpaDao' i faktycznie nie DAO * * * s ale EntityManager wrapper * s (lub jeśli tak będzie * DaoMgr * s). byłoby miło, gdybyś poprawił to w powyższym przykładzie, ponieważ niepotrzebnie komplikuje zrozumienie problemu. –

Odpowiedz

3

Czy to się myli, ponieważ EventInvite przekracza granice transakcji? Załadujesz obiekt w jednej transakcji i usuniesz go w innej.

Zamiast tego utwórz nową metodę @Transactional, która zawiera kompletną logikę biznesową do zaakceptowania zaproszenia, ponieważ jest to pojedyncza operacja logiczna. Spowoduje to również oddzielenie warstwy prezentacji od modelu, gdy chcesz włączyć akceptowanie zaproszeń za pośrednictwem wiadomości SMS lub e-mail.

+0

Jesteś geniuszem. Działa doskonale, dzięki David! – Templar

0

Hi Dla hibernacji można spróbować zobaczyć zrealizowane sql poprzez ustawienie

<property name="hibernate.show.sql" value="true"></property> 

Co ja podejrzewam, że po usunięciu jakoś sesja lub transakcja nie jest zamknięty tak hibernacji nie będzie równo, a wyniki zostaną nie widać w bazie danych.

+1

Mam włączone rejestrowanie zapytań JDBC, a Hibernate nawet nie próbuje usunąć rekordu. Ponadto wywołanie eventMemberDAO.store bezpośrednio przed wywołaniem wywołania jest utrzymywane, więc nie sądzę, że jest to problem transakcyjny. – Templar

3

Miałem podobny problem, miałem klasę, która opisuje wartość, która jest częścią kategorii. Zatem klasa wartości ma odniesienie do kategorii, której jest częścią.

@Entity 
public class CategoryValue extends LouhinObject implements Serializable, Idable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne 
    private Category category; 
} 

musiałem ręcznie ustawić pola kategorii na null, zanim udało mi się usunąć obiekt CategoryValue, ja naprawdę nie wiem, dlaczego Hibernacja działa w ten sposób.

+0

To był brakujący link, którego potrzebowałem :-) –

1

Miałem ten sam problem. Moja istota to Karta (patrz poniżej). I nie mogłem ustawić wartości null na konto i na kliencie, ponieważ mam niezerowych kontroli w bazie danych.

public class Card implements Serializable { 
    @ManyToOne 
    @JoinColumn(name="idAcc") 
    private Account account; 
    @ManyToOne 
    @JoinColumn(name="idCl") 
    private Client client; 

I kiedy próbowałem go usunąć, nawet nie widziałem żądania sql o usunięcie.

em = getEntityManager(); 
    em.getTransaction().begin(); 
    mergedCard = em.merge(card); 
    em.remove(mergedCard); 
    em.getTransaction().commit(); 

Więc postanowiłem to poprzez adnotacje

@ManyToOne(cascade=CascadeType.MERGE) 
@JoinColumn(name="idAcc") 
private Account account; 
@ManyToOne(cascade=CascadeType.MERGE) 
@JoinColumn(name="idCl") 
private Client client; 
Powiązane problemy