Encapsulando atributos com MAP

Especialistas,

Infelizmente não consegui usar Hibernate ou OJB no meu projeto. Preciso mandando objetos fora da sessão desses frameworks por RMI para clientes SWT. Como também são poucas classes, uns dias de programação na unha resolve o problema. Ai me deparei com classes para transportar os dados com muitos gets e sets para os atributos. Pensei em extrair um Map da tabela SQL que contem campo=valor do registro, e instanciar uma classe com a lógica de negócio a partir desse map, como no exemplo abaixo.

Pontos em questão:

  1. Isso é uma implementação suja ?
  2. É um problema de performance o cast de dados no momento do get ?
  3. Fica muito gorda a classe com o Map para ser serializada ?
  4. Existe mecanismo melhor ?

Vejam que a intenção é ser bem genérico para trabalhar com os gets e sets. Se eu criar um Map por uma consulta no banco, posso brincar com esse Map de forma bem simples. Agora imaginem que derrepente esse Map precise vir de um XML ou uma query LDAP? - praticamente não muda nada na estrutura dessa classe DadoSimples…

Um abraço

Davi

import java.util.*;
public abstract class DadoSimples implements java.io.Serializable {
	
	// Colocar todos os atributos dentro do MAP
	private Map<String,Object> meta = null;
	
	// Construtor para receber os dados de fora
	public DadoSimples(Map<String,Object> meta) {
		this.meta = meta;
	}
	
	// Cria uma instancia vazia
	public DadoSimples() {
		meta = new HashMap<String,Object>();
	}
	
	// Todos os setters genéricos usam esse set !
	public void set(String attributeName, Object value) {
		meta.put(attributeName, value);
	}
	
	// Todos os getters genéricos usam esse get !
	public Object get(String attributeName) {
		return meta.get(attributeName);
	}
	
	// Get específico
	
	public String getName() {
		return (String) meta.get("name");
	}
	
	// ...
}

O que deu errado com o Hibernate?

Quando eu joguei pra fora da sessão do Hibernate por RMI a List&lt&gt que tinha os registros mapeados de uma tabela, tinha um mapeamento 1-n que era um atributo dentro da classe que tava na list, assim quando tentei recuperar essa instancia deu erro, dizendo que não achou a sessão do hibernate. o código que eu usei para recuperar a lista foi:

public List<Service> getServices() {
		List<Service> services = new LinkedList<Service>();
		try {
			Transaction tx = session.beginTransaction();
			tx.begin();
			Query select = session.createQuery("from Services service");
			services = select.list();
			tx.commit();
			session.flush();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return services;
	}

Debugando esse a lista, o atributo da classe que deveria ser outra classe era uma instancia do $$EnhancerBy$$CGLIB e quando foi solicitada deu pau. Conversando com um amigo, ele sugeriu de usar um TO para transferir essa list para fora da sessão. To achando que assim complica mais que simplifica, que é a proposta do Hibernate. Paralelamento to tentando usar novamente o hibernate a fazer tudo na unha, mas ainda nao consegui que ele criasse os mapeamentos com instancias de instancias de classes mapeados sem nenhuma estrutura interna do hibernate.

Modelo da aplicação:

(Eclipse RCP/SWT) <------ RMI -----> Server (j2se) <---- SQL -----> DB

Olha o screenshot do DEBUG para a classe. Note que nao tem a instancia tem esse EnhancerBy…


Voce nao pode passar proxies da CGLib pra outra maquina usando RMI. Se vc quiser que os relacionamentos sejam retornados pro cliente, vc vai precisar desligar todo e qualquer lazy-loading.

Ou então usar o mecanismo de extended persistence context do hibernate, que é mais complexo que materializar as collections que você vai precisar, porém.

Louds o que seria “materializar as collections” ?

Outro problema que eu percebi. Se eu retirar o lazy, legal, não existe mais o $$EnhancerBy$$, mas ainda existem detalhes de como o hibernate trabalha com as collections e detalhes da sessão. Tem como remover isso tudo também ?

Veja na figura anexa…