[RESOLVIDO] delete com hibernate many-to-many

13 respostas
V

eu tenho três tabelas no banco de dados: usuarios, permissoes e usuario_permissao. as tabelas representam um relacionamento @ManyToMany.
o problema é que eu quero excluir todos os registros da tabela usuario_permissao que fazem referência à um usuario qualquer para poder inserir as novas permissoes do usuario.
ou seja, sempre que eu vou inserir novas permissões para um usuário quero excluir as antigas antes.

tentei recuperar os elementos que quero excluir com a chamada do método usuario.getUsuarioPermissaoList() mas sempre dá erro no hibernate e se faço somente usuario.setUsuarioPermissaoList( novasPermissoesList ) ele só insere as novas permissoes e não apaga as antigas.

como faço para resolver este problema?

13 Respostas

P

Posta ai como vc ta chamando isso.

Quando vc pega a lista, que erro da? Lazy Exception?

V

aqui é o meu servlet que insere as permissoes

public class DefinirPermissaoUsuarioAction extends HttpServlet {
    private static final String SUCCESS = "Permissões definidas corretamente";
    private static final String FAILURE = "Erro ao definir as permissões do usuário";

    /** 
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost( HttpServletRequest request, HttpServletResponse response )
            throws ServletException, IOException {

        Session session = HibernateUtil.openSession();
        PermissaoDAO permissaoDAO = new PermissaoDAO( session );
        UsuarioDAO usuarioDAO = new UsuarioDAO( session );
        List<UsuarioPermissao> usuarioPermissaoList = new ArrayList<UsuarioPermissao>();
        PrintWriter writer = response.getWriter();

        response.setContentType( "text/html" );

        String[] idPermissoes = request.getParameterValues( "idPermissoes" );
        String responseText = null;

        try {
            Usuario usuario = createUsuario( usuarioDAO, request );

            for( String idPermissao : idPermissoes ) {
                Permissao permissao = createPermissao( idPermissao, permissaoDAO );
                UsuarioPermissao usuarioPermissao = createUsuarioPermissao( usuario, permissao );

                usuarioPermissaoList.add( usuarioPermissao );
            }

            usuario.setUsuarioPermissaoList( usuarioPermissaoList );
            usuarioDAO.insertOrUpdate( usuario );

            responseText = SUCCESS;
        } catch( Exception ex ) {
            responseText = FAILURE;
            Logger.getLogger( DefinirPermissaoUsuarioAction.class.getName() ).log( Level.SEVERE, ex.getMessage(), ex );
        } finally {
            writer.write( responseText );
            writer.close();
            
            session.close();
        }
    }

    private void clearPermissoes( UsuarioDAO usuarioDAO, HttpServletRequest request ) throws Exception {
        Usuario usuario = createUsuario( usuarioDAO, request );
        new UsuarioPermissaoDAO( HibernateUtil.openSession() ).delete( usuario.getUsuarioPermissaoList() );
    }

    private UsuarioPermissao createUsuarioPermissao( Usuario usuario, Permissao permissao ) {
        UsuarioPermissao usuarioPermissao = new UsuarioPermissao();

        usuarioPermissao.setUsuario( usuario );
        usuarioPermissao.setPermissao( permissao );

        return usuarioPermissao;
    }

    private Usuario createUsuario( UsuarioDAO usuarioDAO, HttpServletRequest request ) throws Exception {
        return usuarioDAO.find( request.getParameter( "idUsuario" ) );
    }

    private Permissao createPermissao( String idPermissao, PermissaoDAO permissaoDAO ) throws NumberFormatException, Exception {
        int id = Integer.parseInt( idPermissao );
        return permissaoDAO.find( id );
    }
}
V

o erro que dá quando eu tento excluir os registros antes de inserir os novos é esse

GRAVE: deleted object would be re-saved by cascade (remove deleted object from associations): [br.com.tecnikadigital.bean.UsuarioPermissao#1]
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [br.com.tecnikadigital.bean.UsuarioPermissao#1]
        at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:1014)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:165)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
        at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
        at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
        at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:218)
        at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
        at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
        at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
        at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:131)
        at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:122)
        at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
        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 br.com.tecnikadigital.dao.AbstractDAO.delete(AbstractDAO.java:32)
        at br.com.tecnikadigital.servlet.action.DefinirPermissaoUsuarioAction.doPost(DefinirPermissaoUsuarioAction.java:61)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at br.com.tecnikadigital.filter.AccessFilter.parseRequest(AccessFilter.java:160)
        at br.com.tecnikadigital.filter.AccessFilter.doFilter(AccessFilter.java:70)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:861)
        at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1584)
        at java.lang.Thread.run(Thread.java:619)
P

Tenta o seguinte.

Para excluir a permissao, vc não quer excluir ela, apenas quer tirar ela da relação com seu usuario.

Esvazie a lista de permissoes do seu usuario

Salve seu usuario

logicamente, utilize seus métodos equivalentes, não os que escrevi.

testa e me fala se funcionou.

Abs

V

fiz assim:

usuario.getUsuarioPermissaoList().clear();
usuarioDAO.update( usuario );

usuario.setUsuarioPermissaoList( usuarioPermissaoList );
usuarioDAO.update( usuario );

e não funcionou, como eu tinha mencionado antes, ele não remove os registros que já estavam cadastrados e adiciona os novos
=/

concluí depois de um teste aqui que:

usuario.getUsuarioPermissaoList().clear();
usuarioDAO.update( usuario );

não resulta em nenhuma ação no banco de dados =/

D

Cara eu uso a relaçao CASCADE DELETE ORPHAN, eu nao tenho o codigo aqui, mas segunda feira te posto ele, mas basicamente vc coloca uma relação na tabela “pai”, e outra relação na “filha”, q faz com ao deletar o “pai” a “filha” tbm eh deletada!
:smiley:

F

Para te ajudar, preciso ver o código das duas entidades envolvidas no relacionamento @ManyToMany.

Abraço

P

Cara

tenho esse tipo de relacionamento exaustivamente no projeto que estou trabalhando.

posta suas classes para dar uma olhada que te ajudamos.

abs

V

beleza, lá vai o meu código das três classes representadas no relacionamento

package br.com.hibernateapp.bean;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

/**
 * Classe Usuario
 *
 * @author Victor Guimarães Nunes <code>[email removido]</code>
 * @since
 * @version 
 */
@Entity
@Table( name = "usuario" )
@NamedQueries( {
    @NamedQuery( name = "Usuario.findAll", query = "SELECT u FROM Usuario u" ) } )
public class Usuario implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic( optional = false )
    @Column( name = "IDUSUARIO" )
    @GenericGenerator( name = "generator", strategy = "foreign", parameters = {
        @Parameter( name = "property", value = "pessoa" ) } )
    @GeneratedValue( generator = "generator" )
    private String idusuario;
    @Basic( optional = false )
    @Column( name = "USUARIO" )
    private String usuario;
    @Basic( optional = false )
    @Column( name = "SENHA" )
    private String senha;
    @JoinColumn( name = "IDUSUARIO", referencedColumnName = "IDPESSOA", insertable = false, updatable = false )
    @OneToOne( optional = false )
    private Pessoa pessoa;
    @OneToMany( cascade = CascadeType.ALL, mappedBy = "usuario" )
    private List<Aluno> alunoList;
    @JoinColumn( name = "ID_TIPO_USUARIO", referencedColumnName = "ID_TIPO_USUARIO" )
    @ManyToOne( optional = false )
    private TipoUsuario tipoUsuario;
    @OneToMany( fetch=FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "usuario" )
    private List<UsuarioPermissao> usuarioPermissaoList;

    // Construtor, setters e getters
}
package br.com.hibernateapp.bean;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Classe Permissao
 *
 * @author Victor Guimarães Nunes <code>[email removido]</code>
 * @since
 * @version 
 */
@Entity
@Table( name = "permissao" )
@NamedQueries( {
    @NamedQuery( name = "Permissao.findAll", query = "SELECT p FROM Permissao p" ) } )
public class Permissao implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Basic( optional = false )
    @Column( name = "IDPERMISSAO" )
    private Integer idpermissao;
    @Column( name = "DESCRICAO" )
    private String descricao;
    @Column( name = "URL" )
    private String URL;
    @OneToMany( cascade = CascadeType.ALL, mappedBy = "permissao" )
    private List<UsuarioPermissao> usuarioPermissaoList;

    // Construtor, setters e getters
}
package br.com.hibernateapp.bean;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

/**
 * Classe UsuarioPermissao
 *
 * @author Victor Guimarães Nunes <code>[email removido]</code>
 * @since
 * @version 
 */
@Entity
@Table( name = "usuario_permissao" )
@NamedQueries( {
    @NamedQuery( name = "UsuarioPermissao.findAll", query = "SELECT u FROM UsuarioPermissao u" ) } )
public class UsuarioPermissao implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Basic( optional = false )
    @Column( name = "IDUSUARIO_PERMISSAO" )
    private Integer idusuarioPermissao;
    @JoinColumn( name = "IDPERMISSAO", referencedColumnName = "IDPERMISSAO" )
    @ManyToOne( optional = false )
    private Permissao permissao;
    @JoinColumn( name = "IDUSUARIO", referencedColumnName = "IDUSUARIO" )
    @ManyToOne( optional = false )
    private Usuario usuario;

    // Construtor, setters e getters
}
V

realmente, já tentei de tudo e nada da certo… não consigo achar nada na web

P

Bom, você não precisa criar uma classe UsuarioPermissao o hibernate cria para você através de anotação, não está funcionando como o paulohrl disse porque você não mapeou com a anotação @ManyToMany
Olha como eu utilizo:

.. class Usuario {

@ManyToMany(fecht=FetchType.LAZY)
@JoinTable(name="USUARIO_PERMISSAO",
                 joinColumns={@JoinColumn(name="ID_USUARIO"},
                 inverseColumns={@JoinColumn(name="ID_PERMISSAO"}
private List<Permissao> permissaoList = new ArrayList<Permissao>();


}

.. class Permissao{

@ManyToMany(fecht=FetchType.LAZY, mappedBy="permissaoList ")
private List<Usuario> usuarioList = new ArrayList<Usuario>();

}
V
Priuli:
Bom, você não precisa criar uma classe UsuarioPermissao o hibernate cria para você através de anotação, não está funcionando como o paulohrl disse porque você não mapeou com a anotação @ManyToMany.. Olha como eu utilizo:
.. class Usuario {

@ManyToMany(fecht=FetchType.LAZY)
@JoinTable(name="USUARIO_PERMISSAO",
                 joinColumns={@JoinColumn(name="ID_USUARIO"},
                 inverseColumns={@JoinColumn(name="ID_PERMISSAO"}
private List<Permissao> permissaoList = new ArrayList<Permissao>();


}

.. class Permissao{

@ManyToMany(fecht=FetchType.LAZY, mappedBy="permissaoList ")
private List<Usuario> usuarioList = new ArrayList<Usuario>();

}
o problema é que eu não posso mecher no banco de dados, daí eu tentei fazer como você disse e o seguinte erro apareceu:
GRAVE: Unknown column 'permissaol0_.ID_USUARIO' in 'field list'
25/10/2010 15:14:44 br.com.tecnikadigital.servlet.action.DefinirPermissaoUsuarioAction doPost
GRAVE: could not initialize a collection: [br.com.tecnikadigital.bean.Usuario.permissaoList#1;1]
org.hibernate.exception.SQLGrammarException: could not initialize a collection: [br.com.tecnikadigital.bean.Usuario.permissaoList#1;1]
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.loader.Loader.loadCollection(Loader.java:2001)
        at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
        at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:565)
        at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
        at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1716)
        at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
        at org.hibernate.collection.PersistentBag.clear(PersistentBag.java:364)
        at br.com.tecnikadigital.servlet.action.DefinirPermissaoUsuarioAction.doPost(DefinirPermissaoUsuarioAction.java:64)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at br.com.tecnikadigital.filter.AccessFilter.parseRequest(AccessFilter.java:160)
        at br.com.tecnikadigital.filter.AccessFilter.doFilter(AccessFilter.java:70)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:861)
        at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1584)
        at java.lang.Thread.run(Thread.java:619)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'permissaol0_.ID_USUARIO' in 'field list'
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
        at com.mysql.jdbc.Util.getInstance(Util.java:384)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2113)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2275)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1787)
        at org.hibernate.loader.Loader.doQuery(Loader.java:674)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.loadCollection(Loader.java:1994)
        ... 25 more
=/
V

ops… foi mal o post anterior, foi só uma desanteção que esqueci de modificar o ID_USUARIO por IDUSUARIO como funciona aqui na minha app…
valew mesmo, agora tá funfando certinho!

=)

Criado 22 de outubro de 2010
Ultima resposta 25 de out. de 2010
Respostas 13
Participantes 5