Hibernate - Erro ao remover dados

Olá todos.

Bom, estou tendo um problema aqui com um pequeno programa de Agenda Telefônica que estou fazendo, que só possui duas entidades: Contato e TelefoneContato. No banco de dados, são representadas pelas tabelas Contact e Contact_phone, existindo também a tabela associativa Contact_has_Contact_phone.

Ao inserir e atualizar os contatos, tudo está ocorrendo normalmente, porém ao tentar excluir qualquer contato, ele às vezes realmente o remove, mas às vezes também ocorre essa exceção (com a exclusão ocorrendo ou não):

04/06/2010 19:16:32 org.hibernate.util.JDBCExceptionReporter logExceptions WARNING: SQL Error: 0, SQLState: null 04/06/2010 19:16:32 org.hibernate.util.JDBCExceptionReporter logExceptions SEVERE: Entrada em lote 0 delete from public.Contact_Phone where Cd_contact_phone=1250 foi abortada. Chame getNextException para ver a causa. 04/06/2010 19:16:32 org.hibernate.util.JDBCExceptionReporter logExceptions WARNING: SQL Error: 0, SQLState: 23503 04/06/2010 19:16:32 org.hibernate.util.JDBCExceptionReporter logExceptions SEVERE: ERRO: atualização ou exclusão em tabela "contact_phone" viola restrição de chave estrangeira "contact_has_contact_phone_contact_phone_cd_contact_phone_fkey" em "contact_has_contact_phone" Detalhe: Chave (cd_contact_phone)=(1250) ainda é referenciada pela tabela "contact_has_contact_phone". 04/06/2010 19:16:32 org.hibernate.event.def.AbstractFlushingEventListener performExecutions SEVERE: Could not synchronize database state with session org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87) at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222) at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2479) at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2697) at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:74) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:146) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at com.gmail.thcolbert.agendatelefonica.database.Repository.remove(Repository.java:132) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.removeContact(MainJFrame.java:425) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.deleteSelectedContactMenuItemActionPerformed(MainJFrame.java:238) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.access$300(MainJFrame.java:24) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame$4.actionPerformed(MainJFrame.java:131) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) at javax.swing.AbstractButton.doClick(AbstractButton.java:357) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1225) at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:1266) at java.awt.Component.processMouseEvent(Component.java:6263) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at java.awt.Component.processEvent(Component.java:6028) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) at java.awt.Container.dispatchEventImpl(Container.java:2085) at java.awt.Window.dispatchEventImpl(Window.java:2475) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Caused by: java.sql.BatchUpdateException: Entrada em lote 0 delete from public.Contact_Phone where Cd_contact_phone=1250 foi abortada. Chame getNextException para ver a causa. at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2537) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1328) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:351) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2674) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246) ... 46 more com.gmail.thcolbert.agendatelefonica.database.RepositoryException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at com.gmail.thcolbert.agendatelefonica.database.Repository.remove(Repository.java:137) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.removeContact(MainJFrame.java:425) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.deleteSelectedContactMenuItemActionPerformed(MainJFrame.java:238) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame.access$300(MainJFrame.java:24) at com.gmail.thcolbert.agendatelefonica.gui.MainJFrame$4.actionPerformed(MainJFrame.java:131) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) at javax.swing.AbstractButton.doClick(AbstractButton.java:357) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1225) at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:1266) at java.awt.Component.processMouseEvent(Component.java:6263) ...

Acredito que seja algum problema no mapeamento da relação entre as classes, seria isso?

Contact.java

@Entity
@Table(name="Contact", schema="public")
@SequenceGenerator(name="contact_cd_contact_seq",
    sequenceName="contact_cd_contact_seq")
public class Contact implements Cloneable, Serializable
{
    ...

    /** Todos os números de telefone do contato. */
    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    @JoinTable(name="Contact_has_Contact_phone", schema="public",
        joinColumns={@JoinColumn(name="Contact_Cd_Contact")},
        inverseJoinColumns={@JoinColumn(name="Contact_phone_Cd_Contact_phone")})
    private List<ContactPhone> contactPhones;
}

ContactPhone.java

[code]
@Entity
@Table(name=“Contact_Phone”, schema=“public”)
@SequenceGenerator(name=“contact_phone_cd_contact_phone_seq”,
sequenceName=“contact_phone_cd_contact_phone_seq”)
public class ContactPhone implements Cloneable, Serializable
{

/** Os contatos que possuem este número de telefone. */
@ManyToMany(fetch=FetchType.LAZY, 
    cascade={CascadeType.MERGE, CascadeType.PERSIST},
    mappedBy="contactPhones")
private Collection<Contact> contacts;

}[/code]

Obrigado desde já. :slight_smile:

Ola
Você precisa deletar da tabela de relacionamento antes de deletar das relacionadas.

Abraços

Isso eu sei, se estivesse fazendo em SQL eu faria assim, mas o problema está sendo com o Hibernate…

Tenta isso? http://www.guj.com.br/posts/list/67454.java

Se ainda assim não for issso que deseja usa HQL ou SQL mesmo :wink:

Decidi mudar o Many-to-Many para One-to-Many/Many-to-One e resolvi o problema. :stuck_out_tongue:

Mas o mistério do Many-to-Many ainda continua.