Padrão Interceptor (hibernate)?

Estou com um problema no sistema.

O hibernate trabalha com dois bancos de dados diferentes, um local e outro servidor. Ambos bancos apresentam a mesma estrutura de tabelas, porém são bancos com tecnologias diferentes.

Eu tenho uma entidade que se relaciona com outra entidade em uma relação 1-N

Entidade A pode ter N entidades B.

ETA1 - ETB1
ETA1 - ETB2
ETA1 - ETB3

ETA1 contém 3 ETBs.

O problema que leio a entidade A de uma EntityManager que está associada ao banco 1, e desejo copiar o valor dessa entidade (inclusive todo seu relacionamento) para o banco 2 (que está associado com outro EntityManager)

Quando gravo os dados de uma base para outra, o relacionamento no banco 2 é perdido, simplesmente ele copia todos os dados e todo o seu relacionamento, porém a coluna na entidade B que guarda o valor da chave primária da entidade relacionada em A não é guardado.

Então eu gostaria de saber qual a melhor maneira para copiar, transferir objetos entre EntityManagers diferentes, sessões diferentes, seria usando Interceptores em Hibernate?

Agradeço a todos.

Parece que o Hibernate Shards tem o objetivo de realizar esse tipo de coisa, ou seja, trabalhar com vários bancos ao mesmo tempo.

Dê uma olhada:
http://www.hibernate.org/414.html

Até mais!

Grinvon,

Quando vc realiza um load(), ele é lazy-loading, será carregado a partir do momento que vc utiliza o objeto, entao se vc carrega um objeto e passa para outro banco e em momento algum vc o carregou, terá probelmas, tente carregar o objeto com o metodo get();

Obrigado David, darei uma olhada, se eu conseguir fazer algum exemplo postarei aqui então.

Grivon, vc está usando “Open Session in view” ?

Grivon, só mais uma coisa, para passar um objeto de um contexto peristente para outro, vc precisa carregar esse objeto… ok

[quote=jonimca]Grinvon,

Quando vc realiza um load(), ele é lazy-loading, será carregado a partir do momento que vc utiliza o objeto, entao se vc carrega um objeto e passa para outro banco e em momento algum vc o carregou, terá probelmas, tente carregar o objeto com o metodo get();[/quote]

Eu entendi, mas mesmo assim eu continuo tendo problemas.

Eu tinha buscado o objeto da lista que carreguei de um gerenciador de entidades.

Depois eu simplesmente criei um objeto e o associe ao objeto trazido da outra EM.

Porém depois eu preenchi na mão criando um objeto e pegando todos os atributos de um e passando para o outro, e quando fui persistir na otura base que seria a base da exportação o objeto persistiu usando merge, porém a coluna de relaciona não foi preenchida e não sei pq.

Grivon,

Vc carregou o objeto com o get() ?

passa pra o outro contexo e verifique o estado dele, com certeza será transient;

vc está executando o merge() tudo certinho com o comit() e tal ?

Tô não, vi atér um exemplo desse no site do hiberante.

O meu contexto é dois bancos DIFERENTES (SQL Server o outro Dervy)

Mas com mesmo DDL (mesma tabelas, etc.)

Um deverá se comunicar com outro e vice-versa.

E haverá controle de versão de registro.

Para isso usei duas EntityManager diferentes e duas persistence-unit, uma para cada banco.

Mas há esse problema como falei.

[quote=jonimca]Grivon,

Vc carregou o objeto com o get() ?

passa pra o outro contexo e verifique o estado dele, com certeza será transient;

vc está executando o merge() tudo certinho com o comit() e tal ?[/quote]

As duas entidades de teste que estou usando são:

Auditoria e Procedimento.

Auditoria pode ter N procedimentos. Veja a parte do código que joga elas do banco A para o banco B.

    public void download(Class pEntity) throws Exception {
        Query lQuery = emRemote.createQuery("SELECT m FROM " + pEntity.getName() + " m");
        List<Auditoria> lista = lQuery.getResultList();
        
        if (lista != null && lista.size() > 0) {
            
            for (Auditoria lA : lista) {
                
                //popula uma nova auditoria com seus procedimentos
                Auditoria lModel = new Auditoria();
                
                lModel.setDescricao(lA.getDescricao());
                lModel.setId(lA.getId());
                lModel.setVersaoOnline(lA.getVersaoOnline());
                lModel.setVersaoOffline(lA.getVersaoOffline());
                lModel.setProcedimentos(new ArrayList<Procedimento>());
                lModel.setSituacao(0);
                
                for (Procedimento p : lA.getProcedimentos()) {
                    Procedimento lProc = new Procedimento();
                    
                    lProc.setId(p.getId());
                    lProc.setDescricao(p.getDescricao());
                    lProc.setVersaoOffline(p.getVersaoOffline());
                    lProc.setVersaoOnline(p.getVersaoOnline());
                    lProc.setSituacao(0);
                    
                    lModel.getProcedimentos().add(lProc);
                }
                
                //lModel = lA;
                
                emLocal.merge(lModel);
            }
            
            emLocal.getTransaction().commit();
            
            //baixar registro de Identificador incrementado + 1
            Identificador lIden = emRemote.find(Identificador.class, new Long(1l));
            lIden.setEstacao(incrementarEstacao(lIden.getEstacao()));
            
            //verifica se já existe no banco local, caso não exista, será comitada tanto
            //em local quanto em remoto.
            Identificador localIden = emLocal.find(Identificador.class, new Long(1l));
            
            if (localIden == null) {
                persist(lIden, 0);
                persist(lIden, 1);
            }
        }
    }

Código do persist

    /**
     * 0 - local
     * 1 - remoto
     * @param pModo
     * @param pModel
     */
    public void persist(GenericModel pModel, int pModo) {
        if (pModo == 0) {
            getEntityManager(0);
            emLocal.merge(pModel);
            emLocal.getTransaction().commit();
        } else {
            getEntityManager(1);
            emRemote.merge(pModel);
            emRemote.getTransaction().commit();
        }
    }

Grivon, só para te adiantar, quando vc usa este esquema de ejb e hibernate com 2 contexto persistentes deve evitar o “Open Session in view”, por causa disso que está aconteçendo com vc

Acho que o problema que este objeto que vc está inserido, não pertence ao contexo, entende !!

vc não consegue carregar um objeto no ContextoPesistenteA usando o get() e

no ContextoPesistenteB criar outro objeto que esteja setado tbm no seu arquivo de configuração, ou melhor que esteja @Entity

e settar este objetos com os parametros do objeto passado no ContextoPersistenteA ?

dá um sysout, vê se os atributos foram carregados no contexoB

Opa jonimca,

Ele ta setando realmente todos os atributos que declaro ali, isso ele consegue gravar na outra base sem problema nenhum.

O problema que há um relacionamento de 1-N como declarado abaixo:

Em Auditoria.java

    //coleção de procedimentos
    @OneToMany(mappedBy="auditoria", cascade=CascadeType.ALL)
    @JoinColumn(name="PRC_ADT_ID")
    private List<Procedimento> procedimentos;

Em Procedimento.java

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="PRC_ADT_ID")
    private Auditoria auditoria;

Como pode-se perceber, o hibernate cria a coluna PRC_ADT_ID na tabela de Procedimento, essa coluna irá armazenar o ID da Auditoria.

Esse é o dado que não está sendo levado, e como simplesmente eu não posso setá-lo na mão então quando passo a Auditoria com os procedimentos relacionados do banco A para o banco B os valores para a coluna PRC_ADT_ID ficam todos nulos.

Crivon,

Vc está conseguindo carregar e enviar o objeto, mas tenta criar um objeto para o seu relacionamento tbm, e passar estes 2 objetos carregados atravez do metodo get();

faz esse teste por ai…

Se vc não tivesse usando anotações de Cascating deveria executar um save(), no objeto e outro save() em seus relacionamentos, acho que pode ser isso, carrege os dois, de um new para o objeto carrageado do relacionamento…

Com certeza o relacionamento está gerenciado no contextoA e o contextoB não consegue captura-los, tenta na mão mesmo, carregue o relacionamento e tranfira para outro objeto, e repa-se para o contexto B

Mas como posso carregar na mão se a coluna do relacionamento não tenho acesso, ela é implícita dentor da lógica do hibernate?