Lançado o MentaBean - Persistencia simples via configuração programática

========= Disponível para testes no jar beta e no SVN: http://www.mentaframework.org/beta/mentawai.jar

O Mentawai agora oferece uma solução simples para persistência de beans (POJOs) em banco de dados. Para fazer o mapeamento Tabela -&gt Objeto utilizamos configuração programática ao invés de XML ou Annotations.

A idéia aqui não é competir com Hibernate, JPA ou iBatis, mas sim oferecer uma solução simples, fácil e eficiente para fazer CRUDs de beans em seus projetos que utilizam o Mentawai.

Acreditamos que em muitos casos simples o MentaBean será uma mão-na-roda para vc persistir os seus Beans sem ter que depender do Hibernate/iBatis/JPA, etc e suas configurações.

Veja como é simples:


package hello;

public class User {
	
	private int id;
	
	private String name;
	
	private int age;
	
	public User(int id) {
		
		this.id = id;
	}
	
	public int getId() {
		
		return id;
		
	}
	
	public void setAge(int age) {
		
		this.age = age;
	}
	
	public int getAge() {
		
		return age;
	}
	
	public void setName(String name) {
		
		this.name = name;
	}
	
	public String getName() {
		
		return name;
		
	}
}

public void init(Context application) {

     ioc("session", MySQLBeanSession.class);

     filter(new IoCFilter());

     filter(new ConnectionFilter(connHandler));

    filter(new DIFilter("conn", Connection.class));

}

public void loadBeans() {

      bean(hello.User.class, "Users")
		.field("id", DBTypes.AUTOINCREMENT, true)
		.field("name", DBTypes.STRING)
		.field("age", DBTypes.INTEGER);

        // ou
 
        BeanConfig bc = new BeanConfig(User.class, "Users");
        bc.addField("id", DBTypes.AUTOINCREMENT, true);
        bc.addField("name", DBTypes.STRING);
        bc.addField("age", DBTypes.INTEGER);
        addBeanConfig(bc);
	
}

public class HelloMentaBean extends BaseAction {

     public String execute() throws Exception {

          BeanSession session = (BeanSession) input.getValue("session");

          User u = new User(1);

          if (session.load(u)) {

                System.out.println("Bean carregado!");

          }

          System.out.println("Username: " + u.getName());

          // update a bean...

          u.setName("Azenha");

          session.update(u);

          // delete a bean...

          session.delete(u);

          // inserindo...

          User u = new User(2);

          u.setAge(19);

          u.setName("Pedro");

          session.insert(u);

          return SUCCESS;
     }
}

Pontos importantes:

:arrow: Os updates gerados são inteligentes para fazer apenas o update nas colunas que foram alteradas, ou seja, se vc faz o load() de um bean com 20 colunas, altera uma coluna e faz um update(), apenas a coluna alterada sofrerá um update ao invés de todas.


User u = new User(1);

session.load(u); // 100 campos foram carregados aqui...

u.setAge(44);

session.update(u); // vai gerar apenas update users set age = ? where id = ? e não um update gigantesco dos 100 campos...

:arrow: Se vc deseja fazer um update num registro sem carregá-lo em memória antes, tudo que vc tem que fazer é construir um objeto, não fazer o load, setar os campo que vc deseja fazer o update, e chamar update:


User u = new User(1);

// não estamos dando load() !!!

u.setAge(44);

session.update(u); // vai gerar update users set age = ? where id = ?

:arrow: Suporta a criação de outros tipos de coluna para o banco de dados, isto é, se vc precisar vc pode criar novos tipos de dados para a inserção no seu bd isso é muito fácil de se fazer:


public class MyType extends DBType {
	
	public MyType() {
		
		super("MEUTIPO");
	}
	
	public Object getFromResultSet(ResultSet rset, int index) throws SQLException {
		
		return '&lt' + rset.getString(index) + '&gt';
	}
	
	public Class&lt? extends Object&gt getTypeClass() {
		
		return java.lang.String.class;
	}
	
	public void bindToStmt(PreparedStatement stmt, int index, Object value) throws SQLException {

		if (value instanceof String) {
			
			String s = (String) value;
		
			stmt.setString(index, s);
			
		} else {
			
			throw new IllegalArgumentException("value is not a string!");
		}		
	}
}

:arrow: Suporta AUTOINCREMENT do MySQL, ou seja, automaticamente recupera o ID gerado pelo MySQL e coloca no seu bean quando vc faz um INSERT. Suporta SEQUENCE do Oracle, ou seja, automatimcamente utiliza uma sequence do Oracle para gerar a chave primária do seu bean.


User u = new User(); // sem ID, o id será criado pelo banco...

u.setAge(33);

u.setName("Pela");

session.insert(u);

System.out.println("ID do objeto inserido: " + u.getId());

:arrow: Se o nome da variável do seu bean for diferente do nome do seu campo na tabela do banco de dados, basta fazer assim:


public void loadBeans() {

      bean(hello.User.class, "Users")
		.field("id", DBTypes.AUTOINCREMENT, "USER_ID", true)
		.field("name", DBTypes.STRING, "USER_NAME")
		.field("age", DBTypes.INTEGER, "USER_AGE")
	
}

Em muito breve:

:arrow: Suporte a tranções. Até lá vc pode simplesmente pegar a connection da session e fazer a transação com JDBC.

:arrow: Suporte a carregamento de listas de objetos, ou seja:


User u = new User();

u.setAge(33);

List users = session.loadList(u); // retorna uma lista de todos os usuários que possuem 33 anos...

Simplorio, nao simples. E cade os testes?

Vc acha um saca-rolha simplório ou simples?

Tinha um eletronico vendendo aqui na televisão que sacava a rolha sem danificá-la. O furo ficava perfeito tb, bem no centro.

Estamos falando de CRUD simples de beans. Não suporta outer join nem redes neurais.

Eu fiz alguns testes aqui e funcionou ok. Mas está em beta ainda…

PARABENS ³

Cada dia que passa vejo que nao escolhi o framework errado!!!

Um espetaculo Sergio…

Uma dica, se esforca nesse MentaBeans, faca com que ele se possivel se torne um framework a parte do Menta… E tente encaixar logo o suporte a list, collection e etc…

Porque to vendo que vai da SAMBA!

PARABENS IRMAO!

Quer dizer que o Mentawai também está em beta? Ele ainda não tem testes.

Naoooooo

O Mentawai nao só uma versao estavel, como ja esta a mais de 2 anos no mercado e na versao 1.9!
Sendo usado por empresas profissionalmente, projetos Free Lancers, grande participacao dos usuarios / desenvolvedores no forum do Projeto e etc…

O Que o SAOJ falou que esta beta é o mentaBeans, um framework de persistence que acabou de ser lancado…

Mas se voce chegar no forum e ouvir dizer pega a versao "1.9 beta mais nova"
Quer dizer que tem tudo testado, homologado , documentado da versao 1.9(a atual ate a presente data) mas os bugs , melhorias , codereviews e etc… Adicionado apos o lancamento da 1.9.
Esperando somente a confirmacao das melhorias, adocao de novas features, documentacao, exemplos e etc…
Para sair uma nova versao…

Pois o SAOJ (Sergio) tem uma frase muito boa:
"Bug é bug! Tem que achar e matar rápido mesmo… "
Por isso é capaz de lancar a versao 1.9 hoje e daqui a 1 dia ter a versao 1.9 beta, que significa que tem a 1.9 + as correcoes de bugs e as ideias + novas que nao deu tempo ou nao apareceu antes do lancamento da versao!

[]'s

Sérgio, eu tb gosto de configuração programática para muitos casos, contanto que você NÃO precise configurar.

Minha dica é usar um pouquinho mais de convenções. Não se ofenda nem fique nervoso, é só uma dica. Se não gostar apenas ignore.

Só acho que não adianta nada pegar um xml de N linhas e transformar em código Java de N/2 linhas, ou pior ainda transformar o mesmo xml em N anotações.

[quote=afsrj]Naoooooo

O Mentawai nao só uma versao estavel, como ja esta a mais de 2 anos no mercado e na versao 1.9!
Sendo usado por empresas profissionalmente, projetos Free Lancers, grande participacao dos usuarios / desenvolvedores no forum do Projeto e etc…
[/quote]

Codigo sem teste unitario eh codigo inutil.

ps. isso vai ser engracado …

Ola Sergio.

Para efeito de comparacao, segue aqui o mesmo codigo so que para o hibernate:

A classe usuario fica:

package hello;

@Entity
public class User {
	@Id @GeneratedValue
	private int id;
	
	private String name;
	
	private int age;
      // getters e setter opcionais
	
}

Bem menor nao? Ate porque nem sempre queremos os getters e setters, talvez metodos de negocios vao mexer com os atributos (boa pratica).

E o codigo na sua action fica:

public class HelloMentaBean extends BaseAction {
     public String execute() throws Exception {
	 Session s = new AnnotationConfiguration().configure().buildSessionFactory()
		.openSession();

          User u = session.load(User.class, 1);

          System.out.println("Username: " + u.getName());
          // update a bean...
          u.setName("Azenha");
          session.update(u);
          // delete a bean...
          session.delete(u);

          // inserindo...

          User u = new User();
          u.setAge(19);
          u.setName("Pedro");
          session.save(u);

          return SUCCESS;
     }
}

Alem disso:

  • nao precisa do codigo de init do contexto
  • nao precisa do load beans
  • o hibernate tambem faz update so dos campos que esta dirty se voce quiser. tem muita gente que desconhece mesmo
  • o hibernate pode fazer update sem fazer o load. voce pode usar o merge para isso, ou usar HQL com update.
  • o hibernate suporta criacao de tipos novos, igualzinho como voce fez.
  • alem de auto increment e sequence, suporta propria tabela de sequence, hilo, genracao de id universal e possibilita voce inventar seu sistema de geracao de chaves
  • Para mudar o nome da coluna, no hibernate basta @Column(columnName=“bla”)
  • Da para fazer a configuracao TODA programaticamente, isso tem alguns anos.

E a MUITO tempo, ja tem:

  • suporte a transacao
  • suporte a listas de objetos

Se no hibernate parece ser mais simples, nao entendi o motivo do framework.

prevejo um tópico de 5 páginas…

Paulo, aproveitando a onda, vc poderia explicar como configurar o hibernate para fazer este update inteligente nos objetos transientes? Procurei pelo site do hibernate e pelo google e não tive sucesso. Desculpem a fuga do tema do topico., mas esta é uma sabedoria que deve ser compartilhada. :lol:

Alberto

Sérgio, ja que tu não vai desistir de fazer este MentaBeans (que eu achei completamente desnecessário, se seguir esta linha da demonstração)

por que em vez de fazer algo com configuraçãp programática, tu não tenta fazer algo que não precisa configurar?

pelo menos para as situações mais comuns, não deveria ser necessário configurar, isto sim seria interessante …

o que esta feito até agora é uma versão mais pobre e mais dificil de utilizar que qualquer outro framework O/R que ja existe …

em vez de fazer a mesma coisa, se tu conseguir fazer algo, que pelo menos nas situações consideradas “padrão” pelo framework, não seja necessário configurar, ai sim pode ser algo interessante …

PS.: nada contra opções, mas qual a vantagem de fazer a mesma coisa que ja existe, só que mais dificil, menos flexivel e menos poderoso?

[quote=Paulo Silveira]Ola Sergio.

Para efeito de comparacao, segue aqui o mesmo codigo so que para o hibernate:

A classe usuario fica:

package hello;

@Entity
public class User {
	@Id @GeneratedValue
	private int id;
	
	private String name;
	
	private int age;
      // getters e setter opcionais
	
}

Bem menor nao? Ate porque nem sempre queremos os getters e setters, talvez metodos de negocios vao mexer com os atributos (boa pratica).

E o codigo na sua action fica:

public class HelloMentaBean extends BaseAction {
     public String execute() throws Exception {
	 Session s = new AnnotationConfiguration().configure().buildSessionFactory()
		.openSession();

          User u = session.load(User.class, 1);

          System.out.println("Username: " + u.getName());
          // update a bean...
          u.setName("Azenha");
          session.update(u);
          // delete a bean...
          session.delete(u);

          // inserindo...

          User u = new User();
          u.setAge(19);
          u.setName("Pedro");
          session.save(u);

          return SUCCESS;
     }
}

Alem disso:

  • nao precisa do codigo de init do contexto
  • nao precisa do load beans
  • o hibernate tambem faz update so dos campos que esta dirty se voce quiser. tem muita gente que desconhece mesmo
  • o hibernate pode fazer update sem fazer o load. voce pode usar o merge para isso, ou usar HQL com update.
  • o hibernate suporta criacao de tipos novos, igualzinho como voce fez.
  • alem de auto increment e sequence, suporta propria tabela de sequence, hilo, geração de id universal e possibilita você inventar seu sistema de geração de chaves
  • Para mudar o nome da coluna, no hibernate basta @Column(columnName=“bla”)
  • Dá para fazer a configuracao TODA programaticamente, isso tem alguns anos.

E a MUITO tempo, ja tem:

  • suporte a transacao
  • suporte a listas de objetos

Se no hibernate parece ser mais simples, nao entendi o motivo do framework.[/quote]

Além de tudo isso que o Paulo citou, Hibernate permite que você crie desde soluções de “CRUD simples para Beans” até “persistência entre objetos com relacionamentos malucos”, ou seja, é mais flexível e não vai obrigar que eu reescreva todo meu sistema novamente porque, de repente, ele deixou de ser um simples “cadastrinho” e passou a ser um sistema um pouco mais complexo.

Além disso, este projeto vai seguir a mesma política do MTW de não ter testes unitários para quase absolutamente nada? Como você pretende garantir backward compatibility conforme sua biblioteca evolui sem testes?

Oi Alberto

[quote=alots_ssa]Paulo, aproveitando a onda, vc poderia explicar como configurar o hibernate para fazer este update inteligente nos objetos transientes? Procurei pelo site do hibernate e pelo google e não tive sucesso. Desculpem a fuga do tema do topico., mas esta é uma sabedoria que deve ser compartilhada. :lol:
[/quote]

@org.hibernate.annotations.Entity(dynamicUpdate=true)

Sergio, eu vou ter que concordar com o pessoal. Realmente acho que vc exagerou um pouco na dose.

O Hibernate eh um framework cuja qualidade eh comprovada. Ele eh completo, por isso tem uma ou outra complexidade, nada que um programador relativamente competente nao consiga dominar. E uma vez configurado, eh bem tranquilo de usar (principalmente se usar Hibernate Annotations).

Quanto ao uso ou nao dos testes unitarios, temos opnioes bem distintas quanto a isso (eu particularmente acho muito importante). Mas, you are the boss…

[quote=microfilo]

O Hibernate eh um framework cuja qualidade eh comprovada. Ele eh completo, por isso tem uma ou outra complexidade, nada que um programador relativamente competente nao consiga dominar. [/quote]

Nos casos supracitados, qual é a complexidade?

Esse é o meu ponto. o hibernate, para persistir beans, nao tem complexidade nenhuma.

Nao me venha com analogia furada. E leia o comentario do DQO de novo.

E cade esses testes que voce fez? Eu fui la olhar o repositorio, e ta aqui a versao mais recente do build.xml do Mentawai:

https://svn.sourceforge.net/svnroot/mentaframework/mentawai/build.xml

E nao tem uma mencao sequer as palavras ‘test’, ‘unit’ ou ate mesmo ‘run’. Como voce espera que eu confie no seu codigo? Lendo a porra toda?

Poder dizer “Fui eu quem fiz, ó!”.

Isso realmene ultrapassou todos os níveis do absurdo. Mas bola pra frente, assim é a comunidade Java, cada um que faça o seu e o resto que se lasque.

[quote=Paulo Silveira]Oi Alberto

@org.hibernate.annotations.Entity(dynamicUpdate=true)[/quote]

Desculpe fugir do tópico.
Deixar o update dinâmico (só atualizar as colunas modificas) não é uma boa pratica? porque então o default é false?

Entity.html#dynamicUpdate()

Penso que o Menta deve concentrar-se no MVC e delegar outras atividades que não são de sua competência direta para outros frameworks especialistas e já consagrados no mercado.

No máximo, o Menta poderia adotar um desses frameworks especialistas como padrão e fornecer certas facilidades para se trabalhar com ele. Por exemplo, caso o Menta quisesse facilitar a vida de alguns usuários que só querem trabalhar com objetos, sem se preocupar com JDBC, Mapeamentos OR, etc, poderia usar como padrão o DB4O (só como exemplo, pois como é GPL “contamina”). Tutorial pra quem tiver curiosidade: http://www.db4o.com/about/productinformation/resources/db4o-4.5-tutorial-java.pdf.

Persistência é uma coisa que deve ser levada a sério, pois os dados são a alma de qualquer sistema e frameworks como Hibernate, Ibatis, etc, já estão maduros o suficiente para assumirem tal tarefa.

[EDITADO]
Só para acrescentar, antes que me corrijam, o db4o também possui uma licença comercial. :wink:
[/EDITADO]