2011-02-05 5 views
6

J'utilise une interface JPA pour Hibernate, et j'ai écrit du code simple pour charger une entité de la base de données, puis la supprimer (supprimer). Tous mes appels de fusion pour insérer et mettre à jour des entités fonctionnent parfaitement, mais lorsque j'essaie de supprimer une entité, Hibernate ne la supprime pas de la base de données et aucune exception n'est levée. J'ai inclus le code correspondant ci-dessous:JPA/Hibernate remove entity ne fonctionne pas

Méthode primaire:

/** 
* 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); 
} 

classe AbstractJpaDao (héritée par toutes les classes 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); 
    } 
} 

classe de domaine 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; 
    } 

} 

Des idées sur ce que le problème pourrait être ou comment le déboguer?

+0

votre code est source de confusion depuis votre '' AbstractJpaDao' et eventMemberDAO' ne sont pas réellement * * OAC s mais * wrapper EntityManager * s (ou si vous le sera * DaoMgr * s). ce serait bien si vous corrigiez cela dans votre exemple ci-dessus car cela complique inutilement la compréhension du problème. –

Répondre

3

Est-ce que cela devient confus parce que le EventInvite franchit les limites de transaction? Vous chargez l'entité dans une transaction et la supprimez dans une autre. Au lieu de cela, créez une nouvelle méthode @Transactional qui contient la logique métier complète pour accepter une invitation car il s'agit d'une opération logique unique. Cela permettra également de séparer la couche de présentation du modèle lorsque vous souhaitez activer l'acceptation des invitations par SMS ou e-mail.

+0

Vous êtes un génie. A travaillé parfaitement, merci David! – Templar

0

Salut Pour mise en veille prolongée, vous pouvez essayer de voir sql de exécutées en mettant

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

Ce que je pense est que lorsque vous supprimez, en quelque sorte la session ou de la transaction ne sont pas fermées si mise en veille prolongée ne videra pas et les résultats ne pas être vu dans la base de données.

+1

J'ai activé la journalisation des requêtes JDBC et Hibernate n'essaie même pas de supprimer l'enregistrement. En outre, l'appel eventMemberDAO.store immédiatement avant la suppression de l'appel de suppression, je ne pense pas que ce soit un problème transactionnel. – Templar

3

J'ai eu un problème similaire, j'avais une classe qui décrit une valeur qui fait partie d'une catégorie. Ainsi, la classe de valeur a une référence à la catégorie dont elle fait partie.

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

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

    @ManyToOne 
    private Category category; 
} 

je dû régler manuellement le champ de catégorie null avant que je puisse retirer l'objet de categoryValue, je ne sais pas vraiment pourquoi Hibernate fonctionne de cette façon.

+0

C'était le lien manquant dont j'avais besoin :-) –

1

J'ai eu le même problème. Mon entité est Card (voir ci-dessous). Et je ne pouvais pas définir null à un compte et un client, parce que j'ai contrôles non-null dans la base de données.

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

Et quand j'ai essayé de le supprimer, je n'ai même pas vu sql-request à propos de la suppression.

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

Je résolus par cette annotations

@ManyToOne(cascade=CascadeType.MERGE) 
@JoinColumn(name="idAcc") 
private Account account; 
@ManyToOne(cascade=CascadeType.MERGE) 
@JoinColumn(name="idCl") 
private Client client; 
Questions connexes