Persistência flexível com BoxSQL

Fiquei com uma dúvida. E quando houver relacionamentos entre as tabelas? Como o framework vai identificar a qual entidade pertence o atributo?

Bom, nesse caso ainda não está implementada essa funcionalidade.
Que ainda será implementada utilizando Annotations.

Veja um exemplo que explica como fazer isso:

Imagine que você tenha uma Classe Departamento e nela tem um atributo do tipo Pessoa.
Para você inserir esse departamento completo, incluindo o atributo comples do tipo Pessoa, o código ficaria assim:

[code]
public void insertDpto(Departamento dpto) throws Exception {

try{
BoxSQL box = new BoxSQL();

// Insere o departamento
int result1 = box.executeUpdate("insertDpto.sql", dpto);

// Insere o atributo complexo;
int result2 = box.executeUpdate("inserePessoaDpto.sql", dpto.getPessoa());

if(result1 == 0 || result2 == 0)
  throw new Exception("não inseriu completo!");

}finally{
box.release();
}
}[/code]

Você tb pode setar os parâmetros manualmente, o que seria uma opção um pouco m ais trabalhosa, porém em alguns casos é necessário.

Para recuperar do banco de dados voce terá que fazer assim também. Primeiro recuperar o dpto e depois a pessoa.

Essa funcionalidade está na fila para ser implementada, mas com oeu já disse antes, tá faltando mao-de-obra, hehehhe…
Porém, mesmo sem essa funcionalidade não é tão difícil de realizar essa operaão. O único problema é que terá que ter um SQL para o objeto principal e um SQL para o atributo complexo.

Espero que tenha ajudado.

Felipe

A minha dúvida estava mais para consultas com select. No fim das contas eu gostaria de saber como faço para consultas em mais de uma tabela. Se tem alguma convenção para isso, ou se tem uma maneira de não esperar pela reflection que o framework faz. Estou fazendo essas peguntas porque gostei do framework e pretendo usá-lo em casos que o mapeamento objeo/relaciona não seja viável.

Valeu

[quote=feliperod]Bom, nesse caso ainda não está implementada essa funcionalidade.
Que ainda será implementada utilizando Annotations.

Veja um exemplo que explica como fazer isso:

Imagine que você tenha uma Classe Departamento e nela tem um atributo do tipo Pessoa.
Para você inserir esse departamento completo, incluindo o atributo comples do tipo Pessoa, o código ficaria assim:

[code]
public void insertDpto(Departamento dpto) throws Exception {

try{
BoxSQL box = new BoxSQL();

// Insere o departamento
int result1 = box.executeUpdate("insertDpto.sql", dpto);

// Insere o atributo complexo;
int result2 = box.executeUpdate("inserePessoaDpto.sql", dpto.getPessoa());

if(result1 == 0 || result2 == 0)
  throw new Exception("não inseriu completo!");

}finally{
box.release();
}
}[/code]

Você tb pode setar os parâmetros manualmente, o que seria uma opção um pouco m ais trabalhosa, porém em alguns casos é necessário.

Para recuperar do banco de dados voce terá que fazer assim também. Primeiro recuperar o dpto e depois a pessoa.

Essa funcionalidade está na fila para ser implementada, mas com oeu já disse antes, tá faltando mao-de-obra, hehehhe…
Porém, mesmo sem essa funcionalidade não é tão difícil de realizar essa operaão. O único problema é que terá que ter um SQL para o objeto principal e um SQL para o atributo complexo.

Espero que tenha ajudado.

Felipe[/quote]

Ok,
Para consultas voce pode fazer qualquer tipo de cruzamento entre as tabelas, já que você está utilizando SQL normal.

Quando à esperar pela reflection, tb pode ser evitada na hora de setar os parametros, porém não vejo ganho de performance, já que a API de reflection já é bastante otimizada.

Veja um exemplo para fazer sem reflection:

public  void getDptoById(String Id) throws Exception {
   
   try{  
     BoxSQL box = new BoxSQL();  

     //Define os parametros
     box.setParameter("DPTOID", id);   

     // Obtém o departamento 
     Departamento dpto = (Departamento) box.getObject("obtemDpto.sql", Departamento.class);  
   
     //Obtém a pessoa pelo Id do Departamento (Supondo que exista um relacionamento baseado no ID do DPTO)
     dpto.setPessoa((Pessoa) box.getObject("obtemPessoaPorDptoId.sql", Pessoa.class));

     if(dpto == null || dpto.getPessoa() == null)
        throw new Exception("Deu Pau na hora de pegar do banco!");

   }finally{  
     box.release();  
   }  
}  

Viu a simplicidade?
Isso também poderá ser resolvido quando tivermos uma annotation que defina a recursividade de consultas e updates.
Ainda temos que pensar como serão as annotations para esse caso, mas sempre teremos a opção de fazer da forma
mostrada acima.

Olá,

Eu estava lendo todas mensagens pra entender um pouco do framework mas parei quando li essa parte.

Acredito que o problema que voces tiveram não foi qual framework de ORM utilizar, mas sim problema no banco. Pra eu ter que me preocupar com o plano de execucao de uma query meu banco tem que estar trabalhando por regra ou estar com as estatisticas desatualizadas (o mais comum). Entao ao invez do DBA enxer o saco do pessoal do desevolvimento ele devia era se preocupar em fazer o trabalho dele.

Se o problema fosse consultas gigantes por ter muitos relacionamentos sem necessidade eu até entenderia o argumento, mas esse do plano de execucao em pleno 2007 nao tem mais sentido.

]['s

[quote=fabio.patricio] Acredito que o problema que voces tiveram não foi qual framework de ORM utilizar, mas sim problema no banco. Pra eu ter que me preocupar com o plano de execucao de uma query meu banco tem que estar trabalhando por regra ou estar com as estatisticas desatualizadas (o mais comum). Entao ao invez do DBA enxer o saco do pessoal do desevolvimento ele devia era se preocupar em fazer o trabalho dele.

Se o problema fosse consultas gigantes por ter muitos relacionamentos sem necessidade eu até entenderia o argumento, mas esse do plano de execucao em pleno 2007 nao tem mais sentido. [/quote]

Talvez você esteja certo quando nos referimos a sistemas onde podemos modelar o banco de dados do zero, ou mesmo sistemas onde o banco está bem modelado. Mas não é raro encontrar situações onde o Banco de Dados está altamente fragmentado e incompatível com o modelo Orientado a Objetos.

Outra situação bem comum, são casos onde funções do banco devem ser chamadas durente um select ou um insert. Já vi vários sistemas que obtém informações que ao invés de estarem em um campo da tabela, são resultado de uma função, e devem ser adcionados dentro de um select específco.

Bom, eu ainda vejo muitos e muitos programadores PL/SQL por aí, isso significa que planos de execução e funções para tratamento de regras de negócios ainda são muito usadas.

Agora, se fossemos falar sobre um banco de dados perfeitinho, com um DBA compreensivo e alinhado com Orientação a Objetos, aí sim… Concordo plenamente com você.

:slight_smile:

Note que em nenhum momento eu falei em banco de dados preparado para OOP, o que eu quis dizer é que fazer query baseado em regras é coisa de no minimo uns 7 anos atras. Hoje em dia usar query baseada em custo, as famosas estatisticas do banco, é o mais correto. Se as consultas precisam trabalhar baseadas em regras nos dias de hoje o DBA nao anda fazendo o trabalho dele.

Ja passei por isso tambem, mas não seria essa uma situacao que me faria abandonar as facilidades de um ORM.

O fato de existir muitos programadores PL/SQL por ai não tem nada a ver com o fato de precisar ou não usar RBO. Eu ainda me considero programador PL/SQL e la por 2003 já não usava mais esse tipo de “regra” para minhas consultas.

Certa vez fui até repreendido por um DBA por estar forcando um indice com um hint do Oracle.

Pois é, mas eu nem falei isso, estou falando de banco de dados todo torto mesmo…ja mexeu com IFS Applications? Se sim deve imaginar o que to falando.

]['s

Bom, acho que meu caso se encaixa perfeitamente neste tópico !!!

Trabalho num empresa onde o principal produto é um ERP feito em Delphi + Oracle, que já existe a quase 8 anos. Os projetos web em java é tudo baseado neste banco, onde existem milhares de tabelas com milhares de Triggers e Pkg’s !!!

Estou desenvolvendo um projeto utilizando JSP + VRaptor + Hibernate, neste projeto tive que usar algumas funções específicas do Oracle, por isso 10% do SQL tive que usar Query Nativa.

Agora tenho um caso de um projeto já desenvolvido em JSP + JavaBeans + JDBC, onde pretendo migrar para JSP + VRaptor + Hibernate. Neste novo padrão 50% do SQL deverá ficar em Query Nativa devido ao uso de várias funções específicas do Oracle. Neste caso ficaria melhor usar o BoxSQL ???

Valew.

Pra não dar Quote em cima :

As experiências em cada empresa variam bastante, já encontrei projetos que seguem DDD e outros com tabelas fragmentadas como o amigo citou.

Gostaria só de argumentar em cima de características do Hibernate como Named Queries, para você externalizar e qual o ganho do BoxSQL dessa feature.

Lembrando que pode utilizar de formas diferentes, como XML ou Annotations :

[code]mport javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;

@Entity
@SqlResultSetMapping(name = “implicit”, entities = @EntityResult(entityClass = data.Employee.class))
@NamedNativeQuery(name = “implicitSample”, query = “select e.empno empNumber, e.ename empName, e.job empJob, e.sal empSalary, salg.grade empGrade from emp e, salgrade salg where e.sal between salg.losal and salg.HISAL”, resultSetMapping = “implicit”)

public class Employee {

private String empNumber;

private String empName;

private String empJob;

private Double empSalary;

private int empGrade;

@Column
@Id
public int getEmpGrade() {
return empGrade;
}

public void setEmpGrade(int empGrade) {
this.empGrade = empGrade;
}

@Column
public String getEmpJob() {
return empJob;
}

public void setEmpJob(String empJob) {
this.empJob = empJob;
}

@Column
public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}

@Column
public String getEmpNumber() {
return empNumber;
}

public void setEmpNumber(String empNumber) {
this.empNumber = empNumber;
}

@Column
public Double getEmpSalary() {
return empSalary;
}

public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}

}[/code]

[quote=marceloplis]
Agora tenho um caso de um projeto já desenvolvido em JSP + JavaBeans + JDBC, onde pretendo migrar para JSP + VRaptor + Hibernate. Neste novo padrão 50% do SQL deverá ficar em Query Nativa devido ao uso de várias funções específicas do Oracle. Neste caso ficaria melhor usar o BoxSQL ???

Valew.[/quote]

Eu sugiro utilizar as 2 soluções. Você poderia utilizar o BoxSQL para manter o seu SQL simples e organizado e o JPA ou alguma outra coisa para os outros 50%.

Vale lembrar que o BoxSQL faz isso com 51Kb, então não é nenhum elefante branco para resolver seu problema. É uma API simples, com um objetivo simples.

Mas em minha opinião a flexibilidade que o BoxSQL oferece em relação às NamedQueries do JPA é bem maior, podendo passar várias coisas como parâmetros.

O exemplo do Kenobi ficou muito bom e parece muito simples, mas se você reparar o banco está bem similar ao objeto.
Imagine que essa Classe citada pelo Kenobi tivesse 3 tipos de queries diferentes. Isso pode acontecer por inúmeros motivos.
Uma tabela só de valores e outra só de metadados da entidade. Em momentos você precisa cruzar as duas tabelas para obter os metadados junto com os valores ou momentos que só precisamos dos metadados (para montar telas com campos dinâmicos).
Não gosto da idéia de ter 3 ou quatro queries embutidas em annotations dentro dessa classe.

Aí numa dessa eu pergunto, por que não usar o BoxSQL?
Será que vai ferir muito os conceitos da JPA? O BoxSQL não pode vir a somar num casos como o citado acima ou mesmo o caso do ERP com Java Beans e JDBC? A reestruturação do projeto em JSP + JavaBeans + JDBC para utilização do BoxSQL é bem simples. Remove a linhas de código do DAO, pões as consultas em templates e coloca de 3 a 10 linhas do BoxSQL. E quanto à migração desse projeto para a JPA?

Mais uma vez volto a falar. Em sistemas novos com entidades sólidas e não fragmentadas, não precisamos do BoxSQL (apesar dele atender tb a esse publico). Mas em situações de banco de dados tortos e eu chamo de torto um banco com várias tabelas para formar um único objeto (o que não tem relação com execução por regras), o BoxSQL é realmente uma boa opção para resolver isso.

Lembrando que você pode sempre externalizar isso, não necessariamente precisa ficar como annotation.

Ficaria em XMLs. É válido também, mas se não formos utilizar nenhuma outra funcionalidade da JPA, acho que os templates em .SQL seriam melhores do que os XMLs ou mesmo melhor do que colocar essas annotations em uma única classe.

o que voces acham?

A discussao é… qual a vantagem do BoxSQL ? só estou vendo uma… curva de aprendizado não tão ingrime…

JPA te dá 4 ou 5 maneiras diferentes de fazer o que o boxSQL faz… e ainda é integrado… transacoes etc…

JPA e BoxSQL são diferentes.

Eu uso Ibatis e não tenho problema em ter minhas queries em XML, gosto da maneira do Ibatis.

Você deu dois exemplos gerando exceções.
No ibatis você consegueria fazer o mesmo resultando colocando o retorno da query em um dois objetos.(como foram usado no exemplo)

Tem como fazer isso?

<select id="findEmployees" resultMap="empResult">

      SELECT * FROM emp

      <dynamic prepend="WHERE">

            <isNotEmpty prepend="AND" property="id">

                  empno=#id#

            </isNotEmpty>

            <isNotEmpty prepend="OR" property="name">

                  ename=#name#

            </isNotEmpty>

      </dynamic>

</select>

E isso?

[code]

  SELECT * FROM emp

  <dynamic prepend="WHERE">

        <iterate property="departments" open="(" close=")"

              conjunction="OR">

              deptno=#departments[]#

        </iterate>

  </dynamic>

[/code]

aew feliperod qual a diferença entre usar o boxsql.properties e nao usa-lo.
Verifiquei que na video aula em q o manoel ministra, este nao usa o .properties,
entou pergunto ha alguma diferença de performace entre usa-lo ou não ?

A versção que ele usava quando gravou a video-aula não possuía o arquivo properties ainda.
Hoje é obrigatório o properties.

Tivemos que fazer isso para que o BoxSQL fizesse a conexão automaticamente, e dar a opção de escolha entre conexão JDBC ou JNDI.

A versão que ele usava era denominada 2.21, mas depois de pensarmos um pouco e acabarmos um refactoring estrutural no BoxSQL, decidimos resetar o numero da versão.

QQ dúvida posta aí.

Seguinte,

Estive testando algumas situações no JPA e não precisei ir muito longe.
Imagine que tenho uma tabela simples, com uma primaryKey e um unique constraint para um campo.

Como faria para obter um objeto a partir daquele unique constraint usando JPA?

Simples, teria que construir uma query. Colocar o SQL no meio do código. Ou como já citado aqui, usar uma named query, que na minha opinião deve ser usado para casos mais complexos.

Dessa forma temos que chamar em.createQuery(“seu sql aqui no meio do código”).getResultList()

Tá, ele já retorna a lista populada, mas o BoxSQL também faz isso. Então fica minha pergunta, quando a funcionalidade de queries simples estiver implementada no BoxSQL, sem precisar de templates e também a funcionalidade de um DAO generico utilizando Generics já embutido no BoxSQL, qual será a vantagem de se usar JPA?

PS.: Falta ainda citar que a parte de Log e Transaction do BoxSQL precisar ser repensada.

Mas o que eu quero dizer é, imagine um framework com 51Kb, que faz tudo que o JPA faz com muito menos configuração. Entre qual do dois você optaria?

Sua situacao eh bem particular… porem…

te devolvou com outra pergunta…

e qual eh a vantagem em NAO usar JPA ?

[quote=chun]Sua situacao eh bem particular… porem…

te devolvou com outra pergunta…

e qual eh a vantagem em NAO usar JPA ?[/quote]

Não acho que minha situação seja realmente tão particular assim.

Imagine uma situação simples, de uma tela de login. O cara digita o email e o password.

Mas meu banco de dados tem uma primaryKey pelo CPF e uma unique constraint pelo email.

Tenho que usar uma Query pra fazer isso. Mas e daí? No BoxSQL tb tenho que usar uma query.
Mas o BoxSQL é um framework em evolução e tem apensa 51KB. A curva de aprendizado é bem menor e tem a vantagem de não colocar o SQL dentro do código java.

E para obter uma simples lista de registros usando JPA? Eu preciso de uma Query também. Putz, mas mudou a clausula where, e agora? Compila tudo de novo porque o SQL tá dentro do código. Mas em que classe?

A única vantagem que vejo para JPA é que é especificado pelo JCP. O o torna um padrão no desenvolvimento. Porque os outros itens de vantagem são temporários.

Mapeamento de Herança no BoxSQL é Transparente, indice e constraints também, pois são definidos no código.

Ps.: Eu optei por usar JPA no projeto atual, fato que demonstra que não acho JPA ruim, porém acho o BoxSQL muito promissor.

rapaz… me desculpe… esta estoria de “vai ter que recompilar tudo” para mim eh pura baboseira… hoje em dia um “play” no netbeans e vc tem o .jar na mao pronto. Acho que posso contar nos dedos as vezes que abri um .jar na unha para a alterar o conteudo dele… de alguma conf…

Vantagens temporarias ? Hibernate oferece vantagens temporarias as muito tempo hein ? JPA veio padronizando isso…

Acho que nao tem nada de temporario… :slight_smile: