Estou com o seguinte problema, trabalho hoje com o Delphi 5 + Oracle estamos começando a migração para o Java + Web
as regras de negócios estão todas no banco de dados são Triggers, Procedures, Functions, etc.
Nesse meu cenário onde eu tenho tudo gerado pelo banco de dados qual o melhor framework de persinstência ?
Existem várias ferramentas para gerar as classes Java a partir das tabelas do Oracle (Netbeans é uma boa ferramenta, só precisa adicionar o Hibernate, pois o padrão é o Toplink).
rodrigoallemand
joaosouza:
Olá…
Viajou!
Sugiro, já que seu entendimento é inicial, partir pro hibernate mesmo, sem anotação pra ralar um pouco nos mapeamentos pra poder entender o funcionamento. Se o caso for corporativo mesmo, tipo sistemas de empresa, partir pro JPA!
E entre HibernateEntityManager (JBoss RedHat) e Toplinks (Oracle), sinta-se a vontade pra escolher!
Rodrigo.Lima
Na verdade, não importa se vc escolher entre toplink ou hibernate no começo, pois JPA funciona “sobre” eles.
L
Leonardo3001
Use a JPA (é só uma interface sobre qualquer framework de persistência), mas dê preferência ao Hibernate, pois as mensagens de erros e os log de erro são mais legíveis no Hibernate do que no Toplink Essentials.
L
luciano_guedes_antun
obrigado pessoal pelas respostas,
notei que o hibernate pelo menos para o inicio e a melhor opção já venho estudando ele a uma bom tempo
meu unico medo quanto ao seu uso e referente aquilo que eu havia falado as minhas regras de negocio ficam dentro do banco de dados
um exemplo so para esclarecer eu tenho triggers que geram as chaves primarias para mim, o hibernate consegue se entender com isso.
L
lavh
Cara,
pra esse seu caso aí eu usaria só JDBC. Acho que vc vai evitar boas dores de cabeça fazendo isso. Use no máximo o JDBCTemplate do Spring pra te ajudar…
Hibernate e JPA acho que pro seu caso não agregam muito, pois, pelo que eu entendi, vcs querem continuar a deixar as regras todas no banco, o que não é uma boa prática com Java…mas…
[]'s
F
foliveira81
Hibernate mais maduro e todos ja sabem como funciona o EJB é bom mas ainda é novidade pouco suporte !
Att
R
rflprp
Pense 10x se jdbc simples não atende bem ao seu problema.
Se não for usar EJB´s, pense em utilizar o Spring DAO support, é bem simples.
Se for utilizar ejb3, estude a possibilidade de usar JPA/Hibrnate.
[]´s
L
luciano_guedes_antun
até concordo que deveria utilizar o jdbc puro, mas o hibernate me traz uma forma melhor de lidar com os objetos a serem persistidos sem contar com as consultas que sao possiveis fazer com ele.
usar o hibernate no meu caso seria ruim mesmo assim ?
R
rflprp
Não é que seja ruim, o que eu aconselho é você avaliar se vale a pena incluir qualquer tipo de complexidade num projeto, e não sair utilizando frameworks pq está na moda.
Mas se houver um margem para aprendizado, sim, vale a pena utilizar o hibernate, é uma ferramenta bem interessante.
[]'s
L
luciano_guedes_antun
quanto a margem para o aprendizado não há problema conheco o hibernate já faz um bom tempo venho lendo a sua documentacao vendo exemplos de utilizacao entre outras coisas no modo XML sem anotacoes, mas o que me deixa preocupado e se ele vai me dar a liberdade de manter as minhas regras de negocio no banco de dados.
agodinho
Visto que vc está migrando acho que hibernate não é o melhor caminho.
O hibernate assume que seu modelo de dados foi desenhado para atender um modelo OO.
O hibernate favorece o desenvolvimento de aplicações oo. Se vc tem muita trigger e regra de negócios no banco é mais provável que sua aplicação seja orientada à banco (por mais que o código seja OO). Isso pode se tornar uma grande dor de cabeça visto que é bem possível que vc tenha de alterar algo no seu modelo de dados para melhor utilizar o hibernate e isso nem sempre é possível. Assumindo que vc não vai alterar seu modelo por causa de alguma necessidade do hibernate vc acabará tendo de utilizar algum recurso “extra” do hibernate pra dar a volta em alguma de suas limitações e isso acaba sempre complicando a manutenção.
Dentro do processo de migração você terá de aprender a utlizar todas as ferramentas (frameworks e bibliotecas) que eleger pro seu arsenal. Sugiro então que vc fique com o simples (que já foi validado pelo mercado), feijão com arroz, pra evitar ondas e modismos que possam aumentar seu risco.
Pra aplicações com essa configuração (orientada à banco) eu sugiro o iBatis/sqlMap.
IMO (e na prática).
Woody
L
luciano_guedes_antun
com o ibatis você acha que o meus problemas serão resolvidos deixando toda a regra de negocio no banco de dados ?
ddduran
Se a regra de negocio está em procs, triggers, etc. Aconselho usar JDBC logo
L
luciano_guedes_antun
o iBatis seria a solução então ?
ddduran
não, não seria tão ruim uma coisa legal do hibernate é que ele lhe permite sempre que for preciso passar por cima do framework.
Apenas analise seu sistema melhor para não acabar usando hibernate (ou qualquer outro framework) só por usar
agodinho
polui muito.
O iBatis ajuda exatamente nisso. Todos seus sqls ficarão em arquivos XMLs simples. Vc ainda terá uma camada de persistência (DAO) mas sua camada não fala jdbc. Ela simplismente delega isso pro ibatis.
agodinho
Cara, para a configuração de aplicação que foi mencionada (uma aplicação orientada à banco), seira uma das possíveis soluções sim. Se é a melhor depende de muitos outros detalhes. Só pra dar um exemplo: é possível que sua equipe torça o nariz e nem tente aprender a usar a ferramenta e, por melhor que seja, pode acabar afundando seu projeto.
Eu sugiro iBatis pq é um dos mais utilizados mas existem outros. Não aconselho o hibernate pra esse caso pq seu banco foi modelado sem levar em consideração qq necessidade desse framework.
Já cansei de ver gente reclamando do hibernate simplesmente por telo adotado em situações onde ele não é recomendado:
Se vc tem baixo controle do modelo de dados (o modelo é legado, possui regras rígidas de alteração ou limitação da utilização de recursos do banco)
O hibernate gera querys (DDL, MDL, sei lá) dinâmicamente - por essas serem geradas dinâmicamente não são passíveis de tunning (algumas empresas grandes proíbem o hibernate por isso).
O hibernate é ótimo - não me entenda mal. Só não é recomendado para seu caso.
agodinho
ddduran:
não, não seria tão ruim uma coisa legal do hibernate é que ele lhe permite sempre que for preciso passar por cima do framework.
Apenas analise seu sistema melhor para não acabar usando hibernate (ou qualquer outro framework) só por usar
Desculpe, não concordo. IMO.
JDBC puro só pra coisas muito simples (não comerciais) …
Então acho que no caso de persistência, só por usar, ainda vale.
Toda regra de negócios no banco já não é uma boa solução pra todos os casos, então: não irá resolver todos seus problemas mas não vai te limitar na implementação da solução.
L
luciano_guedes_antun
quanto ao aprendizado da equipe nao vejo problemas somos apenas dois, mas de inicio sou eu quem vai dar o pontape inicial estou mesmo tirando o maior número de duvidas possiveis para nao me arrepender depois, por exemplo eu pretendo trabalhar com as seguintes ferramentas Struts2 + Spring + iBatis que conforme estou vendo e a melhor solucao para mim.
estava lendo o manual do iBatis existe alguma forma de eu usar o Insert Into Teste(descricao) Values (‘xxxx’) Returning Id e uma construcao na qual eu posso utilizar no oracle, ou eu tenho que utilizar o selectKey que ele demonstra do manual ?
packagebr.com.cvrd.igrm.dao.comum;importjava.sql.SQLException;importjava.util.List;importbr.com.cvrd.igrm.to.IProjetoTO;importbr.com.cvrd.igrm.util.AbstractDAO;importbr.com.cvrd.igrm.util.PersistenceException;/** * <p > * Template das classes de persistência das entidades dos projetos do modelo base e * corporativo.</p> * * @author Anaximandro de Godinho. * @version $Revision: 1.2 $ */publicabstractclassAbstractProjetoDAOextendsAbstractDAO{/*/ constantes públicas /*/publicstaticfinalStringP_Projeto="Projeto.";publicstaticfinalStringP_ProjetoBase="ProjetoBase.";/** * Construtor. * @param namespace o namespace do xml do sqlMaps a ser utilizado. */publicAbstractProjetoDAO(finalStringnamespace){_obter_Projeto=namespace+"obter_Projeto";_obter_ProjetoPorIdAlternativo=namespace+"obter_ProjetoPorIdAlternativo";_obter_ProjetoPorNome=namespace+"obter_ProjetoPorNome";_contar_ProjetosRaiz=namespace+"contar_ProjetosRaiz";_obter_ProjetosRaiz=namespace+"obter_ProjetosRaiz";_contar_ProjetosPorProjetoPai=namespace+"contar_ProjetosPorProjetoPai";_obter_ProjetosPorProjetoPai=namespace+"obter_ProjetosPorProjetoPai";_incluir_Projeto=namespace+"incluir_Projeto";_alterar_Projeto=namespace+"alterar_Projeto";_excluir_Projeto=namespace+"excluir_Projeto";}/** * Retorna o TO com os dados da linha da entidade projeto correspondente à chave fornecida. * * @param idProjeto a chave do projeto. * @return o TO com os dados da linha da entidade projeto correspondente à chave fornecida. * @throws PersistenceException */publicIProjetoTOobterProjeto(finalIntegeridProjeto)throwsPersistenceException{try{return(IProjetoTO)_sqlMap.queryForObject(_obter_Projeto,idProjeto);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna o TO com os dados da linha da entidade projeto correspondente à chave alternativa fornecida. * * @param idAlernativo a chave alternativa do projeto. * @return o TO com os dados da linha da entidade projeto correspondente à chave alternativo fornecida. * @throws PersistenceException */publicIProjetoTOobterProjetoPorIdAlternativo(finalStringidAlternativo)throwsPersistenceException{try{return(IProjetoTO)_sqlMap.queryForObject(_obter_ProjetoPorIdAlternativo,idAlternativo);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna o TO com os dados da linha da entidade projeto correspondente ao nome fornecido. * * @param nomeProjeto o nome do projeto. * @return o TO com os dados da linha da entidade projeto correspondente ao nome fornecido. * @throws PersistenceException */publicIProjetoTOobterProjetoPorNome(finalStringnomeProjeto)throwsPersistenceException{try{return(IProjetoTO)_sqlMap.queryForObject(_obter_ProjetoPorNome,nomeProjeto);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna a quantidade de linhas na entidade projeto com projetos no raiz. * * @return a quantidade de linhas na entidade projeto com projetos no raiz. * @throws PersistenceException */publicintcontarProjetosRaiz()throwsPersistenceException{try{return((Integer)_sqlMap.queryForObject(_contar_ProjetosRaiz)).intValue();}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna uma lista de TOs com os dados das linhas da entidade projeto com projetos no raiz. * * @return uma lista de TOs com os dados das linhas da entidade projeto com projetos no raiz. * @throws PersistenceException */publicListobterProjetosRaiz()throwsPersistenceException{try{return_sqlMap.queryForList(_obter_ProjetosRaiz);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna a quantidade de linhas na entidade projeto com o idProjetoPai fornecido. * * @param idProjetoPai a chave do projeto pai. * @return a quantidade de linhas na entidade projeto com o idProjetoPai fornecido. * @throws PersistenceException */publicintcontarProjetosPorProjetoPai(finalIntegeridProjetoPai)throwsPersistenceException{try{return((Integer)_sqlMap.queryForObject(_contar_ProjetosPorProjetoPai,idProjetoPai)).intValue();}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Retorna uma lista de TOs com os dados das linhas da entidade projeto com o idProjetoPai fornecido. * * @param idProjetoPai a chave do projeto pai. * @return uma lista de TOs com os dados das linhas da entidade projeto com o idProjetoPai fornecido. * @throws PersistenceException */publicListobterProjetosPorProjetoPai(finalIntegeridProjetoPai)throwsPersistenceException{try{return_sqlMap.queryForList(_obter_ProjetosPorProjetoPai,idProjetoPai);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Inclui uma linha na entidade projeto com os dados do TO fornecido. * * @param projeto o TO com os dados a incluir, exceto o campo chave. * @return o TO com a chave da linha incluída. * @throws PersistenceException */publicIProjetoTOincluirProjeto(finalIProjetoTOprojeto)throwsPersistenceException{try{finalIntegerkey=(Integer)_sqlMap.insert(_incluir_Projeto,projeto);projeto.setIdProjeto(key);returnprojeto;}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Altera os dados da linha da entidade projeto correspondente à chave fornecida. * * @param projeto o TO preenchido com os dados a alterar, inclusive sua chave. * @return a quantidade de linhas alteradas. * @throws PersistenceException */publicintalterarProjeto(finalIProjetoTOprojeto)throwsPersistenceException{try{return_sqlMap.update(_alterar_Projeto,projeto);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/** * Exclui a linha da entidade projeto correspondente à chave fornecida. * * @param idProjeto a chave da linha a excluir. * @return a quantidade de linhas excluídas. * @throws PersistenceException */publicintexcluirProjeto(finalIntegeridProjeto)throwsPersistenceException{try{return_sqlMap.delete(_excluir_Projeto,idProjeto);}catch(finalSQLExceptione){thrownewPersistenceException(e);}}/*/ constantes privadas /*/privatefinalString_obter_Projeto;privatefinalString_obter_ProjetoPorIdAlternativo;privatefinalString_obter_ProjetoPorNome;privatefinalString_contar_ProjetosRaiz;privatefinalString_obter_ProjetosRaiz;privatefinalString_contar_ProjetosPorProjetoPai;privatefinalString_obter_ProjetosPorProjetoPai;privatefinalString_incluir_Projeto;privatefinalString_alterar_Projeto;privatefinalString_excluir_Projeto;}
L
luciano_guedes_antun
eu vi que no seu insert você chama a sequence antes de fazer o insert, so que no meu caso a sequence vai ser disparada por uma trigger no banco de dados eu tenho que fazer com que o valor gerado pela “trigger” retorne para mim.
eu vi que no seu insert você chama a sequence antes de fazer o insert, so que no meu caso a sequence vai ser disparada por uma trigger no banco de dados eu tenho que fazer com que o valor gerado pela “trigger” retorne para mim.
se vc estiver usando oracle cuidado com as trigger mutantes!!!
porquê que vc precisa fazer isso??? trigger gerando sequence??? explica um pouco isso pra vermos se dá pra fazer alguma outra coisa …
L
luciano_guedes_antun
como eu falei no inicio o banco de dados contem toda a regra de negocio dos nossos sistemas portanto nos temos triggers que fazem com que as sequences sejam atribuidas, por exemplo eu nao hora de um insert eu nao passo a chave primaria passo somente os campos requeridos pela tabela a trigger que esta por traz dessa tabela que faz o trabalho de atribuir a chave primaria para o registro que estou fazendo insert portanto para mim seria fundamental fazer com que na hora do insert o valor que fosse gerado pela trigger fosse devolvido para mim a nivel de front-end (tela), quanto as triggers mutantes nao e motivo de preocupacao todas as nossas triggers estao em perfeito funcionamento sem mutantes
nao ha motivo para preocupacao.
agodinho
uma soluação possível para o que vc está querendo fazer:
vc vai fazer seu insert normalmente.
o banco, em meio ao insert, vai executar sua trigger e atualizar/calcular os campos necessários.
normalmente o ibatis, para operação de insert, retorna a chave primária criada só que como isso foi feito pela trigger não sei se esse retorno vai realmente conter o valor da trigger - melhor testar.
em último caso, se o retorno não corresponder ao id da trigger, vc pode, no dao, buscar a linha incluída.
Acho melhor testar pra não quebrar a cara.
Te adianto que pra campos obrigatórios vc fai ter que ainda específica-los nos sqls pois no momento de sua execução o banco não sabe o quê a trigger faz e, como de costume, irá reclamar da ausência de valores pra esses campos.
Esse é o comportamento do Oracle, não sei qual banco vc está usando.
L
luciano_guedes_antun
como faco para buscar a linha incluida no dao basta fazer um select ? pelo que ? se a chave e gerada pelo banco de dados.
agodinho
select mesmo.
vc tem todos os outros dados no transfer object, se isso não for suficiente ou vc não tiver uma chave alternativa (normalmente o nome) vc então tem um problema. Perceba que isso não tem nada a ver com iBatis, mas sim com a sua forma de trabalho.
L
luciano_guedes_antun
uma outra situação que temos aqui é a seguinte:
ItemPedido -> Tabela
NumPedido NumItemPedido
1 1
2 1
2 2
a chave primaria desta tabela é NumPedido + NumItemPedido sendo que o NumItemPedido é uma trigger que gera (sem mutante) no after como fazer neste caso ? faco um select tambem para recuperar o valor ?
agodinho
cara, seu item de pedido não tem nenhum outro campo que possa ser utilizado pra identificá-lo?
Sua trigger gera apenas o número do item de pedido certo? então vc poderia, no dao, buscar todos itens desse pedido e deduzir qual das linhas retornadas é o seu item …
Isso é medonho!!!
Não consigo parar de pensar na possibilidade de jogar fora essas triggers e chamar o chamar o nextval nos inserts direto. Acho que seria muito mais fácil pra vc.
Qual a necessidade de se manter essas trigger? Qual o esforço pra remover essas trigger e fazer que sua vida social não corra sérios riscos de ser extirpada???
L
luciano_guedes_antun
nao é so os pedidos o banco inteiro tem estes tipos de construcao ou seja as situacoes sao muitas, estou procurando a melhor solucao estou seriamente disposto a abandonar qualquer framework de persistencia e usar o JDBC puro mesmo por exemplo utilizando o JdbcTemplate do spring o que voce acha ?
L
lavh
eu faria isso.
E não acredite em quem fale que JDBC puro é só pra sistemas simples e não comerciais. Aqui na empresa usamos assim, e pode acreditar, as aplicações aqui não são nem um pouco simples, muito pelo contrário.
Frameworks ORM são excelentes. Mas pra este seu caso, você pode começar a ter q contornar(fazer gambiarra) as limitações do framework para esse seu caso, e isso pode virar um inferno.
[]'s
L
luciano_guedes_antun
concordo vou partir para o JDBC puro com o JdbcTemplate do spring.
E quanto a camada de visualização o Struts2 e a melhor opção para o meu caso ou tenho dar uma olhada em outras opções ?
jgbt
se suas regras estão todas no banco, acho que utilizar um framework ORM so vai acrescenar complexidade aoseu projeto.
sugiro usar JDBC com o DaoSupport do Spring. se quiser utilise o controlde de transações do Spring que funciona muito bem tmb, deixando vc livre para se preocupar com sua logica de negocio.
quanto a camada de visão, utilizei bastante o WebWork(atual Struts2), por isso acho uma boa escolha.
[]'s
L
luciano_guedes_antun
como faco o controle de transacoes no spring para o meu caso que vai ser somente jdbc ?
agodinho
Isso não é competição. É minha opinião.
Antes de mandar uma frase dessa pense bem.
Cara, pode-se fazer um prédio com palitos e outro com tijolos não é mesmo???
Mesmo no prédio com tijolos depende-se muito da mão de obra …
Não acredito em desenvolvedor estrela, acredito em equipe. Para projetos grandes vc tem de pensar no melhor pra equpe (ou fábrica).
jdbc puro, isso é fato, aumenta a quantidade de código consideravelmente …
quanto maior a quantidade de código maior o esforço na manutenção.
agodinho
Cara, acho que vc ainda pode tirar proveito do iBatis. Vou tentar com o exemplo de código que vc mandou (estilo call exec).
Posto aqui e depois vc vê se te atende ou se vc gosta.
Até o final da madruga eu posto algo aqui (positivo ou negativo).
W
WilliamSilva
O iBatis ajuda exatamente nisso. Todos seus sqls ficarão em arquivos XMLs simples. Vc ainda terá uma camada de persistência (DAO) mas sua camada não fala jdbc. Ela simplismente delega isso pro ibatis.
O iBatis ajuda exatamente nisso. Todos seus sqls ficarão em arquivos XMLs simples. Vc ainda terá uma camada de persistência (DAO) mas sua camada não fala jdbc. Ela simplismente delega isso pro ibatis.
Verdade, o iBatisDAO foi descontinuado por ser redundante. O iBatisDAO é uma outra bibilioteca que ficava acima do sqlMaps que mencionei. O iBatis é hoje apenas o sqlMap. Pelo que lembro o iBatisDAO era nada mais nada menos que o quê o spring faz com os templates de DAO, daí então a galera do iBatis achou melhor descontinuar.
O exemplo de código que postei (código de produção) usa apenas o ibatis.
Nunca usei o iBatis com o spring. Mas fico meio ressabiado só de pensar numa aplicação orientada à banco com ioc.
Quando disse camada DAO tinha em mente uma camada DAO java mesmo (vide código).
W
WilliamSilva
Nunca usei o iBatis com o spring. Mas fico meio ressabiado só de pensar numa aplicação orientada à banco com ioc.
Pode explicar pq. vc. ficaria ressabiado por usar o spring Dao
Pode ser bobeira minha, tento sempre partir pro mais simples quando se trata de trabalhar com aplicações orientadas à banco, essas velharias sempre me pegam desprevinido. Me sinto como se estivesse tentando socar um triângulo dentro de um quadrado …
Olha só o caso desse post, tô pensando até em abrir outro post só pra ver a opinião da galera sobre esse lance de atualizar sequence dentro de trigger e tal …
Tem tudo a ver com minha assinatura não tem não?
Me pergunto o seguinte: pra quê que eu preciso de uma factory de beans para uma camada DAO que está usando iBatis? Mesmo no caso simples de utilizar um DAO Factory com iBatis, na minha opinião, isso já seria redundante. Teria de criar interfaces para DAOs que não teriam variação de código simplesmente porque a porção que poderia vir a variar (os sqls em si) já está fora desses DAOs.
Dependendo da abordagem isso é uma discussão sem fim.
Seria tão mais fácil se tudo nessa área fosse ou preto ou branco não acha?
Vou dar uma olhada no material que vc linkou, mas te adianto que, na minha opinião, nem sempre vale a pena abstrair bases legadas para um novo sistema oo. Sei que isso é uma simplificação absurda mas na correria do dia a dia é o que eu acabo fazendo.
Agora te pergunto: vc acha que sempre vale a pena usar essa abordagem quando estamos desenvolvendo um novo sistema com uma base legada? uma base que vc não pode alterar ?
Obrigado pelos links …
ainda estou devendo o exemplo com a trigger no iBatis …