Alternativas para não usar Hibernate

Tentei começar a usar o Hibernate aqui. Não consegui. Muito XML, muita configuração. Muita complicação.

Eu sei: é poderoso, é legal, é o padrão, resolve um milhão de problemas mas vou tentar nadar contra a correnteza mais uma vez.

Pensando nas palavras do mestre Maurício:

Quando penso em persistencia, penso em CRUD (Create/Update/Delete) para meus beans. Tenho um objeto User e quero salvar ele no banco de dados sem chateações. Qualquer outra operação diferente de um CRUD, que involva join e/ou um where mais complexo será feita com JDBC puro. Acho que para essas situações, não é um crime usar JDBC e é até uma vantagem dos DAOs, já que podemos ter um DAO para qualquer query.

Então para os CRUDS, terei algo assim:


public class DBInviteImpl extends DBPersistent implements Invite {
	
        private IntField id = new AutoIncrementField(this, "id", true); // true = PK
	private StringField email = new StringField(this, "email");
	private DateTimeField senddate = new DateTimeField(this, "senddate");
	
	public static Invite getInstance() {
		return new DBInviteImpl();
	}
	
	protected DBInviteImpl() { }
	
        // isso aqui pode virar injection...
	public ConnectionHandler getConnectionHandler() { 
		return DefaultConnectionHandler.getInstance();
	}
	
	public String getTableName() { return "invites"; }
	
	public void setId(int id) { this.id.setValue(id); }
	public int getId() { return id.getValue(); }
	
	public void setEmail(String email) { this.email.setValue(email); }
	public String getEmail() { return email.getValue(); }
    
	public void	setSendDate(Date senddate) { this.senddate.setValue(senddate); }
	public Date	getSendDate() { return senddate.getValue(); }
    
}

Note que as únicas funções abstratas de DBPersisten é getConnectionHandler e getTablename().

E para usar o bean:

Invite inv = DBInviteImpl.getInstance();

// carrega por id
inv.setId(10);
if (inv.load()) {
    inv.setEmail("aaa@bbb.com");
    inv.update();
}

// insere um novo no banco...
inv.insert();
System.out.println("NOVO ID: " + inv.getId());

// deleta
inv.delete();

// carrega por username
Invite inv = DBInviteImpl.getInstance();
inv.setUsername("aaaa");
if (inv.load()) {
    System.out.println("O ID é: " + inv.getId());
}

// e qualquer outra coisa com update, insert, delete.

O que falta aí:

-> Transação (isso é mole)
-> Cache (isso não é tão mole mais dá para fazer)

Quais os problemas pratícos que eu terei se usar essa solução ?

  • Não terei que fazer a persistencia na mão, pois isso tudo já está feito pela classe DBPersistent, que gera as queries, etc e tal. (Note que a DBPersistent é uma classe genérica para persistir qualquer POJO)

  • Não terei que fazer tunning da persistencia. (Só terei que tunar o cache, claro!)

  • Isso seria bem produtivo para CRUD, certo?

E tudo que não for CRUD eu faria com JDBC mesmo.

Dessa maneira bye bye XML e configurações do Hibernate!

Já embarquei nessa algumas vezes, e não tive muito do que reclamar.

E aí? Embarco de novo ou tento mais uma vez mexer com o Hibernate?

sergio, performance não quer dizer necessariamente usar JDBC.

E quer uma dica? Aprenda a usar o Hibernate, depois disso crie sua solução “mágica”.

Claro. A questão da performance está fora de discussão. A discussão é porque não usar isso.

Isso é exatamente o que eu estou querendo evitar.

E uma solução mágica com Hibernate seria basicamente gerar todos os XMLs por mágica. Meio sacal isso…

Sinceramente, se preocupar somente com o básico e ignorar o dificil é pedir pra se dar mal mas pra frente.

TU nao é obrigado a usar XML. Pode usar anotacoes, que ai nao precisa de nenhum XML, ai se tu nao curte anotacoes pode usar o XDoclet e usar as tag do Ant que ele gera tudo, nao ter que ficar mexendo nos XML se esse é o problema.

Abra a mente Sergio, nao seja tao turrao contra o coitadinho dos XML e as configuracoes. :stuck_out_tongue:

É mas pode nao ser tao simples assim.

[quote=saoj]-> Transação (isso é mole)
-> Cache (isso não é tão mole mais dá para fazer)[/quote]

Concordo com os dois itens, mas ja existe tudo pronto é so usar. Claro se tu for inventar algo revolucionador va em frente.

Como eu disse ali em cima, nao é tao simples assim. Esse modelo é bonito e perfeito para CRUD simples, mas na prática nunca temos isso.
Operacoes de Update, Insert e Delete em cascata. Ficar controlando isso pode ser muito trabalhoso.

Depende denovo. Se tu precisar de muitos comandos poderá precisar usar bath uddate.

Para CRUD simples eu acredito que sim, mas para CRUD conplexo isso comeca a pegar pelos motivos falados acima (CRUD’s em cascata).

[quote=saoj]
E tudo que não for CRUD eu faria com JDBC mesmo.[/quote]

Denovo pode ter problema, ja penso em consulta metre-detalhe com N detalhes? O Hibernate usa Lazy pra resolver o acesso ao banco. Tu precisaria fazer algo semelhante.
Claro daria pra usar o ListHandler, mas tera que desenvolver um pra cada entidade.

Eu se fosse tu faria igual eu no inicio. Quando migrei pro Java vim do PL/SQL entao nao levava fé que o esquema funcionava. Mas como todos falavam bem resolvi testar. No inicio fiquei perdidao, mas nao sou de desistir continuei testar, tentando usar até que comecei a pegar o jeito. Posso te dizer com 99% de certeza tem muita coisa que pensamos ser simples, mas que esquecemos detalhes e essas coisas o Hibernate ja resolve.

Uma das unicas coisas que eu ainda acho que ele peca é o HQL, na parte das funcoes de agregacao.

Mas é aquele negocio, se tem uma idéia boa va em frente, mas se for pra reiventar a roda e ainda fazer ela redonda igual as existentes, nao perde tempo.

]['s

[quote=saoj]E uma solução mágica com Hibernate seria basicamente gerar todos os XMLs por mágica. Meio sacal isso…
[/quote]

Ai que ta, ta na hora de voltar la nas doc dele e ver que XML nao sao obrigatorios, mas sim uma opcao pra facilitar. Tem como eliminar eles ou usar uma ferramenta que esconda isso de ti. So nao vejo uma real vantagem.

]['s

Com um pouco de boa vontade você poderia programáticamente conectar no banco e configurar o hibernate segundo as propriedades dos teus beans.

Não adianta Sérgio, por mais que nós odiemos, os XMLs vieram para ficar…

[quote=fabgp2001][quote=saoj]E uma solução mágica com Hibernate seria basicamente gerar todos os XMLs por mágica. Meio sacal isso…
[/quote]

Ai que ta, ta na hora de voltar la nas doc dele e ver que XML nao sao obrigatorios, mas sim uma opcao pra facilitar. Tem como eliminar eles ou usar uma ferramenta que esconda isso de ti. So nao vejo uma real vantagem.

]['s[/quote]

se JDK 5.0 não for um problema, com duas anotações por classe usando hibernate3 ta tudo prontinho :smiley:
uma anotação pra dizer que a classe é persistente, e outra pra dizer qual é o campo da PK :smiley:
prontinho, não precisa de uma linha de XML, ele gera o banco pra ti e salva todos os teus objetos :smiley:

Vou tentar usar o Hibernate com annotations.

É que eu já tenho tudo isso que eu falei pronto.

Falta meter um cache.

As questões da lista eu resolvi com um load(rset). Algo assim:


select * from profiles where status = 1;

while(rset.next()) {
   Profile prof = DBProfileImpl.getInstance();
   prof.load(rset);
   list.add(prof);
}

Deixe-me dar uma sugestão, e me corrijam se eu estiver errado!

Como você viu Sérgio, é possível usar annotations e xdoclet para evitar o uso de arquivos xml. Bom, até aqui tudo bém, mas se não me engano, é possível configurar o mapeamento relacional na unha, sem os benditos arquivos xml.

Os *.hbm.xml são apenas uma maneira de evitar que o programador saia fazendo isso na unha, pois acredito que configurar na unha deve ser uma merda.

Se o que eu disse até aqui for real (pelo menos até onde sei, é mais ou menos isso), você poderia pensar em uma tool que facilite a criação destes *.hbm.xml via código java!

Assim vc facilita para aqueles que não curtem o bendito xml, e aproveite toda a força do Hibernate!

Abraços!
Thiago

E viva o HibernateSyncronizer!!!

Opa Sérgio, eu montei um mini-esquema de persistência com Daos pra um trabalho em PHP aqui da faculdade.

No início, era tudo uma maravilha, insert, select, update, delete, e até uns relacionamentos 1:1 ou N:1, o problema aconceceu quando eu encontrei o meu primeiro relacionamento 1:N. Em Java, eu simplesmente tinha o “cascade” do Hibernate, que fazia toda a “mágica”, só que implementar isso de uma forma genérica me deu tanto trabalho, que eu simplesmente não fiz, cada “cascade” tinha o seu próprio “persister”, porque eu não tinha arquivos de configuração pra dar as informações de chaves e tabelas como o Hibernate tem. Deixo pra você imaginar como deve ser simples fazer um relacionamento N:N.

Eu não consigo imaginar um meio de se fazer isso sem correr pra arquivos de configuração, ou então uma nomenclatura muito estrita. Tipo, se Produto tem Item, item tem que ter uma chave “produto_id” ou alguma coisa do gênero e amarrar as coisas assim realmente é muito ruim.

Mas se você tá conseguindo fazer uma coisa transparente e que dê conta dos relacionamentos, vá em frente, senão, reveja o que você tá fazendo pra ver se realmente vale a pena o trabalho.

Agora eu sou uma alma suspeita pra falar, porque eu nunca fiz muita coisa de JDBC na vida, desde que eu comecei a estudar Java (um pouco depois do meio do ano passado), vi JDBC pra não dizer que eu não sabia, mas quando eu fiz a minha primeira aplicação de verdade eu já estava usando o Hibernate. E depois de ver o artigo do Doederlein sobre Daos com JDBC e ver a estrutura de JDBC que o Spring provê, eu fico assustado com o tamanho da luta que as pessoas devem ter pra usar isso, é sofrível, tanto em produtividade quanto em performance. Porque o cache “manual” que eu fiz, dificilmente vai ser tão bem arquitetado quando o EhCache ou o OSCache.

O Hibernate é o meu herói :mrgreen:

Ah, e só pra constar, eu, pessoalmente, sou completamente contra o uso de annotations no código, já basta de poluição, configuração fica em arquivo XML :evil:

E viva o HibernateSyncronizer!!![/quote]

Essa coisa me deu tanto trabalho da primeira vez que eu usei, que eu resolvi nunca mais usar ferramenta nenhuma pra gerar os códigos pro Hibernate :lol:

Sei la, no Rails eh assim e a nomenclatura funciona muito bem, obrigado… :slight_smile:

Sei la, no Rails eh assim e a nomenclatura funciona muito bem, obrigado… :)[/quote]

Ah CV, mas e se o DBA for fresco e não quizer que seja assim?

Eu to participando de um curso aqui que todas as tabelas que o cara tá mostrando, são tb_nome_da_tabela, as views são vw_nome_da_view. Quando só tem a aplicação dagente acessando, isso é besteira, mas e quando outras aplicações também acessam com esses nomes horríveis?

Aí num dá pra mudar :?

Ah, outra coisa, como é que faz N:N no AR CV? Eu só vi até 1:N (você já pegou aquele livro de Rails? Da Pragmatic?)

Em um banco descente da pra fazer isso via MetaData, mas como eu disse na minha primeira resposta o bixo comeca a pegar e nao é simples como fazer um crudizinho com uma ou duas tabelas.

Outra coisa, cache é bom, mas nao resolve todos os problemas de performance. Entao nao adiante achar que fazendo cacha a vida esta a salva.

]['s

Nao é so o DBA ser fresco, tem muitas empresas que tem padrao pra esse tipo de nomeclatura e olha tem cada coisa por ai que da dó. :mrgreen:

]['s

Esse é um dos maiores problemas com os drivers e um dos que o pessoal do Hibernate mais reclama, o Drivers não devolvem as informações dobre o banco corretamente ou devolvem incompletas. O MySQL por exemplo, simplesmente não manda praticamente nada sobre os relacionamentos (especialmente quando você usa MyISAM). Não dá pra confiar só nisso.

Sei não, uma coisa que não se resolve com cache só pode ser query mal feita.