• Like
  • Save
Curso struts e hibernate
Upcoming SlideShare
Loading in...5
×
 

Curso struts e hibernate

on

  • 1,247 views

 

Statistics

Views

Total Views
1,247
Views on SlideShare
1,247
Embed Views
0

Actions

Likes
1
Downloads
67
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Curso struts e hibernate Curso struts e hibernate Document Transcript

    • Versão 2.0 – Março - 2009Revisada por Mauro de Souza Guimarães
    • _____________________Curso Struts & Hibernate______________ EMENTA DO CURSO Ítem Descrição Página 1 Afinal: O que é o Struts e para que serve? 3 2 O padrão de arquitetura M-V-C (Model – View – Controller). Uma rápida revisão. 4 3 O mecanismo do M-V-C em uma aplicação Web 5 4 O mecanismo do M-V-C em uma aplicação Web, com o STRUTS. 6 CONFIGURAÇÃO DO AMBIENTE DE DESENVOLVIMENTO 5 Configuração do Ambiente com o Eclipse 3.x e TomCat 5.x 7 5.1 Instalando o conteiner Web TomCat 7 5.2 Instalando a IDE Eclipse 3.2 7 5.3 Plugando o Eclipse (Plugin do TomCat para o Eclipse 3.x) 8 5.4 Plugin Struts Console 8 6 Criando um projeto Tomcat com Sysdeo 11 7 Adicionando o Struts ao seu projeto 13 8 Rodando o primeiro projeto: logon (struts-blank.war) 15 SOBRE O STRUTS 9 Agora, os detalhes do mecanismo... 16 10 Analisando a aplicação "Register" para entender a função do struts-config.xml 16 11 Descrevendo os componentes envolvidos na aplicação web-struts "Register" 18 12 Parte do Arquivo struts 20 13 Descrição do ocorrido 21 14 Todos os componentes em detalhes 21 14.1 O arquivo descritor de distribuição, web.xml 23 15 O arquivo de recursos da Aplicação e Internacionalização (I18N) 24 16 Como copiar com os ActionForms 25 17 Declarando os ActionForms dentro do struts-config.xml 26 17.1 Jakarta Commons - BeanUtils 27 17.2 Como ligar com os ActionForwards 28 17.3 Como construir com os ActionMappings 29 17.4 Como trabalhar com objetos Action 30 18 Como exibir conteúdo dinâmico - TagLibs 33 18.1 Instalando as extensões da tag do Struts 33 19 Jakarta Struts Framework - Multiplos Arquivos de Configuração 37 20 Tiles Framework – Gerenciamento de Layouts 37 20.1 Habilitando o Tiles Framework 38 20.2 Usando o Tiles Framework 39 20.3 Definindo a página de layout 41 21 Jakarta Struts Framework – Validator 43 22 Request Processor 48 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 2 de 140
    • _____________________Curso Struts & Hibernate______________1. Afinal: O que é o Struts e para que serve? O Struts é um projeto "open-source" criado pelo consórcio Jakarta e tem como objetivo principal oferecerfacilidade de desenvolvimento de aplicativos Web com padrão Java Enterprise Edition (JEE). Oferece uma sériede serviços de infra-estrutura, tais como: Controle de fluxo de requisições HTTP; Internacionalização; Formulários; Validação; Criação de elementos html. Sendo o Struts considerado um "framework de desenvolvimento", o que o diferencia de uma APIconvencional, conhecida como "Biblioteca de classes"? Com uma API ou biblioteca de classes, você simplesmente utiliza fazendo chamadas às suas classes einterfaces. Em um framework de desenvolvimento, além da utilização de classes e interfaces, você também podeestender suas funcionalidades e alterar comportamentos. Tudo isso é possível através de um modelo de trabalhoconhecido como "Framework". Um framework tipicamente oferece serviços técnicos “automatizáveis”, como por exemplo: Persistência de dados em bancos SQL; Log de aplicativos; E no caso do Struts, aplicativos Web MVC de alta qualidade. A utilização dos serviços oferecidos pelo framework é feita através da extensão de classes,implementação deinterfaces, utilização de Tag Libraries (quando Web) e criação de documentos de configuração, tipicamente XML. Concluindo Com a utilização do Framework Struts, o desenvolvedor pode se beneficiar de uma série de "facilidades"que o framework oferece e se concentrar na "Lógica do Negócio", aproveitando os serviços de infraestrutura e dosserviócs técnicos especializados descritos acima. Se o desenvolvedor tivesse que se preocupar com todas asquestões de segurança, validação, tratamento de formulários, fluxo de requisições e ainda, a lógica do negócio,muito tempo e esforço seria dispendido. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 3 de 140
    • _____________________Curso Struts & Hibernate______________2. O padrão de arquitetura M-V-C (Model – View – Controller). Uma rápidarevisão. O padrão de arquitetura M.V.C. é o mais utilizado atualmente para soluções Web JEE e está presente nasprincipais soluções JEE de grandes empresas. Este padrão determina a divisão do aplicativo em três principaispartes: Model: representa as entidades, operações e lógica do negócio; View: representa visualizações utilizadas pelos usuários para interagir com os dados e processamento; Controller: representa a camada que recepciona as requisições, aciona o modelo e responde para o usuário através do despacho para uma view. Sem dúvida alguma, podemos afirmar que as aplicações desenvolvidas utilizando o padrão MVC sãocapazes de crescer sem qualquer dificuldade. A complexidade, ou o que chamamos de responsabilidade decomponentes, é dividida de maneira mais inteligente, propiciando fraco acoplamento entre camadas, garantindoaodesenvolvedor e ao projeto maior flexibilidade para mudanças na arquitetura do software. O Struts aplica fortemente o padrão MVC sob a arquitetura JEE, o que faz com que ele tenha grandecredibilidade e flexibilidade para desenvolvimento de aplicações Web em Java. Veja no diagrama abaixo, orelacionamento entre as camadas. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 4 de 140
    • _____________________Curso Struts & Hibernate______________3. O mecanismo do M-V-C em uma aplicação WebFunciona assim:A IDA...VIEW Um usuário digita uma URL, no browser. A página é localizada em um Servidor web, e este devolve para obrowser uma página que é, por exemplo, um formulário. Esta página , o formulário, representa a camada deinterface com o usuário: a camada View (visão). Ela interage com o usuário tanto na entrada, isto é, no momentoque o usuário está preenchendo um cadastro, ou acionando um Hiperlink dentro de um site de compras, quanto nasaída, isto é, quando o aplicativo apresenta uma outra tela com uma mensagem ou outra página com formulário.CONTROLLER Lembra do formulário preenchido pelo usuário , no texto anterior? Pois bem, este formulário é enviadopara o Servidor Web, através do protocolo HTTP, junto com um objeto "Request" , que leva junto todos os camposdo formulário preenchidos pelo usuário. Estes campos são apresentados a um "servlet" desenvolvido com amissão de "descascar" os dados fornecidos pelo usuário na outra ponta da Web (browser cliente) além deidentificar "o que" o usuário quer com estes dados: Incluir ? Listar ? Excluir ? Filtrar ? Calcular ?. Este "Servlet" ,além de "pegar" os dados, tem que identifica que "regra de negócio" tem que acionar para estes dados"coletados". Dependendo de qual regra seja, este "Servlet" deve acionar as classes Java que foram desenvolvidaspara atender ao negócio. Este "servlet" está agindo como um Controlador (Controller). Esta é a camada deControle.MODEL A classe de negócio, acionada pelo Controlador, é uma classe especializada para exercer a função para aqual ela foi escrita. Por exemplo, para o formulário enviado pelo usuário na camada de apresentação e cujosdados foram "coletados" na camada de Controle, a camada de Modelo é onde estas classes de negócios "atuam".Elas executam suas tarefas, podendo acessar os dados que estão guardados em "Banco de Dados", efetuarcálculos...E A VOLTA....MODEL A classe de negócios aí de cima, ao terminar sua tarefa, prepara os dados para serem enviados peloControlador ao usuário que está esperando de frente para o Browser. Sendo assim , ao terminar suas atividades,a classe de negócio "avisa" ao Servlet controlador que os dados já estão preparados. Aí se encerra a atividade daclasse de negócio. A camada de Modelo (MODEL), fica esperando a próxima demanda.CONTROLLER O Servlet Controlador, na camada de Controle, ao ser avisado pela camada de Modelo, através da classede negócio, que existem "dados" prontos para serem exibidos ao usuário, aciona uma página JSP (por exemplo)que preenche e formata os dados para serem enviados ao Browser do cliente. Pronto. Agora que a página JSP jáestá carregada com dados "novinhos" e formatados, a envia para o Browser do cliente, onde ele estáaflito,esperando..VIEW O usuário recebe os dados formatados, através de uma página JSP, e os apresenta no Browser. O processo pode se repetir, indefinidamente..... Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 5 de 140
    • _____________________Curso Struts & Hibernate______________4. O mecanismo do M-V-C em uma aplicação Web, com oSTRUTS. Veja o diagrama abaixo: Jakarta Struts Framework – Modelo MVC 3Na figura acima, estão representadas as 3 camadas: Model – View – Controller. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 6 de 140
    • _____________________Curso Struts & Hibernate______________O mecanismo, agora, é o seguinte: O cliente preenche o Formulário no Browser (repare a figura do LapTop onde está escrito Client Browser). Ao acionar o botão de “Submit”, um objeto "Request" (HTTPRequest = a solicitação com os dados do formulário) é enviado para o Servlet Controlador na camada de Controle, representado pela classe “ActionServlet”. O objeto “Request” leva os parâmetros do formulário, digitados pelo usuário. O “ActionServlet” preenche automáticamente, uma classe chamada de "ActionForm", que é um JavaBean, carregando os dados do formulário de entrada. Desta forma, os dados de entrada ficarão disponíveis para as outras camadas do aplicativo, dentro do JavaBeans. Baseado em algumas informações, o “ActionServlet” (Servlet Controlador) decide qual classe de negócio será acionada. Estas classes serão acionadas por uma classe especial chamada de "Action" que representa a lógica do negócio. Esta classe implementará, de certa forma, a Regra de Negócio. Esta classe obterá da classe "ActionForm" (o JavaBean) os parâmetros do formulário inicial da camada de Apresentação. Ao final do processamento, a classe "Action" prepara a saída, indicando uma página JSP da camada de Visão, preenchedo-a com os dados resultantes da lógica do negócio. Um outro objeto chamado de "ActionForward" indica qual a página JSP será chamada para apresentar o resultado para o usuário.5. Configuração do Ambiente com o Eclipse 3.x e TomCat 5.x5.1. Instalando o conteiner Web Tomcat 1. Obtenha a instalação do Tomcat através do site tomcat.apache.org. Quando da elaboração deste material, a versão disponível era a 5.5.16 (apache-tomcat-5.5.16.zip) 2. A instalação do Tomcat também é extremamente simples. Basta descompactar o arquivo zip no diretório raiz, ou em uma pasta de uma das unidades de disco disponíveis, mantendo a estrutura de pastas. 3. Criar uma variável de ambiente CATALINA_HOME, apontando para o diretório que foi criado com a descompactação do pacote Tomcat.5.2. Instalando o Eclipse (Esta parte pode variar, dependendo da versão do Eclipse) 1. Obtenha a instalação do eclipse através do site www.eclipse.org/downloads. Quando da elaboração deste material, a versão disponível era a 3.0 (eclipse-SDK-3.0-win32.zip) 2. A instalação do eclipse é extremamente simples. Basta descompactar o arquivo zip no diretório raiz, ou em uma pasta de uma das unidades de disco disponíveis, por exemplo , o drive C: ou D:, tanto faz. Veja a figura: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 7 de 140
    • _____________________Curso Struts & Hibernate______________ Notar que a estrutura de diretórios deve ser mantida, portanto, a opção “Use folder names” deve ser mantida checada. 3. Será criado o diretório "/eclipse" no qual você irá encontrar o executável eclipse.exe para iniciar o mesmo. 4. Para iniciar o eclipse, dependendo da sua versão, é apresentada uma sugestão para onde deverá ser instalado o Eclipse, como mostra a figura abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 8 de 140
    • _____________________Curso Struts & Hibernate______________ 5. Nós iremos utilizar o padrão de diretórios que o Eclipse utiliza, isto é, sugerindo a instalação em “C:eclipseworkspace”, que é padrão. O eclipse cria de forma automática uma pasta para armazenar todos os projetos criados (uma workspace) opte pela pasta default marcando o checkbox correspondente e clicando no botão OK Em outros momentos, o programador poderá escolher um diretório que seja mais prático, dependendo de seu projeto. 6. Após a instalação, a estrutura de diretórios que se apresenta é a descrita na figura abaixo: 7. A tela inicial do eclipse será apresentada. Plugin "Struts Console"O Struts Console é um aplicativo que lhe permite editar de maneira visual o arquivo de configuração struts-config.xml. Ele funciona como uma aplicação stand-alone (isolado, podendo ser executado isoladamente) ouintegrado ao Eclipse como um plugin. 1. Para instalar o aplicativo Struts Console, descompacte o arquivo"struts-console-4.8.zip", que vem no CD do aluno. Será criado um diretório parecido com o abaixo: Para rodar a aplicação fora do Eclipse, basta ir ao diretório "bin", e rodar o arquivo "console.bat" quedeverá apresentar a seguinte tela: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 9 de 140
    • _____________________Curso Struts & Hibernate______________ Conforme dito anteriormente, o "Struts Console" é um editor do arquivo struts-config.xml". Para que ele funcione o aluno deve acionar o "struts-config.xml", onde irá aparecer a seguinte tela: Para instalar o plugin no eclipse basta copiar o diretório "com.jamesholmes.console.struts" no diretório"eclipseplugins" e reiniciar o eclipse. A partir daí, toda vez que o arquivo "struts-config.xml" for clicado dentroda aba “Package Explorer” do eclipse, será aberta uma tela do Struts Console, conforme ilustrado anteriormente. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 10 de 140
    • _____________________Curso Struts & Hibernate______________6. Criando um projeto no Tomcat 1. Agora o programador irá criar o ambiente do Projeto. Para isto vai selecionar as opções "File" > "New" >"Project". Depois escolha “Tomcat Project” para criar uma estrutura já apropriada para aplicações Web, conformeas figuras abaixo:2. Em seguida, o Eclipse apresentará uma tela solicitando o nome do projeto. O aluno preenche e clica no botão"Next". Observe que o botão que se apresenta indicado é o botão "Finish". MAS O ALUNO DEVE CLICARNO BOTÃO "NEXT".3. Depois de informar o nome do projeto, deixe o nome do contexto (o nome que vem depois da porta 8080 naURL digitada no browser) como o nome do projeto; deixe selecionada a opção “Can update server.xml file” , e naopção “Subdirectory to set as web application root”, informe "/web", conforme figura abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 11 de 140
    • _____________________Curso Struts & Hibernate______________4.Estas ações irão criar um projeto com as devidas bibliotecas "servlet/jsp" provenientes do tomcat e irá criar umdiretório "src" para o código fonte, além de criar um diretório "web" para a raiz do seu web site.Ao final , o seu projeto no eclipse deverá se parecer conforme a figura abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 12 de 140
    • _____________________Curso Struts & Hibernate______________7. Adicionando o Struts ao seu projeto O pacote "struts-1.2.8.zip" fornecido no CD do aluno contém diversas aplicações web J2EE compatíveis(arquivos com extensão.war), contidas na pasta "webapps". Uma delas é o struts-blank.war, que é uma aplicaçãoem branco, com todas as configurações necessárias para rodar o struts em uma aplicação web. O Struts-Blank é distribuido como um arquivo do tipo WAR (Web Archive). Para iniciar a aplicação, tudo oque o aluno precisará fazer é: 1) Copiar o arquivo "Struts-Blank.war" da pasta "webapps" do diretório struts-1.2.8 , criado com adescompactação do arquivo struts-1.2.8.zip, fornecido no CD do aluno, para um local qualquer. 2) Um arquivo com extensão "war" pode ser lido com o "Winzip". Para isto, basta associar a extensão dearquivo "war" ao aplicativo "WinZip". 3) Após isto, dê dois cliques no arquivo "Struts-Blank.war" . O "WinZip" abrirá uma janela. O aluno deverásolicitar que o "WinZip" descompacte o "Struts-Blank.war" dentro do diretório "web" do Projeto recém criado noEclipse (projeto "logon" página 10), podendo sobrescrever os arquivos pré-existentes. Logo em seguida você devedar “refresh” na estrutura do seu projeto, o qual deverá agora parecer com a figura abaixo: Logo em seguida você pode remover alguns arquivos e diretórios que não serão necessários nesse ambiente Eclipse: /bin /src /web/WEB-INF/src/build.xml /web/WEB-INF/src/README.txt /web/WEB-INF/META-INF O arquivo MessageResources.properties deve ser movido do diretorio /web/WEB-INF/src/java para /web/WEB-INF/src , o subdiretório java poderá ser eliminado logo em seguida.Para finalizar, a biblioteca principal do Struts, o arquivo "struts.jar", contido no diretório "/web/WEB-INF/lib" deveficar no classpath do seu projeto, para tal, clique com o botão direito no nome do seu projeto (nó), e selecione“Properties/Java Build Path/Libraries/Add Jars…”, e selecione o arquivo struts.jar contido no diretório /web/WEB-INF/lib , conforme figura abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 13 de 140
    • _____________________Curso Struts & Hibernate______________ Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 14 de 140
    • _____________________Curso Struts & Hibernate______________8. Rodando o primeiro projeto: hello O aluno poderá iniciar a execução do Tomcat, de dentro do próprio Eclipse, acionando a figura do gato que está mais à esquerda: O Eclipse irá carregar o Tomcat e o aluno poderá perceber isto, no final numa tela de “console”, como ilustrado abaixo. Quando o aluno perceber a mensagem “INFO: Server startup in 11187 ms” ele saberá que o Tomcat está carregado e pronto para ser utilizado. Para ter certeza de que o servidor de Aplicação Web Tomcat está carregado e funcionando, o usuário deverá carregar o Browser e digitar a URL (*): http://localhost:8080/hello Se tudo estiver correto, a seguinte mensagem aparecerá na tela de seu browser: Welcome! To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your containers "webapp" folder (or equivalent), and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container, and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.) Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 15 de 140
    • _____________________Curso Struts & Hibernate______________9. Agora, os detalhes do mecanismo... O Framework Struts inaugura o conceito de “Programação Declarativa", isto é, muitas informaçõesimportantes são fornecidas sob a forma de tags XML, ao invés de criar classes de programas. O arquivo “struts-config.xml” possui estas informações, como veremos adiante. O “coração” do FrameWork Struts , são o ActionServlet e arquivo de configuração “struts-config.xml”. Esteúltimo contém várias informações importantes e que determinam como o aplicativo se comporta e é consultadopelo "ActionServlet" assim que ele for carregado. Lembrando que todo Servlet, tem que residir em um conteiner, como o TomCat. Assim que o conteiner éinicializado (TomCat) ele primeiro lê o descritor de distribuição, o arquivo web.xml que informa quais Servletsdevem ser carregados pelo conteiner. Desta forma, o "ActionServlet" é carregado automáticamente e fica namemória esperando por alguma URL que acione o mecanismo. O arquivo web.xml deve indicar que o"ActionServlet" será carregado. Isto é feito com o seguinte código : <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-mapping> </servlet-mapping> Desta forma, quando um usuário digitar qualquer caminho que termine em ".do" (que é mais utilizado pela comunidade Struts), a solicitação (Request) com todos os dados preenchidos pelo usuário será enviado para o "ActionServlet". Quando um "ActionServlet" recebe uma solicitação, várias ações ocorrem até que um resultado seja apresentado para o usuário, na "volta" do processo. O "ActionServlet" é um Servlet. Ele não aparece no classpath da aplicação. Ele fica dentro do arquivo struts.jar, este sim, referenciado no classpath da aplicação. Importante !! O "ActionServlet" , ao ser acionado, lê o arquivo struts-config.xml. Este arquivo contém diversas tags e parâmetros que vão determinar como a aplicação vai se comportar. A seguir, iremos detalhar os principais componentes do arquivo struts-config.xml.10. Analisando a aplicação "Register" para entender a função do struts-config.xml Vamos examinar a aplicação "Register", fornecida no CD do aluno, para que possamos compreenderdefinitivamente, todo o processo que envolve desenvolver uma aplicação web, baseada no framework Struts. O usuário digita: http://localhost:8080/register/Register.jsp A tela seguinte será apresentada ao aluno. O aluno fornece um nome de usuário e uma senha. Depois ousuário confirma a senha. Ao final do processo, aciona o botão "OK", que é o botão de "Submit". Não seesqueçam que exite uma ação associada ao botão de "Submit" (botão "ok" na figura) Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 16 de 140
    • _____________________Curso Struts & Hibernate______________ Struts User Registration Username: Password: Confirm: ok figura 12.1 página "register.jsp" Ao pressionar o botão "ok", o padrão "register.do" é enviado para o Servlet. Este envio é feito pelacláusula <form action="register.do"> que está presente no arquivo "Register.jsp". O Servlet "ActionServlet" procura no arquivo "struts-config.xml" dentro da tag <action-mappings> por umatag <action> que possua uma cláusula "path" que possua a palavra "/register", que coincida com a palavra indicada na tagaction do arquivo Register.jsp. Não há a necessidade de se escrever no arquivo struts-config.xml, a palavra "register.do",podendo ser desprezado o final ".do". Bom, tudo começa quando o Servlet encontra (no struts-config.xml ), uma tag <action> com a cláusula "path =/register" conforme pedaço do código destacado abaixo(parte do struts-config.xml) O usuário digita um nome e depois preenche o campo senha. Após isto, deve re-digitar a senha. Caso asenha esteja digitada de forma correta a seguinte mensagem aparece: Registration Succeeded! Try Another? Se a senha for digitada de forma errada, esta outra mensagem aparece: Registration failed! Try Again? O que ocorreu entre o aparecimento da página do formulário e a página com uma das mensagens? Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 17 de 140
    • _____________________Curso Struts & Hibernate______________11. Descrevendo os componentes envolvidos na aplicação web-struts"Register" Para funcionar, e de forma resumida (mais à frente complicaremos mais um pouco) , serão necessárioscriar os seguintes componentes: Um ActionForm; Um Action; O arquivo struts-config.xml; 3 (três) páginas html (register.jsp; sucess.htm e failure.htm).ActionForm O ActionForm é um JavaBean que guardará os parâmetros fornecidos no formulário "register.jsp" quesão o "nome do usuário", "senha_1" e "Senha_2". É comum, dar-se o nome da aplicação, com o sufixo "Form"para um ActionForm. Então , o nosso primeiro "ActionForm" se chamará "RegisterForm". Ele será uma classejava, um JavaBean para ser mais exato. Esta classe, deve "estender" a classe org.apache.struts.ActionForm ecomo já explicamos antes, este objeto captura os parâmetros do formulário trazido pelo Request. Para funcionarcorretamente, é necessário que o RegisterForm possua as variáveis de instância coincidindo com os nomes doscampos do formulário de entrada, juntamente com os métodos getters e setters.Este é o código da classe RegisterForm , o ActionForm da aplicação: package app; import org.apache.struts.action.ActionForm; public class RegisterForm extends ActionForm { protected String username; protected String password1; protected String password2; public String getPassword1() { return password1; } public void setPassword1(String password1) { this.password1 = password1; } public String getPassword2() { return password2; } public void setPassword2(String password2) { this.password2 = password2; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 18 de 140
    • _____________________Curso Struts & Hibernate______________Action Um Action é uma classe java que extende org.jakarta.struts.Action. Após o ActionServlet, preencher oActionForm (RegisterForm no nosso aplicativo) ele aciona um Action, entregando para ele o ActionFormpreenchido, para que ele, Action, valide os campos do ActionForm, depois decida quais outras informações denegócios serão recuperadas/criadas/alteradas e no final do processamento, a classe Action retorna um outroobjeto chamado "ActionForward" (que indica um "caminho" de um recurso, podendo ser uma página JSP deresposta, por exemplo) deve ser retornado ao ActionServlet. É comum, dar-se o nome da aplicação, com o sufixo"Action" para um Action. Então , o nosso primeiro "Action" se chamará "RegisterAction". Observar na listagem do Action que ele possui um método chamado execute( ...) que recebe referênciade vários objetos como ActionMapping, ActionForm, HttpServeltRequest e HttpServletResponse). Este método é ocoração do Action e ao final de sua execução, ele deve retornar um objeto "ActionForward".Este é o código da classe RegisterAction o Action da aplicação: package app; import javax.servlet.http.*; import org.apache.struts.action.*; public class RegisterAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //Faça um cast para o form bean que voce criou RegisterForm registerForm = (RegisterForm)form; //Aplicar a regra do negocio if (registerForm.getPassword1().equals(registerForm.getPassword2())) { //Retorne um ActionForward no caso de sucesso return mapping.findForward("success"); } else { //Retorne um ActionForward no caso de falha return mapping.findForward("failure"); } } } Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 19 de 140
    • _____________________Curso Struts & Hibernate______________12. Parte do arquivo struts-config.xml, com as tags <action-mappings> e <action> <!-- Action Mapping Definitions --> <action-mappings> <action path="/register" type="app.RegisterAction" name="registerForm" validate="true" scope="request" input="/register.jsp"> <forward name="success" path="/success.html" redirect="false" /> <forward name="failure" path="/failure.html" redirect="false" /> </action>Explicando o mecanismo, as tags e parâmetros: O arquivo struts-config.xml contém detalhes que o ActionServlet precisa saber para lidar com o Request(solicitação) feitas à aplicação, via formulário de entrada (register.jsp)<action path=“/register” = este é o caminho lógico da ação. No comando action do HTML do formulário de entrada, deverá estar declarado um "register.do". O ActionServlet procurará no “struts-config” por uma entrada “action” de um register, sem o “.do”.type=“app.RegisterAction” = é o nome da classe Action que será acionada pelo Servlet e processará o objeto “Request” enviado. "app" é o nome do pacote onde a classe RegisterAction se encontraname=”registerForm” = nome do ActionForm (JavaBean) que estará associado ao aplicativo. O ActionForm é a classe de mapeamento do formulário, isto é, todos os dados do formulário de entrada que possuem variáveis de mesmo nome no JavaBean, serão copiados para as variáveis automáticamente.validate="true" = esta cláusula indica que o método validate ( ) do ActionForm será chamado após o ActionForm ser preenchido com os dados do request (solicitação do usuário). Este método é usado como validação superficial e retorna um objeto ActionErros no caso de existir algum. Este objeto será gravado no contexto da solicitação.scope="request" = O identificador do escopo (solicitação ou sessão) dentro do qual o Form (actionForm) associado a este mapeamento, vai ser criado. Neste exemplo, o registerForm.input=“/Register.jsp”> = no caso de um erro de validação, esta é a página que será apresentada ao usuário. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 20 de 140
    • _____________________Curso Struts & Hibernate______________<forward name=“sucess” path=“/sucess.htm”/> = No caso da variável “target” do código acima ser igual a “sucess”, indica a página que será apresentada ao usuário.<forward name=“failure” path=“/failure.htm”/> = No caso da variávél “target” do código acima ser igual a “failure”, indica a página que será apresentada ao usuário.13. Descrição do ocorrido Quando o usuário "aponta" o browser web para http://localhost:8080/register/Register.jsp,o conteiner TomCat se apresenta para receber como sempre faz com qualquer página JSP. As tags HTML dapágina Register.jsp, são devolvidas ao Browser, o que produz a tela da página 19. O usuário fornece um nome e duas senhas. Após isto, o usuário clica no botão "Ok". O browser envia o conteúdo do formulário (nome e duas senhas) como uma solicitação http, que atinge oServidor. O TomCat sabe através da leitura do arquivo "web.xml" que, pelo padrão ".do" ele deve entregar estesdados para um ActionServlet, mais específicamente o "RegisterAction". Esta solicitação (request) é entãoprocessada pelo "RegisterAction". O "RegisterAction" lê o arquivo struts-config.xml procurando por uma tag <action> que possua acláusula "path" coincidindo com o padrão register.do como indicado no arquivo Register.jsp. Mas procura apenaspor "/register" não procurando pelo ".do" Ao achar a tag <action>, o Servlet procura a cláusula "name" que aponta para o ActionForm (JavaBean)que receberá os parâmetros do formulário de entrada. O ActionForm é o "RegisterForm". Ao terminar de preencher o RegisterForm com os dados da entrada, o Servlet "ActionServlet" passa ocontrole da execução para a classe Action, indicada na cláusula "type" dentro da tag <action> " e disponibiliza oJavaBean (RegisterForm) para esta classe. No exemplo, é a classe "RegisterAction. O método execute( ) desta classe é executado e ao final este método devolve um objeto do tipo"ActionForward", fazendo uma referência ao nome "lógico" dele. Este nome "lógico" do ActionForward estátambém registrado dentro do arquivo struts-config.xml e , lá, aponta para um arquivo "html" ou outro "Action". Caso algum erro seja encontrado durante o processo, a cláusula "input" indica qual página a serchamada. No exemplo, a cláusula input aponta para “/Register.jsp”, indicando que chama novamente oformulário de entrada.14. Todos os componentes em detalhes 14.1 O arquivo descritor da distribuição, web.xml. Como já vimos, o centro do framework é o ActionServlet, que é usado como Controlador. Geralmenteeste arquivo não é alterado e muitas configurações de que este arquivo precisa , é feito via o arquivo web.xml. Básicamente, existem dois componentes que precisam ser configurados via o web.xml: o ActionServlet eas bibliotecas de tags do Struts. Vamos apresentar o código de um arquivo web.xml com algumas considerações. Veja na página seguinte,o arquivo web.xml da aplicação "Register". Observe que existe um cabeçalho inicial que identificam o arquivo como um descritor de distribuição <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 21 de 140
    • _____________________Curso Struts & Hibernate______________ Em seguida, dentro da tag <web-app> e </web-app> , exite toda a configuração do arquivo. Dentro da tag<servlet> </servlet>, dá-se a configuração do Action Servlet <web-app> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> A próxima sessão, é utilizada para identificar as solicitações do struts, isto é, qual a forma que asolicitação deve ser feita para que o Servlet seja acionado: <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> A tag <servlet-mapping> indica que toda solicitação (request) que for chamada com o final ".do" servirápara acionar o ActionServlet, devido ao padrão "*.do" Para que a aplicação chame automáticamente o arquivo "register.jsp", devemos indicá-lo com a tag<welcome-file-list> , conforme apresentado abaixo: <welcome-file-list> <welcome-file>register.jsp</welcome-file> </welcome-file-list> A fim de se poder usar as bibliotecas de tags do Struts, assunto que abordaremos mais à frente, énecessário que que as configuremos aqui. Exitem 3 bibliotecas de tags do Struts, básicas: bean, html e logic.Estas serão utilizadas pela maioria das aplicações, e em muitos casos substituirão completamente as tagas html efacilitarão outras ações. Se outras bibliotecas de tags fossem utilizadas pela aplicação, estas seriam configuradas neste mesmolocal, como tiles ( outro assunto mais adiante), conforme o código abaixo: <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>interplan@interplan.com.br site: www.interplan.com.br email: </taglib> site: www.ensina.com.br email: treinamento@interplan.com.br </web-app> Página 22 de 140
    • _____________________Curso Struts & Hibernate______________14.2. Agora o "web.xml" completo: <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <display-name>Struts Blank Application</display-name> <!-- Standard Action Servlet Configuration (with debugging) --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Standard Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- The Usual Welcome File List --> <welcome-file-list> <welcome-file>register.jsp</welcome-file> </welcome-file-list> <!—Descritores da Biblioteca de Tags do Struts --> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location> </taglib> </web-app> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 23 de 140
    • _____________________Curso Struts & Hibernate______________15. O arquivo de recursos da Aplicação e Internacionalização(I18N) O Struts possui um sistema de mensagem muito flexível. Se o programador precisar desenvolver um sitecom mensagens em várias línguas , utilizará este arquivo de recursos para, fácil e rápidamente criar váriasversões de mensagens e labels, uma para cada língua desejada. A isto chama-se "Internacionalização" da aplicação ou "Localização" da aplicação. O mecanismo deinternacionalização é o que garante que uma aplicação irá apresentar-se no idioma local do usuário. O Struts utiliza arquivos de propriedades para armazenamento de mensagens em diferentes idiomas. O arquivo de mensagem , geralmente fica localizado em qualquer lugar debaixo do diretório WEB-INF.Muitos programadores o colocam dentro de WEB-INF/classes, dentro de um pacote , que é um diretório. O "pacote" pode se chamar "resources". Dentro deste pacote, existirão os arquivos "properties"(java.util.Properties). Observar que o uso do pacote NÃO É OBRIGATÓRIO, podendo o arquivo de propriedades,MessageResources, ficar localizado na raiz do diretório WEB-INF. O uso do pacote serve para organização. O arquivo de propriedades que normalmente é utilizado pelos programadores Struts é oMessageResources.properties. Ele é um arquivo que pode ser editado por qualquer editor de texto (até oNotePad) e é constituído por um par de "chave-valor" em cada linha. No arquivo descritor de distribuição web.xml, utiliza-se a tag <init-param> para registrar o arquivo depropriedades e o pacote onde ele reside, conforme ilustrado abaixo: <init-param> <param-name>application</param-name> <param-value>resources.MessageResources</param-value> </init-param> Observe que na tag <param-value> estamos registrando o pacote resources antes do nome do arquivoMessageResources. Isto indica para o Struts que ele deverá buscar, debaixo do diretório/pacote "resources", um arquivoMessageResources.properties Para cada novo idioma deve ser criado um arquivo MessageResources_yy_XX.properties, onde yy é asigla da língua e XX, a sigla o País, por exemplo MessageResource_fr_FR.properties, informa que o conteúdo dasmensagens é da lingua francesa da FRANÇA, ou MessageResource_es_ES.properties , informa que o conteúdodas mensagens é da lingua espanhola da ESPANHA Também podemos informar no arquivo Struts-config.xml, que existe um arquivo de propriedades parainternacionalização, utilizando a tag <message-resources> . Desta forma: <message-resources parameter="resources.MessageResources" />Para atribuir qual a localização (java.util.Locale) atual do usuário à sua respectiva HttpSession, podemos inserir oseguinte código no método execute de um Action: this.setLocale(new java.util.Locale(“en”, “US”), request);O qual irá atribuir a linguagem e país do usuário para inglês dos Estados Unidos. A partir de então o usuário iráacessar o site nesta linguagem, caso o recurso exista. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 24 de 140
    • _____________________Curso Struts & Hibernate______________16. Como copiar com os ActionForms • ActionForms são JavaBeans utilizados para encapsular e validar os parâmetros do objeto "Request". • Para cada parâmetro do request que se deseja obter, será necessário criar métodos getters e setters. • Grande parte dos parâmetros de um formulário que é enviado para o Servidor, deve ser "validado", antes de ser submetido para o nível de negócio. Se um campo deve conter um número, será nosso trabalho garantir que de fato, este campo contenha um número, do contrário deveremos emitir um alerta de erro e não deixar o campo ser enviado ao Servidor. • Para realizar esta e outras tarefas, o framework Struts todas as entradas do formulário serão transferidas automáticamente para um componente do tipo ActionForm para que estas sejam validadas. • Após esta validação, estas entradas serão enviadas para o Action (uma classe de negócio, explicada mais adiante), dentro de um JavaBean preenchido e organizado, que é a classe ActionForm. • Para efetuar a validação dos campos, uma classe ActionForm disponibiliza outros dois métodos (além dos getters e setters) a serem sobrescritos: validate( ) e reset( ). • O método validate( ), serve para a validação do campos do formulário, antes de transmitir para o Action. • Observe que dentro deste método, um objeto “ActionErros” (com a letra “S” no final) é instanciado. • Objetos ActionErros são coleções de ActionErro (no singular). Este último são erros que podem acontecer. • Objetos ActionErros são HashMap que armazenarão um par “Chave x Valor”. • Este objeto será usado quando um Erro for encontrado durante a validação dos campos. • Encontrando um Erro, este será adicionado à HashMap, da seguinte forma: • A ”chave”, é o nome do campo que está sendo testado. • O “valor”, é uma instância de “ActionErro” cujo parâmetro será a descrição do erro. Esta e todas as descrições de erros que o aplicativo reportar estarão registradas no arquivo ApplicationResources . • O arquivo ApplicationResources fica armazenado no diretório WEB-INF da aplicação. • O método validate normalmente é utilizado para implementação de regras de validação dos dados informados nos campos do formulário. • O método reset( ), serve para a iniciar as propriedades do JavaBean (ActionForm), antes que ele seja preenchido com os valores vindo do formulário. Exemplo do método validate () que está inserido no ActionForm: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 25 de 140
    • _____________________Curso Struts & Hibernate______________ Observe no código abaixo: 1) O método retorna um objeto ActionErrors, que é uma coleção de objetos Error (linha 183) 2) Ao ser detectado o erro (linha 189), este será adicionado à coleção de erros (errors.add( ) ), passando o nome do campo (username) como chave da coleção de erros. O valor correspondente à chave, é a instância de uma classe "ActionMessage" (linha 190) com o valor que deve ser procurado no arquivo ApplicationMessage, que é por exemplo, "error.username.required". 17. Declarando os ActionForms dentro do struts-config.xml Para ser reconhecido pelos componentes do framework, os ActionForms (os JavaBeans vitaminados) precisam estar registrados dentro do arquivo de configuração struts-config. Isto é feito conforme exemplo abaixo: <form-beans> <!-- amostra de um descritor de um "form-bean" para um ActionForm --> <form-bean name="logonform" type="app.LogonForm"/> <!-- amostra de um descritor de um "form-bean" para um DynaActionForm --> <form-bean name="logonForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="username" type="java.lang.String"/> <form-property name="password" type="java.lang.String"/> </form-bean> </form-beans> Observe que a tag inicial é <form-beans> com "s" no final, indicando que a partir desta tag, colocaremos todos os beans da aplicação. Para cada elemento ActionForm da aplicação, inicamos uma tag <form-bean> no singular, conforme ilustrado acima. Observe que temos dois tipos de JavaBean: um ActionForm e um DynaActionForm. O primeiro, ActionForm, é um JavaBean, cujas propriedades são descritas na própria classe e o segundo, utiliza a declaração das propriedades no próprio arquivo struts-config.xml, como ilustrado acima. O programador deverá criar sua própria classe ActionForm, dando nome a ela e fazendo-a estender a classe ActionForm (org.apache.struts.action.ActionForm), como ilustrado abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 26 de 140
    • _____________________Curso Struts & Hibernate______________17.1 Jakarta Commons - BeanUtilsO Projeto Jakarta Commons • Projeto Open-Source da Apache Software Foundation • Conjunto de componentes reutilizáveis em Java • Componentes evoluídos, testados e seguros • Soluções para tarefas específicas • Estimula a padonização do código • O programador se concentra na regra do negócioCommons BeanUtils • Manipulação dinâmica de Beans • Clonar Beans • Obter propriedades dinamicamente • Copiar propriedades • Comparar/Classificar Beans Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 27 de 140
    • _____________________Curso Struts & Hibernate______________ Uma excelente maneira de colocar os dados ActionForm em outros JavaBean é usar a reflexão.Inicialmente, a refelexão tinha uma desvantagem no desempenho, mas cada versão da JVM, temreduzido isso. Você pode adcionar alguns métodos simples a uma classe de base ActionForm e facilitar atransferência dos dados para, e , a partir de qualquer outro componente usando a reflexão. Os métodossão apenas componentes em torno dos métodos da classe BeanUtils usados em outro lugar noframework. O ActionServlet usa BeanUtils para preencher os ActionForms a partir da solicitação http. O pacote Common BeanUtil, usado pelo Struts 1.1 , fornece uma conversão do tipo muito boa.Se vc estiver usando a reflexão para transferir seus próprios dados, recomendamos importar o pacoteCommons BeanUtil, independentemente de qual versão do Struts está usando (1.0 ou 1.1). O melhor método de transferência de dados completo é o BeanUtils.copyProperties. Eis como usar o copyProperties para preencher seu componente a partir de outro: BeanUtils.copyProperties(this, source);O método copyProperties, aplicará automáticamente qualquer String nas conversões do tipo nativo emqualquer direção. O novo copyProperties facilitará a "ida e volta" de seus ActionForms e doscomponentes de negócio: Veja o exemplo abaixo: BeanUtils.copyProperties (myBusinessBean, myActionForm); myBusinessOperation(myBusinessBean); BeanUtils.copyProperties(myActionForm, myBusinessBean);O código neste fragmento transfere as propriedades String em myActionForm para os tipos nativos emmyBusinessBeans, permite que a operação de negócio atualize os valores e então transfere os tiposnativos de volta para String myActionForm17.2 Como ligar com os ActionForwards O que eles fazem? • Muito bem depois da entrada pelo formulário ter sido passada para o ActionServlet e este chamar o Action entregando-lhe um ActionForm repleto de informações, o Action, poderá perguntar ao final de ter terminado sua tarefa com sucesso: "Tudo bem. A operação teve sucesso.E agora? O que devo fazer?" • Neste momento, o framework struts lança mão de um objeto ActionForward para indicar qual a página JSP ou que outro Action será utilizado para transferir o controle da aplicação. • Todas as JSPs que serão utilizadas como mecanismo de apresentação resultante do processamento de uma ou mais classes Action, deverão ser mapeadas no arquivo struts-config.xml, desta forma: A colocação da barra no início do path é fundamental! Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 28 de 140
    • _____________________Curso Struts & Hibernate______________ • Diferentemente do exemplo acima, é possível fazer com que o mapeamento da JSP esteja disponível para toda a aplicação, de forma GLOBAL. Isto é útil para páginas de "erro" e "login" por exemplo• A tag forward, vai fazer o redirecionamento “lógico” para as páginas da camada de “Apresentação”.• O parâmetro name, indica o nome Lógico.• O parâmetro path, indica o mapeamento Físico. Acompanhe no exemplo abaixo. Ele é um trecho do arquivo struts-config.xml. Nele podemos observar nalinha 141, um forward indicando que a página Welcome.jsp, no diretório "pages" referente ao contexto , deve serapresentada assim que o URI "logon.do" for aplicado pelo browser. Da mesma forma, na linha 143, podemosobservar uma tag <action cujo path é igual a "/logonsubmit", sugerindo que a URI aplicada pelo browser é"logonsubmit.do". Observe também outra forma de se apresentar o elemento Actionforward: na linha 149, ao voltar daexecução da classe de negócio LogonAction caso o método execute( ) do Action encaminhe de volta ao Servletpara procurar um ActionForward com o nome lógico de success, o fluxo de execução do programa será desviadopara outro Action : o welcome.do. O professor deve explicar que, dentro do struts-config.xml, deverá existir umaoutra tag <action> , cujo elemento path deverá ser igual a "/welcome"....17.3 Como construir com ActionMappings Um objeto do tipo ActionMapping (org.apache.struts.action.ActionMapping) está associado a um URI(identificador de um recurso no Servidor). Quando um usuário digita uma informação no browser ou clica numhyperlink que está associado a um padrão "*.do" do struts, o servlet (ActionSerlvet) vai ao arquivo struts-config.xml, para procurar um objeto do tipo ActionMapping (tag <action) cujo parâmetro path coincida com opadrão, sem o ".do" (como vimos anteriormente). Os objetos ActionMapping ficam catalogados dentro da tag <ActionMappings, que é uma coleção deActionMapping. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 29 de 140
    • _____________________Curso Struts & Hibernate______________ Já vimos na página 24 as principais propriedades dos objetos ActionMapping: path type name validate input scope forward action A história é a seguinte: O Servlet (ActionServlet) ao ser acionado, analisa o URI digitado ou fornecido pelobrowser e tem que carregar uma classe de negócio, que é uma classe Action (org.apache.struts.action.Action).Para esta classe Action, é fornecido (disponibilizado o acesso) um objeto ActionMapping, que fornece todas asinformações necessárias para o fluxo de execução da aplicação: Indica a classe Action a ser carregada pelo Servlet – através do parâmetro "type" Indica qual o JavaBean (classe FormAction) deve ser carregado – através do parâmetro "name" Indica se tem que fazer a validação dos campos do formulário – parâmetro validate = true. Indica qual classe chamar caso ocorra algum erro na validação – parâmetro "input" Indica o escopo (área que o servlet usa para trocas de informações) onde o formulário será criado.17.4 Como trabalhar com objetos Action Os objetos Action representam a força de uma aplicação Struts, e onde os desenvolvedores web passamgrande parte de seu tempo. As principais responsabilidades de um Action são: o Acessar a camada de negócio o Preparar os objetos de dados para a camada de apresentação o Lidar com os erros que apareçam nestas ações O ActionServlet, ao ser acionado (quando o container web for carregado, ele lê o arquivo web.xml queindica qual o servlet carregar, lembra?) analisa a URI digitada ou informada pela cláusula action do HTML quedeve indicar um nome com extensão “.do” , por exemplo, “Login.do” Ao receber esta solicitação, o ActionServlet, vai consultar o arquivo “struts-config.xml” para procurar umatag Action ( <action ) que tenha uma entrada /Login (sem o “.do”) como indicado no parâmetro "path". Na verdade, o programador vai escrever uma classe de negócio que estende uma classe Action,colocando o sufixo "Action" no nome da classe, como por exemplo, "LoginAction" ou "ProcessarPedidoAction". Istoé uma recomendação. As classes Action possuem um método execute (na versão struts 1.1) que deverá ser sobrescrita pelaimplementação da subclasse de Action. Abaixo um exemplo de uma classe Action que trabalha com HttpServlets: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 30 de 140
    • _____________________Curso Struts & Hibernate______________ import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import modelo.* import org.apache.struts.action.*; public class CadastroAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ServletContext appContext = request.getSession().getServletContext(); if (appContext.getAttribute("bairros")==null) { Collection bairros= Bairro.consultar(); appContext.setAttribute("bairros", bairros); } return mapping.findForward("sucesso"); } }Método execute (..) Observe que a classe CadastroAction, estende a classe Action e possui o método execute(...). Observe também que, os parâmetros do método execute são os objetos ActionMapping, ActionForm,HttpServletRequest e HttpServletResponse. Desta forma, a classe Action poderá dispor de todos estes objetospara trabalhar e obter os resultados da camada de negócio. Então, resumindo, o ActionServlet chama o Action, executando o método execute (...). O papel do Action é servir como uma espécie de "adaptador" entre os níveis da "web" e a camada denegócio. Para isto, o Action pode dispor do objeto ActionForm, que é passado como parâmetro. Lembrem-se deque o objeto ActionForm possuem os parâmetros do formulário e ficam desta forma, disponíveis para o Action.Separar as camadasIMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!!!! IMPORTANTE !!!!! É importante EVITAR colocar qualquer lógica de negócio na própria class Action. A classe Action devesimplesmente reunir qualquer dado que os métodos de negócio e classes Action precisarem, e transmiti-los. Osmétodos de negócios deverão estar numa classe separada, que o Action possa chamar. Na realidade, não se deve implementar as “Regras de Negócio” nas classes Action, pois isto aumenta emmuito o “acoplamento” entre as camadas de Modelo (Regras de Negócio) e acamada de Controle (ActionServlet e Action). O que deve ser feito é que outras classes extendam Action e executem o método execute( ). Estemétodo sim, é que deve chamar as classes que iremos construir e que implementam as regras de negócioTratamento de Exceções As classes Action também detectam os erros que possam acontecer. O processo envolve a utilização dedois objetos: ActionMessages e ActionError. Este assunto será coberto e apresentado em exemplos em algunscapítulos à frente. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 31 de 140
    • _____________________Curso Struts & Hibernate______________ As classes Action também executam o tratamento de exceções. Para isto, a fim de tratar uma exceção deuma maneira consistente em todos os objetos Action, o programador poderá registrar um ExceptionHandler com oarquivo de configuração do Struts, o struts-config.xml. Para registrar uma Exceção, precisará fornecer o tipo Exception, a chave do recurso da mensagem e ocaminho da resposta, como ilustrado a seguir: <exception type="org.apache.struts.webapp.example.ExpirePasswordException" key="expired.password" path="/changepassword.do"/>Actions roteiam o Controle Como vimos anteriormente, os objetos ActionForwards podem definir os "lugares aonde ir", mas é oobjeto Action que seleciona qual ActionForward deve ser executado. O ActionForward define o "para onde";oobjeto Action define o "quando". A maneira mais comum de uma classe Action selecionar um envio é através do método findForward doActionMapping, desta forma: return mapping.findForward("sucesso");DispatchAction Uma estratégia comum entre os desenvolvedores Struts é usar a mesma classe Action para lidar comvárias tarefas afins. Um bom exemplo é executar as operações CRUD (create, Read, Update e Delete) básicas em um registrode dados. Como estas operações tem muito em comum, poderá ser mais simples mantê-las em uma mesma classe.Com os DispatchAction (org.apache.struts.action.DispatchAction) os desenvolvedores poderão agrupar diversosmétodos em um único Action. Vamos supor que nossa classe "gravacaoDispatchAction" possuísse os seguintes métodos: public ActionForward create (ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) throws Exception { public ActionForward read (ActionMapping mapping, ActionForm form, HttpServletRequestrequest, HttpServletResponse response) throws Exception { public ActionForward update (ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) throws Exception { public ActionForward delete (ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) throws Exception { Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 32 de 140
    • _____________________Curso Struts & Hibernate______________O arquivo de configuração Struts poderia criar uma entrada como esta:<action. path="/registrarDados" type="app.gravacaoDispatchAction" name="dataForm" o parâmetro "parameter" indica qual método será scope="request" chamado na classe DispatchAction input="data.jsp" parameter="method"/>E para acessar o método "update" na classe "gravacaoDispatchAction" deveremos fazer: http://localhost/app/dataRecord?method=update18. Como exibir conteúdo dinâmico - Tag LibsO Framework Struts disponibiliza algumas bibliotecas de tags. As mais usadas são: html, bean e logic . html Tags usadas para criar formulários de entrada padrão HTML que podem interagir com o frameowrk Struts e as tags HTML afins bean Tags úteis ao acessar os JavaBeans e suas propriedades, assim como ao definir novoscomponentes logic Tags para gerenciar a geração condicional de saída, fazer um loop nas coleções deobjetos para uma geração repetida da saída e o gerenciamento de fluxo da aplicação18.1 Instalando as extensões da tag do Struts• Assim como qualquer outra biblioteca de tags, as existentes no Struts precisam ser declaradas no descritorweb.xml da aplicação, desta forma: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 33 de 140
    • _____________________Curso Struts & Hibernate______________• Na página "jsp", deve ser colocada a diretiva taglib conforme abaixo:• Tem que existir estas diretivas no início da página• Os parâmetros prefix, indicam de que forma devemos colocar na página HTML ,por exemplo: < bean:write .... < html:select...18.2 Quais são as TagLibs ?• Bean tags definir novos beans (em qualquer escopo) a partir de uma variedade de fontes e para imprimir beanse suas propriedades na resposta :Exemplo: <bean:write name="user“ property="fullName"/> <bean:message key="index.title"/>Esta instrução, <bean:write name="user“ property="fullName"/>, indica que , no tempo de execução,apresentará “ali, no local onde a instrução está”, o FullName de “user”, que é uma propriedade do JavaBean.Vejam as Bean Tags, na tabela abaixo: Nome da Tag Descrição cookie Define uma variável baseada no cookie especificado no request. define Define uma varíavel para referenciar um bean ou propriedade específica. header Define uma variável para referenciar um header específico do request include Carrega a resposta de um request e disponibiliza o mesmocomo um bean. message Processa uma mensagem de internacionalização e disponibiliza como uma string. page Expõe um item específico do contexto da página como um bean. parameter Define uma variável que faz referência um parameter específico do request. resource Carrega e disponibiliza como um bean um recurso. size Define um bean com o total de elementos de uma Collection ou Map. write Exibe o valor de uma propriedade específica de um bean. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 34 de 140
    • _____________________Curso Struts & Hibernate______________• HTML tags para ajudar a montar páginas JSP mais rapidamente, principalmente "forms"<html:link page="/editRegistration.do?action=Create"><html:hidden name=“phone">Na tag acima, <html:link page="/editRegistration.do?action=Create"> está sendo passado o parâmetro Create por “Query String”.• A tag <html:link /> é equivalente ao href do HTML.Vejam as html Tags, na tabela abaixo: Nome da Tag Descrição button Gera um botão html button cancel Gera um botão html cancel checkbox Gera um checkbox html errors Imprime a coleção de erros file Gera um campo do tipo file html form Define um form html frame Gera um elemento HTML frame hidden Gera um campo html hidden (oculto) html Gera a tag html image Gera um input tag do tipo image img Gera uma img html tag javascript Utilizado para processamento de regras de validação do Validator no lado cliente. link Gera um elemento html link option Gera um elemento select option password Gera um elemento input password radio Gera um elemento do tipo radio button reset Gera um elemento do tipo reset select Gera um elemento do tipo select submit Gera um elemento do tipo submit text Gera um input do tipo text textarea Gera um elemento do tipo textarea Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 35 de 140
    • _____________________Curso Struts & Hibernate______________• Logic tags para fazer um pouco de lógica sem scriptlets, apenas através de parâmetrosapropriadosExemplo de uma logic tag, usando todas as quatro propriedades comuns <logic:iterate scope="request" name="result" property="collection" id="row" > </logic:iterate>Este exemplo informa para examinar o contexto da solicitação (scope="request"), para obter um componente,denominado "result" (name="result"). Ao encontrar estes componente, recupera uma propriedade dele que éuma coleção (property="collection), fazendo por exemplo um "getCollection". Então, faz uma iteração nestacoleção (percorre a coleção) e exibe cada elemento desta, colocando cada elemento na variável "row"(id="row")Vejam as logic Tags, na tabela abaixo: Nome da Tag Descrição empty Executa o conteúdo da tag se a variável testada for null ou um string vazia. equal Executa o conteúdo da tag se a variável testada for igual ao valor especificado. forward Direciona o controle do fluxo de navegação para o ActionForward especificado. greaterEqual Executa o conteúdo da tag se a variável testada for igual ou maior ao valor especificado. greaterThan Executa o conteúdo da tag se a variável testada for maior do que o valor especificado. iterate Executa o corpo da tag até o tamanho da collection especificada. Executa o conteúdo da tag se a variável testada for igual ou menor do que o valor lessEqual especificado. lessThan Executa o conteúdo da tag se a variável testada for menor do que o valor especificado. Executa o conteúdo da tag desde de que a string informada contenha o trecho procurado. match (indexOf) notEmpty Executa o conteúdo da tag se a variável testada não for um valor nulo ou vazio. notEqual Executa o conteúdo da tag se a variável testada não for igual ao valor especificado. notMatch Executa o conteúdo da tag se a variável testada não for uma substring da string principal. notPresent Executa o conteúdo da tag se o valor informado não estiver presente no request. present Executa o conteúdo da tag se o valor informado estiver presente no request. redirect Gera um http redirect. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 36 de 140
    • _____________________Curso Struts & Hibernate______________19 - Jakarta Struts Framework - Multiplos Arquivos de Configuração• Uma das features do Struts é a possibilidade de dividir uma aplicação em módulos. Uma aplicação em módulos poderá ter vários arquivos de configuração (struts-config.xml). Com apenas umarquivo de configuração, o struts-config.xml ficaria assim:• Com vários arquivos, o struts-config.xml, ficaria assim:• Esta abordagem é especialmente útil para o desenvolvimento com o Struts em equipes muito grandes. Istoporque um único arquivo struts-config.xml, tende a ficar indisponível por muito tempo com um mesmodesenvolvedor.20 - Tiles Framework – Gerenciamento de Layouts• O Tiles apresenta-se como um framework de gerenciamento de layout de aplicações web. O mesmo pode serutilizado de forma independente, porém normalmente o mesmo é utilizado em conjunto com o Struts.• Uma preocupação que deveríamos ter em projetos web diz respeito a capacidade de reutilização de páginasweb. É comum a reutilização em outras camadas do modelo MVC, porém não há nenhum motivo para nãobeneficiarmos da reutilização nas páginas de nossa aplicação, na camada de apresentação.• A construção de aplicações baseadas em templates facilita a manutenção. Imagine um cenário no qual o usuáriodo sistema solicita uma mudança no padrão visual do sistema, como mudar o logotipo da empresa. Sem o uso deum mecanismo de templates como o Tiles, você teria que alterar todas as páginas de sua aplicação. Com o Tilesdependendo da forma como está estruturado o sistema, a alteração se dará em apenas algumas poucos páginas.• O Tiles irá realizar um trabalho semelhante ao executado pela ação <jsp:include>. Nesta ação temos a inclusãodinâmica de um recurso (normalmente uma outra JSP) em uma outra página. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 37 de 140
    • _____________________Curso Struts & Hibernate______________20.1 - Habilitando o Tiles• Para facilitar o uso do Tiles em uma aplicação Struts, o mesmo disponibiliza um conjunto de tags que irão facilitara criação de templates. Assim como para qualquer outro conjunto de tags, devemos declarar no descritor web.xmla taglib refernte ao Tiles:No web.xml, escrever:<taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location></taglib>• Este arquivo descritor da taglib "struts-tiles.tld", encontra-se no pacote do próprio Struts. Devemos salvar esteaquivo no diretório "WEB-INF",da aplicação. Após salvar o arquivo podemos então declarar a utilização da taglibem nossas páginas conforme abaixo:<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> • Em cada página que formos utilizar o Tiles, temos que colocar no começo esta diretiva. • Lembramos que o prefixo utilizado pode ser definido pelo próprio programador, sendo utilizada a palavra tiles apenas para manutenção de um padrão. • Como já foi mostrado anteriormente, o Tiles pode ser utilizado de forma independente do Struts, porém quando usado em conjunto, devemos informar seu uso no arquivo de configuração do Struts (struts- config.xml) conforme abaixo:No<plug-in className="org.apache.struts.tiles.TilesPlugin"> <set-property property= "definitions-config" value="/technology/WEB-INF/tiles-defs.xml"/></plug-in> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 38 de 140
    • _____________________Curso Struts & Hibernate______________20.2 - Utilizando o Tiles• Como primeiro passo para utilização do Tiles, devemos criar o arquivo de mapeamento utilizado pelo Tiles. Oarquivo tiles-defs.xml (conforme declarado anteriormente), irá conter a estrutura de cada um dos templatesutilizados pelo Tiles. Observe o exemplo abaixo:<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD TilesConfiguration//EN""http://jakarta.apache.org/struts/dtds/tiles-config.dtd"><tiles-definitions><definition name="portal.index" path="/padrao.jsp"> <put name=”title” value=”My Page”/> <put name="topo" value="/topo.jsp"/> <put name="menu" value="/menu.jsp"/> <put name="conteudo" value="/home.jsp"/> <put name="rodape" value="/rodape.jsp"/></definition><definition name="portal.notfound" extends="portal.index"> <put name="conteudo" value="/erro404.jsp" /></definition><definition name="portal.cadastros.usuarios" extends="portal.index"> <put name="conteudo" value="/paginas/cadastros/usuarios.jsp" /> <put name="menu" value="/paginas/cadastros/menu.jsp" /></definition></tiles-definitions>• Observe que definimos uma tag PUT com o nome title. Seu valor corresponde a uma "String". Este valor poderáser recuperado posteriormente em uma página da aplicação através da tag getAsString conforme abaixo: <tiles:getAsString name="title"/>• No exemplo acima temos a definição do template portal.index mapeando para a página padrao.jsp. Apágina de template padrao.jsp está divida em quatro áreas distintas (topo, menu, conteúdo e rodapé). Estespor sua vez, mapeam para páginas jsp de sua aplicação.• Assim como ocorre com uma estrutura de classes, o Tiles permite que você possa trabalhar com o conceito deherança de layouts. Para este propósito utilizamos o argumento extends da tag definition. Desta formapodemos ter uma definição estendendo uma outra e alterando apenas o que desejar.Veja no código anterior o código abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 39 de 140
    • _____________________Curso Struts & Hibernate______________<definition name="portal.notfound" extends="portal.index"> <put name="conteudo" value="/erro404.jsp" /></definition><definition name="portal.cadastros.usuarios" extends="portal.index"> <put name="conteudo" value="/paginas/cadastros/usuarios.jsp" /> <put name="menu" value="/paginas/cadastros/menu.jsp" /></definition>• Para se ter acesso ao layout definido basta referenciar no arquivo struts-config.xml através do atributo forwardde uma action, usando o nome do arquivo de definição portal..... Observe abaixo:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD StrutsConfiguration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"><struts-config> <data-sources /> <form-beans /> <global-exceptions /> <global-forwards /> <action-mappings> <action forward="portal.index" path="/index"/> <action forward="portal.notfound" path="/notfound"/> <action forward="portal.cadastros.usuarios" path="/cadastro"/> </action-mappings> <controller /> <plug-in className="org.apache.struts.tiles.TilesPlugin"> <set-property value="/WEB-INF/tiles-defs.xml" property="definitions-config" /> </plug-in></struts-config>• Neste exemplo temos a ação /index.do encaminhando o resultado do processamento para o mapeamentoportal.index. Lembre-se que em nosso arquivo tiles-defs.xml temos a declaração deste mapeamento.Veja:<definition name="portal.index" path="/padrao.jsp"> <put name="topo" value="/topo.jsp" /> <put name="menu" value="/menu.jsp" /> <put name="conteudo" value="/home.jsp" /> <put name="rodape" value="/rodape.jsp" /></definition> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 40 de 140
    • _____________________Curso Struts & Hibernate______________20.3 - Definindo a página de layout• Observamos que todo o processo de geração da página, está baseado em uma página básica. Esta páginacorresponde ao nosso layout ou template.<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %><%@ page contentType="text/html; charset=windows-1252" %><html:html locale="true"><head> <html:base/> <title>Meu Portal</title></head><body bgcolor="#FFFFFF" leftmargin="0" topmargin="0"><div align="left"> <table width="100%" border="0" cellspacing="0"> <tr> <td colspan="2"><tiles:get name="topo"/></td> </tr> <tr> <td width="17%"><tiles:get name="menu"/></td> <td width="83%"><tiles:get name="conteudo"/></td> </tr> <tr> <td colspan="2"><tiles:get name="rodape"/></td> </tr> </table></div></body></html:html>• Nesta página utilizamo a tag get do Tiles para que em tempo de execução o mesmo saiba em que ponto docódigo deverá fazer a inclusão dinâmica das demais páginas (topo,conteúdo,menu e rodapé). Todas as definiçõesde layout que se baseam nesta página irão utilizar o padrão visual definido na mesma.• As definições menu, conteúdo, topo e rodapé apontam para as suas respectivas páginas conforme abaixo:topo.jsp<table width="100%" border="0" bgcolor="#990000"> <tr> <td><font face="Arial, Helvetica, sans-serif" size="5"><b><fontcolor="#FFFFFF">Java Portal </font></b></font></td> </tr></table> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 41 de 140
    • _____________________Curso Struts & Hibernate______________menu.jsp<html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> </head> <body bgcolor="#FFFFFF" text="#000000" leftmargin="0" topmargin="0"> <table width="100%" border="1" cellspacing="0"bordercolor="#990000"> <tr> <td><a href="#">Membros</a></td> </tr> <tr> <td><a href="#">Artigos</a></td> </tr> <tr> <td><a href="#">Reuni&otilde;es</a></td> </tr> <tr> <td><a href="#">Fale Conosco</a></td> </tr> <tr> <td>&nbsp;</td> </tr> </table> </body></html>rodape.jsp<html> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> </head> <body bgcolor="#FFFFFF" text="#000000"> <div align="center"> <hr size="1"> <font face="Verdana, Arial, Helvetica, sans-serif, Trebuchet MS"size="2"><b>Java Magazine - Struts em Pedaços</b></font></div> </body></html> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 42 de 140
    • _____________________Curso Struts & Hibernate______________home.jsp<table width="100%" border="0"> <tr> <td> Aqui fica o centeúdo do portal</font></b></font></td> </tr></table>21 - Jakarta Struts Framework – Validator • Aplicações Web devem fornecer rotinas de validação da entrada dos dados para se obter o seguinte: o Requerer que certos campos tenham valores; o Confirmar que um certo valor de um campo de entrada, esteja em um padrão esperado ou pertencente a uma faixa de valores; o Verificar o formulário inteiro uma vez e retornar uma lista de mensagens sobre problemas com alguns campos; o Retornar a posição do cursor para a entrada original que está errada, para sua correção; o Possibilita a validação de entradas do usuários no lado servidor e no lado cliente (javascript) o Executar validações no lado do Servidor, se o JavaScript estiver desabilitado. • Para executar estas validações pode-se utilizar o framework Jakarta Commons Validator. • Para se utilizar o Validator em uma aplicação web, deve-se registrar o Validator no arquivo struts- config.xml desta forma: • O Validator, é registrado no struts-config.xml, como um plug-in. • As regras de validação se encontram no arquivo validator-rules.xml • Nos arquivos validation.xml e validator-rules.xml - ficarão das definições de validação dos formulários e as regras e classe (JavaScript) para utilização na validação dos mesmos. • No Struts 1.1 (validator-rules.xml) você encontrará alguns validadores para data, campo, tamanho, etc. Veja abaixo uma listagem dos validadores do struts. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 43 de 140
    • _____________________Curso Struts & Hibernate______________ No exemplo, "intRange" é definido pelo método validateIntRange da classe org.apache.struts.validator.FieldChecks. Define o identificador da mensagem exibida se a validação gerar um erro; a mensagem deve ser especificada em um dos arquivos•Exemplo de validação no validation-rules.xml de recursos do Struts. O atributo depends determina que o validador somente será executado após todos os outros validadores listados como dependentes. Este elemento <javascript>, dentro do arquivo de configuração do validator, serve para indicar quais validações no lado CLIENTE deverão ser feitas.O arquivo “validation-rules.xml” contém os nomes das regras de validação, a classe em que esta regra foiimplementada, e os argumentos da regra.-No código acima: <validator name=“IntRange” = “IntRange” é o nome da validação, da regra.classname=“org.apache.struts.validator.FieldChecks = Classe onde está a regra.depends=“integer” msg=“errors.range” = Define uma outra regra (regra de nome "integer") que já deveria estar aplicada para que esta (IntRange) possa ser aplicada. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 44 de 140
    • _____________________Curso Struts & Hibernate______________Jakarta Struts Framework – Validator (continuação)•No arquivo validation.xml temos a definição dos campos com as regras de validação aplicáveis.Jakarta Struts Framework – Validator (continuação)•Na página JSP temos: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 45 de 140
    • _____________________Curso Struts & Hibernate______________•A tag <html:javascript> gera código de acordo com configurações determinadas nos arquivos validation.xml evalidator-rules.xml. O nome da função de validação gerada segue o padrão validate<nome do formulario>,como pode ser visto na chamada a onsubmit="return validateCadUserForm(this);" do exemplo. Um aviso égerado em forma de alert informando que alguns campos obrigatórios não foram preenchidos, e a submissão écancelada.Pulando a validação em um botão de cancelamento ou retornoQuando criamos botões do tipo <html:cancel> ou até botões de “voltar” que venham a submeter o formulário, nãoqueremos que a validação de Javascript seja executada. Neste caso, atribuímos o valor false à variável deJavascript bCancel, isto é feito colocando-se o seguinte valor no atributo onclick das tags que renderizam botões:<html:cancel onclick=”bCancel=true” >Cancelar</html:cancel> Jakarta Struts Framework – Fluxo da Solicitaçãoweb browser 37 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 46 de 140
    • _____________________Curso Struts & Hibernate______________ Jakarta Struts Framework – Sequência 38 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 47 de 140
    • _____________________Curso Struts & Hibernate______________22. Jakarta Struts Framework – RequestProcessor•RequestProcessor é a classe que é processada a cada request disparado pelo cliente da aplicação.•Esta classe pode ser estendida para se obter uma implementação especializada para o tratamento dassolicitações da web.•processPreprocess( ) é normalmente o método sobrescrito.• O “Request Processor” é um objeto que recebe todos os “Requests” disparados pelos clientes da aplicação, quando estes submetem as requisições ao clicar no botão “Submit” do formulário HTML.• É uma espécie de PRÉ-PROCESSAMENTO, que é feito , antes de se enviar para o “ActionServlet”.• Com ele, pode-se ter informações como IP da máquina, Host Address etc.• Assim como outros componentes de Struts, o RequestProcessor exige uma declaração de mapeamento no arquivo struts-config.xml.• O mapeamento do “Request Processor” se dá dentro do arquivo “struts-config.xml”.• A classe será “chamada” (objeto instanciado) a cada “Request”. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 48 de 140
    • _____________________Curso Struts & Hibernate______________ Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 49 de 140
    • _____________________Curso Struts & Hibernate______________ ÍNDICE ANALÍTICO1. Conceitos Gerais ------------------------------------------------------------------------------------------------52 1.1 Persistência ---------------------------------------------------------------------------------------------- 52 1.2 Entidades ------------------------------------------------------------------------------------------------- 52 1.3 Mapeamento Objeto Relacional ---------------------------------------------------------------- 531.3.1 Mapeamento de um objeto com tipos primitivos -------------------------- 531.3.2 Mapeamento de objetos que contém uma coleção de objetos ------------- 542. Introdução ao Hibernate-------------------------------------------------------------------------------------563. Arquitetura do Hibernate ------------------------------------------------------------------------------------58 3.1 Session (org.hibernate.Session) --------------------------------------------------------------- 59 3.2 SessionFactory (org.hibernate.SessionFactory) ---------------------------------------- 59 3.3 Configuration (org.hibernate.cfg.Configuration) ---------------------------------------- 59 3.4 Transaction (org.hibernate.Transaction) --------------------------------------------------- 59 3.5 Interfaces Criteria e Query ----------------------------------------------------------------------- 594. Classes Persistentes -------------------------------------------------------------------------------------------59 4.1 Identidade/Igualdade entre Objetos --------------------------------------------------------- 61 4.2 Escolhendo Chaves Primárias ------------------------------------------------------------------- 615. Objetos Persistentes, Transientes e Detached ----------------------------------------------------626. Instalando o Hibernate ---------------------------------------------------------------------------------------638. Configurando o Hibernate-----------------------------------------------------------------------------------689. Manipulando Objetos Persistentes ----------------------------------------------------------------------7110. Associações ------------------------------------------------------------------------------------------------------73 10.1 Associações 1-n (one-to-many) -------------------------------------------------------------- 73 10.2 Associações n-1 (many-to-one) -------------------------------------------------------------- 76 10.3 Associações n-n (many-to-many) ----------------------------------------------------------- 78 10.4 Associações n-n com Atributos --------------------------------------------------------------- 8110.4.1 Composite-id---------------------------------------------------------------- 82 10.5 Associações 1-1 (one-to-one) ----------------------------------------------------------------- 8311. Coleções ----------------------------------------------------------------------------------------------------------85 11.1 Set --------------------------------------------------------------------------------------------------------- 85 11.2 List--------------------------------------------------------------------------------------------------------- 87 11.3 Map-------------------------------------------------------------------------------------------------------- 88 12. Herança --------------------------------------------------------------------------------------------------- 8813. Transações -------------------------------------------------------------------------------------------------------93 13.1 Ambientes Gerenciados e Não Gerenciados -------------------------------------------- 93 13.2 Transações JDBC ------------------------------------------------------------------------------------ 94 13.3 Transações JTA -------------------------------------------------------------------------------------- 94 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 50 de 140
    • _____________________Curso Struts & Hibernate______________ 13.4 API para Transações do Hibernate ---------------------------------------------------------- 94 13.5 Flushing ------------------------------------------------------------------------------------------------- 95 13.6 Níveis de Isolamento de uma Transação ------------------------------------------------- 95 13.9 Configurando o nível de isolamento -------------------------------------------------------- 9714. Concorrência ----------------------------------------------------------------------------------------------------97 14.1 Lock Otimista ----------------------------------------------------------------------------------------- 98 14.2 Lock Pessimista ------------------------------------------------------------------------------------- 10215. Busca de Dados---------------------------------------------------------------------------------------------- 103 15.1 SQL Nativo -------------------------------------------------------------------------------------------- 103 15.2 Hibernate Query Language - HQL ---------------------------------------------------------- 103 15.3 Criteria -------------------------------------------------------------------------------------------------- 106 15.4 Query By Example --------------------------------------------------------------------------------- 107 15.5 Paginação --------------------------------------------------------------------------------------------- 107 15.6 Named Query ---------------------------------------------------------------------------------------- 10816. Hibernate com Anotações e JPA ---------------------------------------------- 109 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 51 de 140
    • _____________________Curso Struts & Hibernate______________1. Conceitos Gerais1.1 Persistência Imagine um usuário fazendo uso de uma aplicação, por exemplo, um sistema para controlar suasfinanças. Ele passa a fornecer como dados de entrada todos os seus gastos mensais para que a aplicação lhegere, por exemplo, gráficos nos quais ele possa avaliar seus gastos. Finalizada, a sua análise financeira, o usuário resolve desligar o computador em que a aplicação seencontra. Imagine agora que o usuário teve novos gastos, voltou a ligar o computador, acessounovamente o sistema de finanças e que gostaria de realizar novas análises com todos os seus gastosacumulados. Se a aplicação não armazenar, de alguma forma, os primeiros gastos fornecidos, o usuário teria queinformá-los novamente e em seguida, acrescentar os novos gastos para fazer a nova análise, causandogrande trabalho e o sistema não sendo eficiente. Para resolver esse tipo de problema, uma solução seria armazenar (persistir) os dados lançados a cadavez pelo usuário em um banco de dados relacional, utilizando SQL (Structured Query Language).1.2 Entidades Entidades são classes, cujos objetos representam elementos existentes no mundo real (nomes,pessoas, objetos, valores, documentos, etc.), em torno dos quais o software é desenvolvido. No ambiente deexecução do software, os objetos das classes entity (classes de entidade) irão representar a ocorrência dessasentidades do mundo real. Também são conhecidas como classes de domínio da aplicação. Exemplos:Cliente;Pessoa;CursoNotificação;Cheque;Universidade;Registro de tarifação;Passagem aérea;Registros de vendas. O ciclo de vida de uma entidade é longo e, freqüentemente, maior do que o ciclo de vida do ambientede execução. Os objetos de "classes de entidade" precisam ser não-voláteis ou persistentes, isto é, precisamse manter entre diversas sessões de utilização de software - sessões que podem ser estabelecidas por usuáriosdiferentes. Um objeto pode ser considerado persistente quando seus atributos podem ser armazenados ao términode uma sessão de utilização do software e recuperados ao início de uma outra sessão. Existem diversas alternativas para persistir objetos. Veja abaixo, alguns exemplos:Bancos de dados orientados a objetos;Serialização de objetos em sistema de arquivos;Bancos de dados relacionais;Bancos de dados hierárquicos;Documentos XML.Web Services As duas primeiras alternativas têm a vantagem de manter fielmente representadas as estruturas dedados orientadas a objeto do software. As demais, não sendo orientadas a objetos, conseguirão representaruma estrutura OO através de processos de adaptação ou mapeamento de estruturas de dados. Em todos oscasos podemos estabelecer o conceito de repositório de dados das entidades. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 52 de 140
    • _____________________Curso Struts & Hibernate______________ Diante do repositório de dados, um objeto estará sujeito a quatro operações de persistência (CRUD): Criação, inserção ou inclusão no repositório (Create); Leitura ou recuperação dos dados (Read); Atualização ou modificação dos dados (Update); Remoção ou eliminação dos dados (Delete).1.3 Mapeamento Objeto Relacional Por vários anos os projetos de aplicações corporativas tiveram uma forte necessidade de se otimizar acomunicação da lógica de negócio com a base de dados. Essa necessidade ganhou mais intensidade com o crescimento dessas aplicações, crescimento esse,tanto em requisitos (funcionalidade) quanto em volume de dados armazenados em seu banco de dados. Na década de 70, foram criados os bancos de dados relacionais (BDR) que substituíram as bases dedados de arquivos. Para esse tipo de base de dados foi criada uma linguagem, a SQL = Structured Query Language. Essalinguagem foi toda baseada na lógica relacional e por isso contava com diversas otimizações em suas tarefas secomparadas com as outras tecnologias existentes. A partir de então foi diminuído o tempo gasto para as operações de persistência, mesmo com umgrande volume de dados. Entretanto, essa linguagem não propiciava aos desenvolvedores uma facilidade para que aprodutividade fosse aumentada. Uma solução que surgiu no início da década de 90 foi à criação de um modelo de banco de dadosbaseado no conceito de orientação a objetos. Este modelo visava facilitar, para os desenvolvedores, aimplementação da camada de persistência da aplicação, pois eles já estavam familiarizados com o paradigmadeorientação a objetos, consequentemente, a produtividade certamente aumentaria. Na prática, esse modelo de dados não foi utilizado em grandes aplicações, visto que elas tinham umvolume de dados muito grande e esse modelo era ineficiente em termos de tempo de resposta, pois aocontrário dos bancos de dados relacionais, eles não tinham um modelo matemático que facilitasse as suasoperações depersistências. Então a solução foi usar os BDR e desenvolver ferramentas para que o seu uso seja facilitado. Umadessas ferramentas é o framework Hibernate que usa o conceito de mapeamento objeto relacional (MOR). O mapeamento objeto relacional funciona com a transformação dos dados de um objeto em uma linha(tupla) de uma tabela de um banco de dados, ou de forma inversa, com a transformação de uma linha databela (tupla) em um objeto da aplicação. A seguir, mostraremos alguns tipos de mapeamentos entre objetos e tipos, primitivos ou tipos nãoprimitivos como uma Coleção de objetos.1.3.1 Mapeamento de um objeto com tipos primitivos Esse é o mapeamento mais simples, onde um objeto tem apenas tipos de dados básicos. Vale salientarque se entende por tipos básicos aqueles que possuem um correspondente em SQL, ou seja, o tipo String dalinguagem Java é considerado um tipo básico, pois ele possui um correspondente em SQL. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 53 de 140
    • _____________________Curso Struts & Hibernate______________ Na Figura 1, abaixo, observa-se o mapeamento de três objetos do tipo Veículo na tabela de um bancode dados. Caso a aplicação deseje saber o veículo da cor vermelha, por exemplo, então o objeto que tem o Paliocomo modelo é retornado.1.3.2 Mapeamento de objetos que contém uma coleção de objetos Esse tipo de mapeamento é quando um objeto possui um conjunto de outros objetos. Para obter esseconceito é necessário adicionar, ao exemplo da Figura 1, uma nova classe chamada de Fabricante que conteráas informações: nome, que armazenará o nome desse fabricante e o veiculos, que conterá o conjunto deveículos do fabricante (telefone e endereco não são informações relevantes no exemplo). Faz-se necessário a adição de uma informação na classe Veiculo chamada de fabricante, comomostrado na Figura 2. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 54 de 140
    • _____________________Curso Struts & Hibernate______________ O atributo "fabricante" adicionado à classe Veiculo, serve simplesmente para relacionar um veículo aoseu fabricante, enquanto o atributo "veiculos" na classe Fabricante, referencia a classe Veiculo. Como foram realizadas mudanças no domínio do exemplo orientado a objetos, faz-se necessária umaalteração no modelo do banco de dados. Primeiramente, o vínculo que foi realizado entre um fabricante e um veículo deverá ser implementadoatravés de uma chave estrangeira (FK = referência a uma outra tabela, pois em Banco de Dados Relacionaisnão existe o conceito de coleções) que se localizará na tabela VEICULO, caracterizando o mapeamento 1 paraN, ou seja, uma instância da entidade veículo "possui" (está relacionado) a uma instância da entidadefabricante e uma instância da entidade fabricante está relacionada ("possui") vários (N) veículos. Essa chave estrangeira será realizada entre a informação nome da classe Fabricante e o atributofabricante da classe Veiculo. Vejamos um exemplo deste relacionamento 1 x N e o mapeamento objeto relacional MOR: Para um melhor entendimento, a Figura 3 (acima), mostra o mapeamento dos objetos para as tabelasno BDR. Nele observa-se que cada veículo está associado a um fabricante, isso implica dizer que na tabela deVEICULO existe uma referência para a tabela FABRICANTE (chave estrangeira na entidade Veículo que é chaveprimária na entidade FABRICANTE). Essa associação é feita através da coluna Fabricante da tabela VEICULO. Pensando em termos práticos, quando um veículo for inserido no banco de dados, ele será ligado aoseu respectivo fabricante, no momento da inserção. Para recuperar os veículos inseridos o desenvolvedor terá que implementar uma busca que retorne asinformações do veículo . Isso poderá ser realizado fazendo a seguinte consulta SQL: SELECT * FROM VEICULO WHERE nome = <modelo>, onde <modelo> é o nome do modelo que está na tabela VEICULO. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 55 de 140
    • _____________________Curso Struts & Hibernate______________ Por exemplo, caso a aplicação deseje as informações do veículo do modelo Palio, então para se buscaro fabricante a seguinte consulta será realizada: SELECT * FROM VEICULO WHERE Modelo = Palio Utilizando a mesma idéia, os fabricantes são buscados; a única diferença é que agora a consulta quebuscará os veículos associados com o fabricante retornará uma coleção de veículos SELECT * FROM VEICULO WHERE fabricante = Fiat Esse tipo de mapeamento é muito utilizado em aplicações em que os objetos fazem muita referência aoutros objetos. Com a idéia do MOR (do inglês ORM = Object Relational Modeling) vários projetos de ferramentacomeçaram a ser desenvolvidas, visando facilitar a implementação da camada de persistência, dentre elas oframework Hibernate, que é um software livre de código aberto e que está tendo uma forte adesão de novosprojetos corporativos.2. Introdução ao Hibernate O Hibernate é uma ferramenta de mapeamento objeto/relacional para Java, e recentemente foidisponibilizada para a plataforma "dot net". Ela transforma os dados tabulares de um banco de dados em umconjunto de objetos definido pelo desenvolvedor. Usando o Hibernate, o desenvolvedor se livra de escrevermuito do código de acesso a banco de dados e de SQL que ele escreveria não usando a ferramenta, acelerandoa velocidade do seu desenvolvimento de uma forma fantástica. Mas o framework não é uma boa opção para todos os tipos de aplicação. Sistemas que fazem usoextensivo de stored procedures, triggers ou que implementam a maior parte da lógica da aplicação no banco dedados, contando com um modelo de objetos “pobre” não vai se beneficiar com o uso do Hibernate. Ele é mais indicado para sistemas que contam com um modelo rico, onde a maior parte da lógica denegócios fica na própria aplicação Java, dependendo pouco de funções específicas do banco de dados. A utilização de código SQL dentro de uma aplicação agrava o problema da independência de plataformade banco de dados e complica, em muito, o trabalho de mapeamento entre classes e banco de dados relacional. O Hibernate abstrai o código SQL da nossa aplicação e permite escolher o tipo de banco de dadosenquanto o programa está rodando, permitindo mudar sua base sem alterar nada no seu código Java. Além disso, ele permite criar suas tabelas do banco de dados de um jeito bem simples, não se fazendonecessário todo um design de tabelas antes de desenvolver seu projeto que pode ser muito bem utilizado emprojetos pequenos. Já projetos grandes onde o plano de ação padrão tomado pelo Hibernate não satisfaz as necessidadesda empresa (como o uso de select *, joins etc), ele possui dezenas de otimizações que podem ser feitas paraatingir tal objetivo. O projeto open-source Hibernate (www.hibernate.org) vem se consolidando entre a comunidade dedesenvolvedores Java como o melhor framework de persistência - levando em consideração os seguintesfatores:custo: é open-source LGPL.benefício: é uma solução poderosa, madura e portável - compatível com diversos bancos de dados relacionais e servidores de aplicação J2EE;curva de aprendizado: é rápida comparada com as outras soluções;documentação: livros publicados e diversos tutoriais e artigos disponíveis na internet; Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 56 de 140
    • _____________________Curso Struts & Hibernate______________suporte: pode ser contratado comercialmente ou pode se recorrer a uma comunidade extremamente ativa nos fóruns de discussão. Pretendemos com este curso, apresentar ao aluno já experiente na linguagem java , as facilidades queeste framework oferece para otimizar a construção de aplicações robustas, onde o programador vai dedicarmaior esforço nas regras de negócio, deixando as atividades de persistência, a cargo do Hibernate. O Hibernate é um framework de mapeamento objeto relacional para aplicações Java, ou seja, é umaferramenta para mapear classes Java em tabelas do banco de dados e vice-versa. É bastante poderoso e dásuporte ao mapeamento de associações entre objetos, herança, polimorfismo, composição e coleções. O Hibernate não apresenta apenas a função de realizar o mapeamento objeto relacional. Tambémdisponibiliza um poderoso mecanismo de consulta de dados, permitindo uma redução considerável no tempo dedesenvolvimento da aplicação. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 57 de 140
    • _____________________Curso Struts & Hibernate______________3. Arquitetura do Hibernate A arquitetura do Hibernate é formada basicamente por um conjunto de interfaces. A Figura 4 apresentaas interfaces mais importantes nas camadas de negócio e persistência. A camada de negócio (Business Layer) aparece acima da camada de persistência (Persistence Layer)por atuar como uma cliente da camada de persistência. Vale salientar que algumas aplicações podem não ter aseparação clara entre as camadas de negócio e de persistência. De acordo com a Figura 4, as interfaces são classificadas como: Interfaces responsáveis por executar operações de criação, deleção, consulta e atualização no banco dedados: Session, Transaction e Query; Interface utilizada pela aplicação para configurar o Hibernate: Configuration; Interfaces responsáveis por realizar a interação entre os eventos do Hibernate e a aplicação: Interceptor,Lifecycle e Validatable. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 58 de 140
    • _____________________Curso Struts & Hibernate______________ Interfaces que permitem a extensão das funcionalidades de mapeamento do Hibernate: UserType,CompositeUserType e IdentifierGenerator. O Hibernate também interage com APIs já existentes do Java: JTA, JNDI e JDBC. De todas as interfaces apresentadas na Figura 4 (acima), as principais são: Session, SessionFactory,Transaction, Query, Configuration. Os sub-tópicos seguintes apresentam uma descrição mais detalhada sobre elas.3.1 Session (org.hibernate.Session) O objeto Session é aquele que possibilita a comunicação entre a aplicação e a persistência, através deuma conexão JDBC. É um objeto leve de ser criado, não deve ter tempo de vida por toda a aplicação e não é threadsafe.Um objeto Session possui um cache local de objetos recuperados na sessão. Com ele é possível criar, remover,atualizar e recuperar objetos persistentes.3.2 SessionFactory (org.hibernate.SessionFactory) O objeto SessionFactory é aquele que mantém o "mapeamento objeto relacional" (MOR) em memória.Permite a criação de objetos Session, a partir dos quais os dados são acessados, também denominado comofábrica de objetos Sessions. Um objeto SessionFactory é threadsafe, porém deve existir apenas uma instância dele na aplicação,pois é um objeto muito pesado para ser criado várias vezes. Existe uma técnica que será explicada para queeste objeto seja carregado uma única vez, evitando o custo de várias cargas.3.3 Configuration (org.hibernate.cfg.Configuration) Um objeto Configuration é utilizado para realizar as configurações de inicialização do Hibernate. Comele, define-se diversas configurações do Hibernate, como por exemplo: o driver do banco de dados a serutilizado, o dialeto, o usuário e senha do banco, entre outras. É a partir de uma instância desse objeto que se indica como os mapeamentos entre classes e tabelas debanco de dados devem ser feitos.3.4 Transaction (org.hibernate.Transaction) A interface Transaction é utilizada para representar uma unidade indivisível de uma operação demanipulação de dados. O uso dessa interface em aplicações que usam Hibernate é opcional. Essa interfaceabstrai a aplicação dos detalhes das transações JDBC, JTA ou CORBA.3.5 Interfaces Criteria e Query As interfaces Criteria e Query são utilizadas para realizar consultas ao banco de dados.4. Classes Persistentes As classes persistentes de uma aplicação são aquelas que implementam as entidades domínio denegócio. O Hibernate trabalha associando cada tabela do banco de dados a um POJO (Plain Old Java Object). POJO´s são objetos Java que seguem a estrutura de JavaBeans (construtor padrão sem argumentos, emétodos getters e setters para seus atributos). Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 59 de 140
    • _____________________Curso Struts & Hibernate______________ A Tabela 1 apresenta a classe Pessoa ,representando uma classe POJO. package modelo; import java.util.Date; public class Pessoa { private long id; private String cpf; private String nome; private int idade; private Date dataNascimento; public Pessoa() { } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Date getDataNascimento() { return dataNascimento; } public void setDataNascimento(Date dataNascimento) { this.dataNascimento = dataNascimento; } public int getIdade() { return idade; } public void setIdade(int idade) { this.idade = idade; } } Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 60 de 140
    • _____________________Curso Struts & Hibernate______________Considerações: O Hibernate requer que toda classe persistente possua um construtor padrão sem argumentos, assim, oHibernate pode instanciá-las simplesmente chamando Construtor.newInstance(); Observe que a classe Pessoa apresenta métodos setters e getters para acessar ou retornar todos os seusatributos. O Hibernate persiste as propriedades no estilo JavaBeans, utilizando esses métodos; A classe Pessoa possui um atributo id que é o seu identificador único. É importante que, ao utilizarHibernate, todos os objetos persistentes possuam um identificador e que eles sejam independentes da lógica denegócio da aplicação.4.1 Identidade/Igualdade entre Objetos Para verificar se dois objetos são iguais em Java, deve-se utilizar o método equals, ou seja, verificar seobj1.equals(obj2), retorna um booleano true . Incluindo o conceito de persistência, passa a existir um novo conceito de identidade, a identidade debanco de dados. Dois objetos armazenados em um banco de dados são idênticos se forem mapeados em uma mesmalinha da tabela.4.2 Escolhendo Chaves Primárias Um passo importante ao utilizar o Hibernate é informá-lo sobre a estratégia utilizada para a geração dechaves primárias. Uma chave primária é uma coluna ou um conjunto de colunas que identifica unicamente uma linha deuma tabela do banco de dados. Ela deve satisfazer as seguintes propriedades: Ser Única; Nunca ser nula; Ser Constante. Ser mínima. Uma única tabela pode ter várias colunas ou combinações de colunas que satisfazem essaspropriedades. Se a tabela possui um único atributo que a identifique, ele é por definição a sua chave primária. Sepossuir várias chaves que atendem a estas características, elas são chamadas de chaves candidatas e, apenasuma (um campo, uma coluna) deve ser escolhida para representar a chave primária e as demais colunasdevem ser definidas como chaves únicas (marcar como Unique Keys). Muitas aplicações utilizam como chaves primárias chaves naturais, ou seja, que têm significados denegócio. Por exemplo, o atributo cpf da tabela Pessoa (associada à classe Pessoa). Essa estratégia pode nãoser muito boa em longo prazo, já que uma chave primária adequada deve ser constante, única e não nula. Seuma Pessoa, não possuir cpf (muitas mulheres utilizam o cpf do marido e existem pessoas que não possuemcpf) Dessa forma, se for desejado que a chave primária da tabela Pessoa seja uma outra ao invés do cpf,podem surgir problemas já que provavelmente o cpf deve já estar referenciado em outras tabelas. Umproblema que poderia acontecer seria a remoção do cpf da tabela. O Hibernate apresenta vários mecanismos internos para a geração de chaves primárias.Veja a Tabela 2. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 61 de 140
    • _____________________Curso Struts & Hibernate______________Tabela 2 – Mecanismos de Geração de Chaves Primárias Mecanismo Descrição Mapeado para colunas identity no DB2, MySQL, MSSQL, Sybase, identity HSQLDM, Informix. Mapeado em sequências no DB2, PostgreSQL, Oracle, SAP DB, Firebird sequence (ou generator no Interbase). Lê o valor máximo da chave primária e incrementa um. Deve ser usado quando a aplicação é a única a acessar o banco e de forma não increment concorrente. hilo Usa algoritmo high/low para geração de chaves únicas. Usa uma combinação do IP com um timestamp para gerar u m identificador uudi.hex único na rede. Utiliza o valor atribuído com set à propriedade do objeto associada ao assigned mapeamento de chave única (id).5. Objetos Persistentes, Transientes e Detached Nas diversas aplicações existentes, sempre que for necessário propagar o estado de um objeto que estáem memória para o banco de dados ou vice-versa, há a necessidade de que a aplicação interaja com umacamada de persistência. Isto é feito, invocando o gerenciador de persistência e as interfaces de consultas doHibernate. Quando interagindo com o mecanismo de persistência, é necessário para a aplicação ter conhecimentosobre os estados do ciclo de vida da persistência. Em aplicações orientadas a objetos, a persistência permite que um objeto continue a existir mesmoapós a destruição do processo que o criou. Na verdade, o que continua a existir é seu estado, já que pode serarmazenado em disco e então, no futuro, ser recriado em um novo objeto. Em uma aplicação não há somente objetos persistentes, pode haver também objetos transientes.Objetos transientes são aqueles que possuem um ciclo de vida limitado ao tempo de vida do processo que oinstanciou. Em relação às classes persistentes, nem todas as suas instâncias possuem necessariamenteum estado persistente. Elas também podem ter um estado transiente ou detached. O Hibernate define estes três tipos de estados: persistentes, transientes e detached. Objetos com esses estados são definidos como a seguir: Objetos Transientes: são objetos que suas instâncias não estão nem estiveram associados a algumcontexto persistente. Eles são instanciados, utilizados e após a sua destruição não podem ser reconstruídosautomaticamente; Objetos Persistentes: são objetos que suas instâncias estão associadas a um contexto persistente, ou seja,tem uma identidade de banco de dados. Objetos detached: são objetos que tiveram suas instâncias associadas a um contexto persistente, mas quepor algum motivo deixaram de ser associadas, por exemplo, por fechamento de sessão, finalização de sessão.São objetos em um estado intermediário, nem são transientes nem persistentes. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 62 de 140
    • _____________________Curso Struts & Hibernate______________6. Instalando o Hibernate Instalar o Hibernate é uma tarefa bastante simples. O primeiro passo é copiar sua versão do sitehttp://hibernate.org, disponível em um arquivo compactado. Por fim, este arquivo deve ser descompactado e seu conteúdo consiste em um conjunto de arquivosJARs (Java Archive, o equivalente no Java a uma DLL), descritos abaixo: ant-antlr-1.6.5.jar antlr-2.7.6.jar asm-attrs.jar asm.jar c3p0-0.9.0.jar cglib-2.1.3.jar commons-collections-2.1.1.jar commons-logging-1.0.4.jar dom4j-1.6.1.jar ehcache-1.2.jar hibernate3.jar hsqldb.jar jdbc2_0-stdext.jar jta.jar libs.txt log4j-1.2.11.jar xerces-2.6.2.jar xml-apis.jar Esses arquivos devem ser referenciados no classpath da aplicação, juntamente com a classe do driverdo banco de dados utilizado. Depois de fazer o download, adicione o arquivo hibernate3.jar e os seguintesarquivos da pasta “lib” do download ao seu classpath (ou ao classpath da sua IDE): Como já dissemos, o banco de dados escolhido para este curso é o MySQL, versão 5.0, mas os scriptsSQL pra gerar as tabelas podem ser facilmente adaptados para outros bancos. Usando o MySQL você tambémvai ter que colocar o driver JDBC dele no seu classpath, ele pode ser baixado no seguinte endereço: http://dev.mysql.com/downloads/connector/j/5.0.html . A estrutura de tabelas será criada automaticamente conforme os mapeamentos forem criados. Você vai aprender sobre os mapeamentos do Hibernate e a HQL, a linguagem de buscas do framework.O curso assume que você já tenha um conhecimento sobre a linguagem Java, bancos de dados e XML, além deser capaz de montar um ambiente de desenvolvimento Java com todas as configurações necessárias.objetosdo modelo Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 63 de 140
    • _____________________Curso Struts & Hibernate______________7. Primeiro Exemplo de Mapeamento Inicialmente, o Hibernate precisa saber como carregar e armazenar objetos de classes persistentes. Para isso, existe um arquivo de mapeamento XML que informa que tabela do banco de dados deve seracessada para uma dada classe persistente e quais colunas na tabela são referentes a quais atributos da classe.Isto é o "mapeamento" Objeto x Relacional. Qualquer classe pode ser mapeada desde que seja um POJO, ou seja, possua um construtor semargumento e seus atributos mapeados possuam métodos getter e setter (um JavaBean) . É recomendável que as tabelas possuam chaves primárias, de forma que se possa aproveitar aomáximo as funcionalidades do Hibernate. Para alguns dos exemplos a serem ilustrados, considere o digrama UML mostrado na Figura 6. Nele, éapresentado o domínio simplificado de uma Universidade. Como se pode observar, uma Universidade é formada por um identificador (id), um nome, possui umendereço e um conjunto de centros. Cada centro também possui um identificador (id), um nome, uma Universidade a que pertence e éformado por um conjunto de departamentos. Cada departamento associa-se a um conjunto de cursos, possui uma coleção de professores e possuium professor como sendo seu chefe, além do seu identificador id e de seus demais atributos nome e sigla. Um curso possui um identificador, um código, um nome, uma sigla, um professor como seucoordenador, associa-se a um ou mais departamentos e possui um conjunto de alunos. Um professor possui um identificador, uma matrícula, um nome, um cpf e um departamento onde élotado. Por fim, um aluno possui um identificador, uma matrícula, um nome, um cpf e um curso a quepertence. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 64 de 140
    • _____________________Curso Struts & Hibernate______________ Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 65 de 140
    • _____________________Curso Struts & Hibernate______________ Neste primeiro exemplo, será apresentado o mapeamento da classe Aluno em um arquivo XML, que oHibernate utiliza para saber que tabela no banco de dados a representa. Os arquivos de mapeamentos XMLentre classes e tabelas do banco de dados devem ser nomeados como *.hbm.xml (convenção definida pelacomunidade de desenvolvedores do Hibernate). É nos arquivos com a extensão .hbm.xml que o Hibernate realiza o mapeamento objeto relacional. A classe que representa a entidade Aluno do diagrama da Figura 6 está ilustrada na Tabela 3. Tabela 3 - Classe de Domínio: Aluno package modelo; public class Aluno { private long id; private long matricula; private String nome; private String cpf; private Curso curso; public Aluno() { } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public long getMatricula() { return matricula; } public void setMatricula(long matricula) { this.matricula = matricula; } public Curso getCurso() { return curso; } public void setCurso(Curso curso) { this.curso = curso; } } Todos os arquivos XML que mapeiam as classes para as tabelas de banco de dados no Hibernatepossuem a estrutura básica mostrada na Tabela 4. O arquivo XML começa normalmente com as definições daDTD (Definição do Tipo do Documento – Document Type Definition) e da tag raiz, o <hibernate-mapping>,depois vem a tag que nos interessa neste caso, <class>. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 66 de 140
    • _____________________Curso Struts & Hibernate______________ Os elementos para o mapeamento objeto relacional encontram-se entre as tags hibernate-mapping. Tabela 4 - Estrutura Básica do Arquivo *.hbm.xml <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> ... </hibernate-mapping> Para a classe Aluno considere seu arquivo de mapeamento como sendo o Aluno.hbm.xml. A partirdeste momento, o cabeçalho do arquivo XML será ocultado e o conteúdo entre as tags hibernate-mapping seráapresentado. O primeiro passo do mapeamento é informar que classe de domínio serefere a que tabela do banco de dados, através da tag <class>, como mostrado na Tabela 5. O único atributo obrigatório desta tag é o name, que contém o nome completo da classe. Se o nomeda classe for diferente do nome da tabela a que se referencia, o nome da tabela é informado a partir doatributo table. Tabela 5 - Aluno.hbm.xml 1 <hibernate-mapping> <class name="modelo.Aluno" table="ALUNO"> ... </class> </hibernate-mapping> Em seguida, mapeia-se a chave primária da tabela, como mostrado na Tabela 6: Tabela 6 - Aluno.hbm.xml 2 <hibernate-mapping> <class name="modelo.Aluno" table="ALUNO"> <id name="id" column="ID_ALUNO" type="long"> <generator class="identity" /> </id> </class> </hibernate-mapping> A tag id identifica a chave primária. O atributo name="id" informa o nome do atributo da classe Java que se refere à chave primária databela. O Hibernate utiliza os métodos getter e setter para acessar este atributo. O atributo column informa ao Hibernate qual coluna na tabela é a chave primária, no caso ID_ALUNO. O atributo generator informa qual a estratégia para a geração da chave primária, conforme ilustradona tabela 2, para esse exemplo, a estratégia utilizada foi sequence. Dessa forma, o nome da seqüênciatambém deve ser informado (aluno_seq) através da tag param. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 67 de 140
    • _____________________Curso Struts & Hibernate______________ Agora as declarações das propriedades persistentes das classes serão incluídas no arquivo demapeamento. Por padrão, os atributos das classes não são considerados como persistentes. Para se tornarem,é necessário incluí-los no arquivo de mapeamento. Na Tabela 7, são incluídos os mapeamentos das propriedades persistentes através da tag property.Essas tags indicam propriedades simples dos objetos, como por exemplo, String, os tipos primitivos e seuswrappers, objetos Date, Calendar, entre outros. Tabela 7 - Aluno.hbm.xml 3 <hibernate-mapping> <class name="modelo.Aluno" table="ALUNO"> <id name="id" column="ID_ALUNO" type="long"> <generator class="identity" /> </id> <property name="matricula" type="long" column="MATRICULA"/> <property name="nome"/> <property name="cpf" type="java.lang.String" column="CPF" not-null="false"/> <many-to-one name="curso" class="modelo.Curso" column="ID_CURSO"/> </class> </hibernate-mapping> Os nomes das propriedades da classe são definidos pelo atributo XML name, o tipo da propriedadepelo atributo XML type e a coluna da tabela a que se refere, pelo atributo XML column. Observe que apropriedade nome não possui seu tipo e coluna a que se referenciam definidos. Se o atributo column nãoaparece no mapeamento da propriedade, o Hibernate considera que a coluna na tabela do banco de dados aquese referencia possui o mesmo nome que o definido pelo atributo name. Então pode-se concluir que apropriedade "nome" da classe, refere-se à coluna NOME na tabela do banco de dados. Em relação ao atributo type não ser definido, o Hibernate também tenta, analisando o tipo dacoluna na tabela, converter para o tipo adequado Java. O atributo not-null presente no mapeamento do atributo cpf serve para informar se a coluna podeser ou não nula na tabela. Se for true, não pode ser nula. Se for false, pode assumir valor nulo. A última tag do arquivo <many-to-one> define o relacionamento n-para-1 que a classe Aluno temcom a classe Curso ( um Aluno pode fazer muitos Cursos). Uma descrição mais detalhada destatag será feita posteriormente. Depois de criar todas as classes persistentes com seus respectivos mapeamentos *.hbm.xml, deve-se realizar algumas configurações do Hibernate.8. Configurando o HibernatePode-se configurar o Hibernate de três maneiras distintas: Instanciar um objeto de configuração (org.hibernate.cfg.Configuration) e inserir suas propriedadesprogramaticamente; Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 68 de 140
    • _____________________Curso Struts & Hibernate______________ Usar um arquivo .properties com as suas configurações e indicar os arquivos de mapeamentoprogramaticamente; Usar um arquivo XML (hibernate.cfg.xml) com as propriedades de inicialização e os caminhos dos arquivosde mapeamento. Será apresentada a configuração a partir do arquivo hibernate.cfg.xml. Um exemplo deste arquivo de configuração pode ser visto na Tabela 8. Vários parâmetros podem serconfigurados. Basicamente, deve-se configurar: A URL de conexão com o banco de dados; Usuário e senha do banco de dados; Números máximo e mínimo de conexões no pool; Dialeto. Tabela 8 - hibernate.cfg.xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- a SessionFactory instance listed as /jndi/name --> <session-factory name="java:comp/env/hibernate/SessionFactory"> <!-- properties --> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="connection.url"> jdbc:mysql://localhost:3306/data2 </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="show_sql">true</property> <property name="connection.username">mysql</property> <property name="connection.password">interplan</property> <property name="connection.pool_size">10</property> <property name="hibernate.hbm2ddl.auto" >create-drop</property> <!-- mapping files --> <mapping resource="modelo/Aluno.hbm.xml"/> <mapping resource="modelo/Centro.hbm.xml"/> <mapping resource="modelo/Curso.hbm.xml"/> <mapping resource="modelo/Departamento.hbm.xml"/> <mapping resource="modelo/Professor.hbm.xml"/> <mapping resource="modelo/Universidade.hbm.xml"/> </session-factory> </hibernate-configuration> Resumindo as descrições das propriedades a serem configuradas: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 69 de 140
    • _____________________Curso Struts & Hibernate______________ connection.datasource: Nome jndi de um datasource em um connection pool (tomcat, jboss…). Opcional. hibernate.dialect: Implementação do dialeto SQL específico do banco de dados a ser utilizado. Usado paraidentificar as particularidades do banco de dados; hibernate.connection.driver_class: Nome da classe do driver JDBC do banco de dados que está sendoutilizado; hibernate.connection.url: É a URL de conexão específica do banco que está sendo utilizado; hibernate.connection.username: É o nome de usuário com o qual o Hibernate deve se conectar ao banco; hibernate.connection.password: É a senha do usuário com o qual o Hibernate deve se conectar ao banco; hibernate.connection.pool_size: Tamanho do pool de conexões; hibernate.hbm2ddl.auto: Valida ou exporta automaticamente o esquema do banco de dados quando oSessionFactory é criado (validate | update | create | create-drop). NÃO UTILIZE EM PRODUÇÃO! ; hibernate.connection.isolation: define o nível de isolamento. Parâmetro opcional (1| 2| 4| 8); hibernate.show_sql: utilizado para definir se os SQL’s gerados pelo Hibernate devem ou não ser exibidos(true | false) . O Hibernate trabalha com dialetos para um grande número de bancos de dados, tais como: DB2,MySQL, Oracle, Sybase, Progress, PostgreSQL, Microsoft SQL Server, Ingres, Informix entre outros. Possíveisvalores para os dilates estão presentes na Tabela 9: Tabela 9 - Possíveis valores de dialetosDB2 - org.hibernate.dialect.DB2DialectHypersonicSQL - org.hibernate.dialect.HSQLDialectInformix - org.hibernate.dialect.InformixDialectIngres - org.hibernate.dialect.IngresDialectInterbase - org.hibernate.dialect.InterbaseDialectPointbase - org.hibernate.dialect.PointbaseDialectPostgreSQL - org.hibernate.dialect.PostgreSQLDialectMckoi SQL - org.hibernate.dialect.MckoiDialectMicrosoft SQL Server - org.hibernate.dialect.SQLServerDialectMySQL - org.hibernate.dialect.MySQLDialectOracle (any version) - org.hibernate.dialect.OracleDialectOracle 9 - org.hibernate.dialect.Oracle9DialectProgress - org.hibernate.dialect.ProgressDialectFrontBase - org.hibernate.dialect.FrontbaseDialectSAP DB - org.hibernate.dialect.SAPDBDialectSybase - org.hibernate.dialect.SybaseDialectSybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect O final do arquivo hibernate.cfg.xml é onde devem ser informados os arquivos de mapeamentos dasclasses que o Hibernate deve processar. Se algum arquivo de mapeamento não for definido neste local, a classea que se refere não poderá ser persistida utilizando o Hibernate. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 70 de 140
    • _____________________Curso Struts & Hibernate______________9. Manipulando Objetos Persistentes O Hibernate utiliza objetos Session para persistir e recuperar objetos. Um objeto Session pode serconsiderado como uma sessão de comunicação com o banco de dados através de uma conexão JDBC. O código fonte exibido na Tabela 10 mostra a criação e persistência de um objeto do tipo Aluno. Tabela 10 - Exemplo de Persistência1. try{2. //SessionFactory deve ser criado uma única vez durante a execução3. //da aplicação4. SessionFactory sf = newConfiguration().configure("/hibernate.cfg.xml").buildSessionFactory();5. Session session = sf.openSession(); //Abre sessão6. Transaction tx = session.beginTransaction(); //Cria transação7.8. //Cria objeto Aluno9. Aluno aluno = new Aluno();10. aluno.setNome("João Victor");11. aluno.setMatricula(2031998);12. aluno.setCpf(“1234567898”);13. //Considera-se que o objeto “curso” já havia gravado na base de dados e14. //recuperado para ser atribuído neste momento.15. aluno.setCurso(curso);16.17. session.save(aluno); //Realiza persistência18. tx.commit(); //Fecha transação19. session.close(); //Fecha sessão20. } catch(HibernateException e1) {21. e1.printStackTrace();22. } O código presente nas linhas 4 deve ser chamado uma única vez durante a execução da aplicação. Oobjeto SessionFactory armazena os mapeamentos e configurações do Hibernate. É um objeto pesado e lento dese criar. Pode-se pensar em colocar estas instruções em um Bloco Estático para minimizar o desperdício detempo. A Tabela 11 apresenta alguns dos métodos que podem ser invocados a partir do objeto Session. Tabela 11 - Métodos invocados a partir do objeto Session Assinatura do Método Descrição save(Object) Inclui um objeto em uma tabela do banco de dados. saveOrUpdate(Object) Inclui um objeto na tabela caso ele ainda não exista (seja transiente) ou atualiza o objeto caso ele já exista (seja persistente). delete(Object) Apaga um objeto da tabela no banco de dados get(Class, Serializable id) Retorna um objeto a partir de sua chave primária. A classe do objeto é passada como primeiro argumento e o seu identificador como segundo argumento Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 71 de 140
    • _____________________Curso Struts & Hibernate______________ Em relação ao método saveOrUpdate, uma questão que se pode formular é “Como o Hibernate sabese o objeto em questão já existe ou não no banco de dados, ou seja, se ele deve ser criado ou atualizado?”. Aresposta é simples: o desenvolvedor deve informar isso a ele. Essa informação é incluída no arquivo de configuração *.hbm.xml da classe na tag que define a chaveprimária. No caso da classe Aluno, a tag da chave primária no arquivo Aluno.hbm.xml deve ter o atributo<unsaved-value> adicionado, como mostrado na Tabela 12. Neste caso com o atributo unsaved-value="0"significa que, no momento da chamada ao método saveOrUpdate(Objetc obj), se o atributo identificador doobjeto estiver com valor 0 (zero) significa que ele deve ser criado na tabela do banco de dados. Dessa forma, se o seu valor for diferente de zero, o objeto deve ter sua linha na tabela atualizada(deve-se garantir que o valor do identificador do objeto se refere a um valor da chave primária da tabela). Tabela 12 - Trecho de Aluno.hbm.xml <id name="id" column="ID_ALUNO" type="int" unsaved-value="0"> <generator class="identity"> </id> As Tabela 13 e Tabela 14 apresentam exemplos dos métodos invocados a partir do objeto Session. Tabela 13 - Exemplo de Busca e Atualização de Objeto ... Session session = sf.openSession(); Transaction tx = session.beginTransaction(); //Busca objeto aluno da base de dados com chave primária = 1 Aluno aluno = (Aluno) session.get(Aluno.class, 1); //Atualiza informação de matrícula. aluno.setMatricula(200027807); //Como o identificador do objeto aluno é diferente de 0, //a sua matrícula é atualizada já que foi alterada session.saveOrUpdate(aluno); tx.commit(); session.close(); ... Tabela 14 - Exemplo de Remoção de Objeto ... Session session = sf.openSession(); Transaction tx = session.beginTransaction(); Aluno aluno = new Aluno(); //Existe linha na tabela aluno com chave primária = 2 aluno.setId(2); //Deleta aluno com id = 2 da tabela. //Somente necessária informação do seu identificador session.delete (aluno); tx.comiit(); session.close(); ... Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 72 de 140
    • _____________________Curso Struts & Hibernate______________10. Associações O termo associação é utilizado para se referir aos relacionamentos entre as entidades. Osrelacionamentos n-para-n, n-para-1 e 1-para-n são os mais comuns entre as entidades de um banco dedados. Todos os exemplos apresentados nesta seção baseiam-se no diagrama de classes mostrado na Figura6.10.1 Associações 1-n (one-to-many) Para exemplificar o relacionamento 1-n, considere o relacionamento entre a entidade Centro e aentidade Universidade da Figura 7. O relacionamento diz que "uma universidade possui um conjunto de ncentros" e "um centro está associado a apenas uma única universidade". Considere as classes de domínio Javade uma universidade e de um centro, respectivamente, mostradas na Tabela 15 e na Tabela 16. Figura 7 - Relacionamento entre Centro e Universidade Tabela 15 - Classe de Domínio: Universidade package modelo; import java.util.Collection; public class Universidade implements Serializable{ private long id; private String nome; private Endereco endereco; private Collection centros; //Implementação dos métodos setter e getter ... } Tabela 16 - Classe de Domínio: Centro Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 73 de 140
    • _____________________Curso Struts & Hibernate______________ package modelo; import java.util.Collection; public class Centro implements Serializable{ private long id; private String nome; private Universidade universidade; //departamentos -> Atributo mapeado das mesma forma que a //coleção centros em Universidade private Collection departamentos; //Implementação dos métodos setter e getter }A classe de domínio Universidade é a que possui um mapeamento do tipo 1-n. O seu mapeamento pode servisto na Tabela 17. Neste momento, as informações do endereço da universidade foram desconsideradas. Tabela 17 - Mapeamento 1-n: tabela universidade ... <hibernate-mapping> <class name="modelo.Universidade" table="UNIVERSIDADE"> <id name="id" column="ID_UNVERSIDADE" type="long"> <generator class="increment"/> </id> <property name="nome"/> <!-- Mapeamento da Coleção de centros --> <set name="centros" inverse="true" lazy="true"> <key column="ID_UNIVERSIDADE"/> <one-to-many class="modelo.Centro"/> </set> </class> </hibernate-mapping> Observa-se que para realizar o mapeamento 1-n, ou seja, da coleção centros foi utilizada uma tag set.Um set ou um conjunto, representa uma coleção de objetos não repetidos que podem ou não estar ordenados. O atributo name define a propriedade que está sendo tratada para realizar o relacionamento 1-n. Oatributo key representa a coluna da tabela relacionada (Centro) que possui a chave estrangeira para a classeUniversidade. O nome da coluna da chave estrangeira (ID_UNIVERSIDADE) é informado no atributo column. Na tag <one-to-many> informa-se a classe a qual pertence à coleção de objetos, no caso"modelo.Centro". A tag set também apresenta um atributo denominado inverse. Esse atributo é utilizado para que oHibernate saiba como tratar a associação entre duas tabelas. Quando um lado da associação define o atributoinverse como true, indica que a ligação do relacionamento entre a associação será de responsabilidade do"outro lado" da associação. Esse atributo será explicado em maiores detalhes na seção 10.1.1. Na tag set também está presente o atributo lazy. Ele é utilizado para resolver o seguinte problema:quando se realiza um select em um objeto Universidade implica em serem feitos n (número de centros dauniversidade) outros select’s para buscar os seus centros. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 74 de 140
    • _____________________Curso Struts & Hibernate______________ Dessa forma, a resolução do problema é feita apenas definindo o atributo lazy como sendo true. Acoleção de centros passa a ser lazy-loading, o que significa que somente será recuperada quando solicitada,ou seja, a coleção de centros de uma universidade só seria solicitada caso o programador a acesse através dachamada ao método getCentros().10.1.1 - O atributo inverse Considerando o relacionamento entre uma universidade e seus centros, no mapeamento do conjunto decentros em universidade, o atributo inverse é igual a true. Dessa forma, a criação ou atualização dorelacionamento entre um centro e uma universidade será feita durante a persistência ou atualização de umobjeto Centro. A partir do exemplo apresentado na Tabela 18, cria-se uma instância da classe Universidade e define-seum valor para o atributo nome. Em seguida, uma instância da classe Centro também é criada, definindo o atributo nome e o atributouniversidade (como sendo a instância de Universidade anteriormente criada). Por fim, o objeto Centro criadoé adicionado à coleção de centros do objeto Universidade, o qual é persistido. Tabela 18 - Exemplificando o uso do atributo inverse Universidade univ = new Universidade() univ.setNome("Universidade Federal do Maranhão"); Centro centro = new Centro(); centro.setNome("Centro de Informática Aplicada"); centro.setUniversidade(univ); univ.setCentros(new HashSet<Centro>()); univ.getCentros().add(centro); session.save(univ); A Tabela 19 apresenta o que acontece se o atributo inverse no mapeamento 1-n for definido comofalse. O que acontece é que o Hibernate insere uma linha na tabela UNIVERSIDADE e em seguida tentaatualizar o relacionamento entre uma universidade e um centro, no caso a partir de um UPDATE na tabelaCENTRO, setando a chave estrangeira para a tabela UNIVERSIDADE. Tabela 19 – SQL gerado pelo Hibernate com atributo inverse=false Hibernate: insert into UNIVERSIDADE (nome, ID_ENDERECO,ID_UNIVERSIDADE) values (?, ?, ?) Hibernate: update CENTRO set ID_UNIVERSIDADE=? where ID_CENTRO=? Verifica-se, então, que com o atributo inverse sendo igual a false, o Hibernate tenta atualizar orelacionamento entre uma universidade e um centro logo após a inserção da universidade. Neste caso, como orelacionamento com a universidade está sendo feito com um objeto transiente de um Centro, o que vai ocorreré que o Hibernate vai tentar atualizar a chave estrangeira para a tabela UNIVERSIDADE em uma linha da tabelaCENTRO que não existe, acontecendo o erro exibido na Tabela 20. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 75 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 20 – Erro gerado após teste com o atributo inverse=false no relacionamento 1-n em Universidade ERRO: Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: modelo.Centro ... De acordo com o mapeamento da Tabela 17, o atributo inverse é definido como true. Então, para ocódigo da Tabela 18 vai ser gerado o SQL exibido na Tabela 21. Neste caso, veja que apenas é dado um INSERT na tabela UNIVERSIDADE, ou seja, no momento dainserção de uma universidade o Hibernate não atualiza o relacionamento entre ela e seus centros, pois esperaque ele seja feito no momento da inserção/atualização de um objeto Centro.Tabela 21 - SQL gerado pelo Hibernate com atributo inverse=trueHibernate: insert into UNIVERSIDADE (nome, ID_ENDERECO,ID_UNIVERSIDADE) values (?, ?, ?) Resumindo, se o atributo inverse não for definido como true, o Hibernate não tem como saber qual dosdois lados foi atualizado, ou seja, vai sempre atualizar os dois lados de uma vez, uma atualização para cadaclasse da relação, o que seria desnecessário. Caso contrário, o Hibernate passa, a saber, de qual lado fazer aatualização e fazendo uma única vez.Portanto, para o atributo inverse, é importante levar em consideração os seguintes pontos: O atributo inverse=true só é valido em associações bidirecionais. Não é necessário usar inverse quando somente o lado com elementos <set><one-to-many></set> existir. O atributo inverse define qual lado é responsável pela manutenção da associação. Modificações efetuadas somente no lado que não é responsável pela manutenção da associação não serão persistidas pelo lado contrário, mesmo com inverse=="true". Para garantir, é melhor utilizar o método add. De qualquer maneira, sem no mínimo um parâmetro cascade="save-update", a manutenção da associação deverá ser responsabilidade do programador10.2 Associações n-1 (many-to-one) O relacionamento n-1 será apresentado a partir do relacionamento <manyto-one> existente entre atabela Centro e a tabela Universidade. Neste caso, o relacionamento está presente no mapeamento da classeCentro, como mostrado na Tabela 22. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 76 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 22 - Mapeamento n-1: tabela centro ... <hibernate-mapping> <class name="modelo.Centro" table="CENTRO"> <id name="id" column="ID_CENTRO" type="long"> <generator class="increment"/> </id> <property name="nome" type="java.lang.String"/> <!-- Mapeamento da Universidade --> <many-to-one name="universidade" class="modelo.Universidade" cascade="save-update" fech="join" update="true" insert="true" lazy="false" column="id_universidade"/> <set name="departamentos" lazy="true" inverse="true"> <key column="ID_CENTRO"/> <one-to-many class="modelo.Departamento"/> </set> </class> </hibernate-mapping> Como mostrado no mapeamento da classe Centro, o relacionamento n-1 é mapeado a partir da tag<many-to-one>. Essa tag apresenta um conjunto de atributos, que podem assumir os valores apresentadosna Tabela 23: Tabela 23 – Mapeamento n-1: atributos <many-to-one name="propertyName" class="ClassName" column="column_name" fetch="join|select" update="true|false" lazy="true|false" insert="true|false" cascade="all|none|save-update|delete"/> name: nome do atributo na classe Java; column: coluna do banco de dados. É uma chave estrangeira; class: nome da classe Java da entidade relacionada; insert e update: indica se o atributo será incluído e alterado ou somente lido; cascade: indica com que ação em cascata o relacionamento será tratado. o none: associação é ignorada; o save-update:os objetos associados vão ser inseridos ou atualizados automaticamente quando o objeto "pai" for inserido ou atualizado; o delete: os objetos associados ao objeto "pai" vão ser deletados; o all: junção de delete e save-update; o all-delete-orphan: o mesmo que all, mas o Hibernate deleta qualquer objeto que tiver sido retiradoda associação; o delete-orphan: se o objeto não fizer mais parte da associação, ele removido. fetch: se definido como join é usado para realizar joins sem restrição de nulidade (outer-join). Se for select,um novo select é feito para recuperar a informação da associação. lazy: se igual a true, o objeto só será recuperado se solicitado; se igual a false, o objeto sempre serárecuperado. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 77 de 140
    • _____________________Curso Struts & Hibernate______________10.3 Associações n-n (many-to-many) O relacionamento n-n será feito a partir do relacionamento entre as entidades Departamento e Cursomostrado na Figura 8. (Um curso tem muitos departamentos e um departamento contém muitos cursos) Figura 8 - Relacionamento n-n entre Curso e Departamento Um relacionamento n-n implica em existir uma nova tabela para mapear o relacionamento no banco dedados. Vamos denominar essa nova tabela como DEPARTAMENTO_CURSO, como mostrado na Figura 9. Dessa forma, um departamento possui uma coleção de cursos e um curso uma coleção dedepartamentos. A existência dessas coleções é opcional. Por exemplo, pode ser que em um sistema real não seja necessário saber todos os departamentos dedeterminado curso, mas se for realmente necessário, o Hibernate apresenta outros mecanismos para aobtenção desta informação. Figura 9 - Tabela de relacionamento DEPARTAMENTO_CURSO As classes Java das entidades Departamento e Curso estão ilustradas nas Tabela 24 e Tabela 25,respectivamente. Tabela 24 - Classe de Domínio: Departamento package modelo; import java.util.Collection; public class Departamento implements Serializable{ private long id; private String nome; private String sigla; private Centro centro; private Collection professores; private Collection cursos; // Implementação dos métodos setter e getter } Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 78 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 25 - Classe de Domínio: Curso package modelo; import java.util.Collection; public class Curso implements Serializable{ private long id; private long codigo; private String nome; private String sigla; private Collection departamentos; private Collection alunos; //Implementação dos métodos setter e getter } A Tabela 26 apresenta o mapeamento da classe Departamento. Já a Tabela 27, mostra o mapeamentoda classe Curso: Tabela 26 - Departamento.hbm.xml<hibernate-mapping> <class name="modelo.Departamento" table="DEPARTAMENTO"> <id name="id" column="ID_DEPARTAMENTO" type="long"> <generator class="increment"/> </id> <property name="nome" type="java.lang.String"/> <property name="sigla" type="java.lang.String <many-to-one name="centro" class="modelo.Centro" column="ID_CENTRO" cascade="save-update"/> <set name="professores"> <key column="ID_DEPARTAMENTO"/> <one-to-many class="modelo.Professor"/> </set> <!-- Mapeamento dos cursos --> <set name="cursos" table="DEPARTAMENTO_CURSO" inverse="true"> <key column="ID_DEPARTAMENTO"/> <many-to-many column="ID_CURSO" class="modelo.Curso"/> </set> </class></hibernate-mapping> Tabela 27 - Curso.hbm.xml<hibernate-mapping> <class name="modelo.Curso" table="CURSO"> <id name="id" column="ID_CURSO" type="long"> <generator class="increment"/> </id> <property name="codigo"/> <property name="nome"/> <property name="sigla"/> <set name="alunos"> <key column="ID_CURSO"/> <one-to-many class="modelo.Aluno"/> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 79 de 140
    • _____________________Curso Struts & Hibernate______________ </set> <!-- Mapeamento dos departamentos--> <set name="departamentos" table="DEPARTAMENTO_CURSO"> <key column="ID_CURSO"/> <many-to-many column="ID_DEPARTAMENTO" class="modelo.Departamento"/> </set></class></hibernate-mapping> Observa-se que tanto no mapeamento da coleção cursos em Departamento quanto no da coleçãodepartamentos em Curso, o relacionamento n-n é feito a partir de uma tag set. Os mapeamentos das duas coleções apresentam uma tag key, na qual o atributo column indica a chaveestrangeira do pai na tabela de relacionamento DEPARTAMENTO_CURSO. Apresentam também a tag many-to-many utilizada para indicar a entidade filha e sua chave estrangeira no relacionamento. A única diferença entre o mapeamento das duas coleções é que na tag set de cursos no mapeamentoda entidade Departamento o atributo inverse é igual a true, significando que na tabela DEPARTAMENTO_CURSOsó será inserido o relacionamento entre as duas entidades, quando um curso for inserido no banco de dadosassociado a um departamento. Neste caso, não seria necessário mapear a coleção de cursos em Departamento, pois não está sendoutilizada para popular a tabela de relacionamento. Como já citado, para recuperar a coleção de cursos de um departamento, o Hibernate apresenta outrosmecanismos. Em outros relacionamentos n-n, pode ser que seja necessário inserir/atualizar o relacionamento natabela de relacionamento durante a inserção/atualização de qualquer um dos lados das entidades, portanto,basta que o atributo inverse nas duas coleções seja mapeado como false. O código presente na Tabela 28 cria um instância de um objeto Departamento. Em seguida recuperaum objeto persistente da classe Curso com identificador igual a 1, adiciona esse objeto Curso na coleção decursos do objeto Departamento criado e, por fim, persiste o departamento. O SQL gerado é apresentado na Tabela 29. Observa-se que apenas um SELECT na tabela CURSO é feito e um INSERT na tabela DEPARTAMENTO.Não há uma inclusão de linha na tabela de relacionamento DEPARTAMENTO_CURSO, pois o atributo inverse dacoleção de cursos no mapeamento da classe Departamento foi definido como true. Tabela 28 - Persistência de Departamento Departamento depart = new Departamento(); depart.setNome("Departamento 1"); Curso curso = (Curso)session.get(Curso.class, 1); depart.getCursos().add(curso); session.save(depart); Tabela 29 - SQL para comandos da Tabela 28 Hibernate: select curso0_.ID_CURSO as ID1_0_, curso0_.codigo as codigo1_0_, curso0_.nome as nome1_0_, curso0_.sigla as sigla1_0_, curso0_.ID_COORDENADOR as ID5_1_0_ from CURSO curso0_ where curso0_.ID_CURSO=? Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 80 de 140
    • _____________________Curso Struts & Hibernate______________ Hibernate: insert into DEPARTAMENTO (nome, sigla, ID_CENTRO, ID_CHEFE, ID_DEPARTAMENTO) values (?, ?, ?, ?, ?) Já o código presente na Tabela 30, cria uma instância da classe Curso, busca o objeto persistenteDepartamento de identificador 1 na base de dados, adiciona o departamento à coleção de departamentos doobjeto Curso e realiza a sua persistência. O SQL presente na Tabela 31 mostra que um SELECT foi feito na tabela DEPARTAMENTO, um INSERTna tabela CURSO e um outro INSERT na tabela DEPARTAMENTO_CURSO. Nesse caso, o relacionamento foipersistido, pois no mapeamento da coleção departamentos da classe Curso, como o atributo inversenão foi definido como true, assume-se que ele é false. Tabela 30 - Persistência de Curso Curso curso = new Curso(); Departamento d = (Departamento)session.get(Departamento.class, 1); curso.getDepartamentos().add(d); session.save(curso); Tabela 31 - SQL para comandos da Tabela 30 Hibernate: select departamen0_.ID_DEPARTAMENTO as ID1_0_, departamen0_.nome as nome4_0_, departamen0_.sigla as sigla4_0_, departamen0_.ID_CENTRO as ID4_4_0_, departamen0_.ID_CHEFE as ID5_4_0_ from DEPARTAMENTO departamen0_ wheredepartamen0_.ID_DEPARTAMENTO=? Hibernate: insert into CURSO (codigo, nome, sigla, ID_COORDENADOR, ID_CURSO)values (?, ?, ?, ?, ?) Hibernate: insert into DEPARTAMENTO_CURSO (ID_CURSO, ID_DEPARTAMENTO) values(?, ?)10.4 Associações n-n com Atributos Imagine que seria necessário guardar a data em que foi feita a associação entre um determinado cursoe um determinado departamento, ou seja, necessário ter um novo atributo na tabela DEPARTAMENTO_CURSO.Dessa forma, a tabela DEPARTAMENT_CURSO não seria formada apenas pelos identificadores de curso e dedepartamento, mas sim também pela data. Para essa situação, os mapeamentos dos relacionamentos <many-to-many> nas tabelas Curso eDepartamento não resolveriam o problema. Então, deve-se criar uma nova classe DepartamentoCurso, como mostrado no diagrama da Figura 10.Como pode ser visto nesta figura, existem agora relacionamentos <many-to-one> e uma chave primáriadupla. Figura 10 - Mapeamento n-n com Atributo Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 81 de 140
    • _____________________Curso Struts & Hibernate______________Dessa forma, o mapeamento da tabela DEPARTAMENTO_CURSO seria feito como mostrado na Tabela 32. Tabela 32 - DepartamentoCurso.hbm.xml<hibernate-mapping> <class name="modelo.DepartamentoCurso" table="DEPARTAMENTO_CURSO"> <composite-id name="compositeID" class="modelo.DepartamentoCursoID"> <key-many-to-one name="curso" column="ID_CURSO" class="modelo.Curso"/> <key-many-to-one name="departamento " column="ID_DEPARTAMENTO" class="modelo.Departamento "/> </composite-id> <property name="data" type="java.util.Date" column="data"/> </class></hibernate-mapping>10.4.1 Composite-id Como pode ser visto na Tabela 32, há o mapeamento de uma chave composta. Neste caso, a chave éum objeto da classe Curso e um objeto da classe Departamento. O primeiro passo é a criação de uma classe de domínio para a chave composta, DepartamentoCursoID(Tabela 33).Tabela 33 - Classe de Domínio: DepartamentoCursoID public class DepartamentoCursoID implements Serializable { private Departamento departamento; private Curso curso; //Métodos getter e setter .. Para esse exemplo, a classe DepartamentoCurso possuirá um atributo Date data e um atributoDepartamentoCursoID compositeID. Veja Tabela 34.Tabela 34 - Classe de Domínio: DepartamentoCurso public class DepartamentoCurso implements Serializable{ private DepartamentoCursoID compositeID; private Date data; //Métodos getter e setter } Observando a Tabela 32, vê-se que a tag <composite-id> mapeia a chave composta. O atributo nameinforma o atributo que mapeia a chave composta e o atributo class a classe de domínio, no caso"modelo.DepartamentoCursoID". O corpo da tag é formado por duas outras tags <key-many-to-one> que informam os atributos dachave composta dentro da classe DepartamentoCursoID. Para exemplificar o relacionamento n-n com atributos, observe o exemplo da Tabela 35. Primeiro umdepartamento e um curso são buscados da base de dados, ambos com identificadores iguais a 1. Em seguida, cria-se uma instância de um objeto da classe DepartamentoCursoID que representa achave composta. Os valores que compõem a chave, curso e departamento, são atribuídos. Finalmente, cria-seum objeto da classe DepartamentoCurso que representa a tabela de relacionamento entre as entidades, define-se a sua chave composta e a data de criação, persistindo-o na base de dados. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 82 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 35 - Exemplo: Relacionamento n-n com atributos Departamento d = (Departamento)session.get(Departament1.class, 1); Curso c = (Curso)session.get(Curso.class, 1); DepartamentoCursoID dcID = new DepartamentoCursoID(); dcID.setDepartamento(d); dcID.setCurso(c); DepartamentoCurso dc = new DepartamentoCurso(); dc.setCompositeID(dcID); dc.setData(new Date()); session.save(dc); O resultado da execução do código presente na Tabela 35 pode ser visto na Tabela 36. Tabela 36 - Resultado da execução do código presente na Tabela 35 Hibernate: select departamen0_.ID_DEPARTAMENTO as ID1_0_ from DEPARTAMENTO1 departamen0_where departamen0_.ID_DEPARTAMENTO=? Hibernate: select curso1x0_.ID_CURSO as ID1_0_ from CURSO1 curso1x0_ wherecurso1x0_.ID_CURSO=? Hibernate: insert into DEPARTAMENTO_CURSO (data, ID_CURSO,ID_DEPARTAMENTO) values (?, ?, ?)10.5 Associações 1-1 (one-to-one) Da Figura 6, considere o relacionamento 1-1 entre as entidades Universidade e Endereco, ou seja, umauniversidade tem um único endereço e um endereço pertence apenas a uma única universidade. As Tabela 37 e Tabela 15 apresentam as classes Java para as entidades Universidade e Endereco,respectivamente. Tabela 37 - Classe de Domínio: Endereço package modelo; public class Endereco implements Serializable{ private long id; private String rua; private long numero; private String bairro; private String cidade; private String uf; private long cep; private Universidade universidade;//Implementação dos métodos setter e getter} Existem duas formas de se mapear este relacionamento 1-1. A primeira estratégia é no mapeamento da entidade Universidade adicionar um mapeamento <many-to-one> para a tabela Endereco. O mapeamento da entidade Endereco é visto na Tabela 38 e não apresentanenhuma novidade. Tabela 38 - Endereco.hbm.xml <hibernate-mapping> <class name="modelo.Endereco" table="ENDERECO"> <id name="id" column="ID_ENDERECO" type="int"> <generator class="native"/> </id> <property name="rua"/> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 83 de 140
    • _____________________Curso Struts & Hibernate______________ <property name="numero"/> <property name="bairro"/> <property name="cidade"/> <property name="uf"/> <property name="cep"/> </class> </hibernate-mapping> Para realizar o mapeamento 1-1 de acordo com essa estratégia, basta inserir um mapeamento <many-to-one> no mapeamento da tabela Universidade (Tabela 17), como mostrado na Tabela 39. Tabela 39 – Relacionamento 1-1 em Universidade.hbm.xml: 1ª estratégia ... <many-to-one name="endereco" class="modelo.Endereco" column="ID_ENDERECO" cascade="save-update" unique="true"/> ... Veja que o atributo cascade foi definido como save-update o que implica em o objeto Endereco serinserido ou atualizado automaticamente quando o objeto Universidade for inserido ou atualizado. Nessemapeamento aparece o atributo unique, que quando assume valor true implica em ter apenas umauniversidadepor endereço. A outra abordagem é ao invés de inserir o código da Tabela 39 no mapeamento deUniversidade.hbm.xml, inserir o código mostrado na Tabela 40. A tag <one-to-one> define o relacionamento 1-1 que a classe Universidade tem com a classe Endereco.Os atributos desta tag não são novidades.Tabela 40 - Relacionamento 1-1 em Universidade.hbm.xml: 2ª estratégia...<one-to-one name="endereco"class="modelo.Endereco"cascade="save-update"/>...Para utilizar a tag <one-to-one> no arquivo Universidade.hbm.xml, omapeamento do endereço em Endereco.hbm.xml deve ser feito como mostrado naTabela 41. Tabela 41 - Relacionamento 1-1 em Endereco.hbm.xml: 2ª estratégia ... <hibernate-mapping> <class name=" modelo.Endereco" table="ENDERECO"> <id name="id" column="ID_UNIVERSIDADE" type="long"> <generator class="foreign"> <param name="property">universidade</param> </generator> </id> <property name="rua"/> <property name="numero"/> <property name="bairro"/> <property name="cidade"/> <property name="uf"/> Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 84 de 140
    • _____________________Curso Struts & Hibernate______________ <property name="cep"/> <one-to-one name="universidade" class="modelo.Universidade" constrained="true"/> </class> </hibernate-mapping> A primeira diferença para o mapeamento anterior da entidade Endereco é o valor do atributo class datag generator agora é foreign. A tag param de name igual a property permite a associação 1-1 da classeEndereco com a classe Universidade, o que acontece é que um parâmetro é passado para a classe geradora doidentificador, que neste caso é a propriedade universidade, que é da classe que se relaciona 1-1 com Endereco. A garantia de que um endereço pertença a uma única universidade vem do fato da chave primária deEndereco (ID_UNIVERSIDADE) ser também a chave estrangeira que liga a Universidade. O mapeamento 1-1 em Endereco de Universidade também é feito utilizando a tag <one-to-one>. A única novidade da tag é o atributo constrained que sendo igual a true, implica em existir uma relaçãoentre a chave primária de Endereco e de Universidade, informando ao Hibernate que um endereço não podeexistir sem que uma universidade exista.11. Coleções O mapeamento de coleções já foi apresentado no contexto dos relacionamentos. Essa seção estádestinada a apresentar o mapeamento dos três tipos de coleções existentes: Set, List e Map.11.1 Set Um Set é um conjunto que contém elementos únicos. Como já citado, o seu mapeamento é feitoatravés da tag set e possui o conjunto de atributos mostrado na Tabela 42. Esses atributos são semelhantespara os demais tipos de coleções a serem apresentadas. Tabela 42 - Coleções: Atributos <set name="nomePropriedade” table="nomeTabela" schema="nomeEsquema" lazy="true|false" inverse="true|false" cascade="all|delete|save-update|delete|delete-orphan|all-delete-orphan" sort="unsorted|natural|comparatorClass" order-by="nome_coluna asc|desc" where="condição sql arbitrária"> <key .../> <element .../> | <one-to-many .../> | <many-to-many .../> </set> Dos atributos ainda não apresentados no curso, estão: schema: indica o nome do esquema do banco de dados; sort: a ordenação pode ser feita na classe Java. o unsorted: desordenada o natural: odenada a partir do método equals(...); o comparatorClass: ordenada a partir do método compareTo(); Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 85 de 140
    • _____________________Curso Struts & Hibernate______________ order-by: ordenação feita no banco de dados a partir do nome da coluna informada. Pode ser ascendente ou descendente; where: para informar uma condição arbitrária para a busca da coleção. element: indica que a coleção é formada por um tipo primitivo. Exemplos de Set já foram apresentados nos mapeamentos dos relacionamentos. Para exemplificar omapeamento de um Set de tipos primitivos considere o mapeamento de uma coleção de String’s paraarmazenar os telefones de um Aluno, como visto na Figura 11. Então no mapeamento Aluno.hbm.xml deve ser inserido o mapeamento mostrado na Tabela 43. Figura 11 - Coleção de telefones para Aluno: Set Os telefones do aluno são armazenados na tabela ALUNO_TELEFONE. Para o banco de dados estatabela é separada da tabela ALUNO, mas para o Hibernate, ele cria a ilusão de uma única entidade. A tag keyindica a chave estrangeira da entidade pai (ID_ALUNO). A tag element indica o tipo da coleção (String) e acoluna na qual está a informação. Tabela 43 - Coleções: Set ... <set name="telefones" lazy="true" table="ALUNO_TELEFONE"> <key column="ID_ALUNO"/> <element type="java.lang.String" column="TELEFONE" not-null="true"/> </set> ... Um Set não pode apresentar elementos duplicados, portanto a chave primária de ALUNO_TELEFONEconsiste nas colunas ID_ALUNO e TELEFONE. Dado o mapeamento da coleção de telefones de Aluno, observe o exemplo mostrado na Tabela 44.Neste exemplo, cria-se um objeto Aluno que terá o seu nome definido e um único número de telefone inseridoem sua coleção de String’s. Por fim, o objeto Aluno é persistido. O resultado é mostrado na Tabela 45, onde primeiro é inseridauma linha na tabela ALUNO e posteriormente uma linha na tabela ALUNO_TELEFONE. Tabela 44 - Exemplo de Mapeamento de Set Aluno aluno = new Aluno(); aluno.setNome("João Maria Costa Neto"); aluno.setTelefones(new HashSet<String>()); aluno.getTelefones().add("32222529"); session.save(aluno); Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 86 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 45 - Resultado da execução do código presente na Tabela 44 Hibernate: insert into ALUNO (MATRICULA, NOME, CPF, ID_CURSO, ID_ALUNO) values (?, ?, ?, ?, ?) Hibernate: insert into ALUNO_TELEFONE (ID_ALUNO, TELEFONE) values (?, ?)11.2 List Um List é uma coleção ordenada que pode conter elementos duplicados. O mapeamento de uma listarequer a inclusão de uma coluna de índice na tabela do banco de dados. A coluna índice define a posição do elemento na coleção, como visto na Figura 12 no mapeamento dacoleção de telefones da entidade Aluno como sendo um List. Dessa maneira, o Hibernate pode preservar a ordenação da coleção quando recuperada do banco dedados e for mapeada como um List. Observe o mapeamento da coleção telefones na Tabela 46. Figura 12 - Coleção de telefones para Aluno: List Tabela 46 - Coleções: List ... <list name="telefones" lazy="true" table="ALUNO_TELEFONE"> <key column="ID_ALUNO"/> <index column="POSICAO"/> <element type="java.lang.String" column="TELEFONE" not-null="true"/> </list > ... Mapeando a coleção como um List, a chave primária da tabela ALUNO_TELEFONE passa a ser ascolunas ID_ALUNO e POSICAO, permitindo a presença de telefones (TELEFONE) duplicados na coleção. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 87 de 140
    • _____________________Curso Struts & Hibernate______________11.3 Map Maps associam chaves aos valores e não podem conter chaves duplicadas. Eles diferem de Sets no fatode que Maps contêm chaves e valores, ao passo que Sets contêm somente a chave. O mapeamento de um Map é semelhante ao de um List, onde o índice de posição passa a ser a chave.Veja a Figura 12. A Tabela 47 apresenta a coleção de telefones sendo mapeada como um Map. A chaveprimária da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e CHAVE, também permitindo apresença de telefones duplicados na coleção. Figura 13 - Coleção de telefones para Aluno: Map Tabela 47 - Coleções: Map ... <map name="telefones" lazy="true" table="ALUNO_TELEFONE"> <key column="ID_ALUNO"/> <index column="CHAVE" type="java.lang.String"/> <element type="java.lang.String" column="TELEFONE" not-null="true"/> </map> ...12. Herança O Hibernate fornece vários mecanismos de se realizar o mapeamento de uma relação de herança: Tabela por classe concreta: cada classe concreta é mapeada para uma tabela diferente no banco dedados; Tabela por Hierarquia: todas as classes são mapeadas em uma única tabela; Tabela por Sub-Classe: mapeia cada tabela, inclusive a classe pai, para tabelas diferentes. Observe o exemplo de herança apresentado na Figura 15. Neste caso, as classes Aluno e Professorherdam da classe Pessoa, ou seja, são seus filhos. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 88 de 140
    • _____________________Curso Struts & Hibernate______________ Figura 15 – HerançaAs Figuras Figura 16, Figura 17 e Figura 18 mostram as tabelas que devem ser criadas para as estratégias demapeamento tabela por classe concreta, tabela por hierarquia e tabela por sub-classe, respectivamente. Figura 16 - Tabela por Classe Concreta Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 89 de 140
    • _____________________Curso Struts & Hibernate______________ Figura 17 -Tabela por Hierarquia Figura 18 - Tabela por Sub-Classe Em relação à estratégia tabela por classe concreta, o mapeamento deve ser feito aplicando osconhecimentos já estudados, pois existem duas tabelas independentes. O principal problema dessa estratégia éque não suporta muito bem associações polimórficas. Em banco de dados, as associações são feitas através de relacionamentos de chave estrangeira. Nestecaso, as sub-classes são mapeadas em tabelas diferentes, portanto uma associação polimórfica para a classemãe não seria possível através de chave estrangeira. Outro problema conceitual é que várias colunas diferentes de tabelas distintas compartilham da mesmasemântica, podendo tornar a evolução do esquema mais complexo, por exemplo, a mudança de um tipo deuma coluna da classe mãe implica em mudanças nas várias tabelas mapeadas. Em relação à tabela por hierarquia, o mapeamento deve ser feito como mostrado na Tabela 49. Omapeamento da classe Pessoa é feito para a tabela PESSOA. Para haver a distinção entre as três classes(Pessoa, Aluno e Professor) surge uma coluna especial (discriminator). Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 90 de 140
    • _____________________Curso Struts & Hibernate______________Essa coluna não é uma propriedade da classe persistente, mas apenas usada internamente pelo Hibernate. Nocaso, a coluna discriminator é a TIPO_PESSOA e neste exemplo pode assumir os valores 1 e 2. Esses valores são atribuídos automaticamente pelo Hibernate. Cada sub-classe tem uma tag<subclass>, onde suas propriedades devem ser mapeadas. Tabela 49 - Mapeamento Herança: Tabela por Hierarquia...<hibernate-mapping> <class name="modelo.Pessoa" table="PESSOA" discriminator-value="0"> <id name="id" column="ID_PESSOA" type="long"> <generator class="sequence"> <param name="sequence">pessoa_seq</param> </generator> </id> <!-- Coluna Discriminante --> <discriminator column="TIPO_PESSOA" type="long"/> <!-- Propriedades comuns --> <property name="matricula"/> <property name="nome"/> <property name="cpf"/> <!-- Sub-Classes --> <subclass name="modelo.Aluno" discriminator-value="1"> <many-to-one name="curso" column="ID_CURSO" class="modelo.Curso"/> </subclass> <subclass name="modelo.Professor" discriminator-value="2"> <many-to-one name="departamento" column="ID_DEPARTAMENTO" class="modelo.Departamento"/> </subclass> </class></hibernate-mapping> A estratégia tabela por hierarquia é bastante simples e apresenta o melhor desempenho narepresentação do polimorfismo. É importante saber que restrições ,"não nulas", não são permitidas para omapeamento de propriedades das sub-classes, pois esse mesmo atributo para uma outra sub-classe será nulo. A terceira estratégia, como já citada, consiste em mapear cada classe em uma tabela diferente. Para oexemplo citado, essa estratégia de mapeamento pode ser vista na Tabela 50. Nessa estratégia as tabelas filhascontêm apenas colunas que não são herdadas e suas chaves primárias são também chaves estrangeiras para atabela mãe. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 91 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 50 - Mapeamento Herança: Tabela por Sub-Classe<hibernate-mapping> <class name="modelo.Pessoa" table="PESSOA"> <id name="id" column="ID_PESSOA" type="long"> <generator class="increment"/> </id> <!-- Propriedades comuns --> <property name="matricula"/> <property name="nome"/> <property name="cpf"/> <!--Sub-Classes --> <joined-subclass name="modelo.Aluno" table="ALUNO"> <key column="ID_ALUNO"/> <many-to-one name="curso" column="ID_CURSO" class="modelo.Curso"/> </joined-subclass> <joined-subclass name="modelo.Professor" table="PROFESSOR"> <key column="ID_PROFESSOR"/> <many-to-one name="departamento" column="ID_DEPARTAMENTO" class="modelo.Departamento"/> </joined-subclass> </class></hibernate-mapping> Neste caso, por exemplo, se um objeto da classe Aluno é persistido, os valores das propriedades daclasse mãe são persistidos em uma linha da tabela PESSOA e apenas os valores correspondentes à classe Alunosão persistidos em uma linha da tabela ALUNO. Em momentos posteriores essa instância de aluno persistida pode ser recuperada de um join entre atabela filha e a tabela mãe. Uma grande vantagem dessa estratégia é que o modelo de relacionamento é totalmente normalizado. Observe que no mapeamento, o Hibernate utiliza a tag <joined-class> para realizar o mapeamento porsub-classe. A tag key declara as chaves primárias das sub-classes que são também chaves estrangeiras para achave primária da classe mãe. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 92 de 140
    • _____________________Curso Struts & Hibernate______________13. TransaçõesUma transação é uma unidade de execução indivisível (ou atômica). Isso significa dizer que todas as etapaspertencentes a uma transação são completamente finalizadas ou nenhuma delas termina. Para exemplificar o conceito de transações, considere um exemplo clássico de transferência entrecontas bancárias: transferir R$ 150,00 da conta corrente do cliente A para a conta corrente do cliente B. Basicamente, as operações que compõem a transação são:1º) Debitar R$ 150,00 da conta corrente do cliente A2º) Creditar R$ 150,00 na conta corrente do cliente B Para garantir a consistência do banco, esses passos devem ser executados dentro de uma transação, jáque ela deve ser uma unidade de execução atômica. A transação pode ter dois fins: commit ou rollback,conforme demonstrado na figura 19. Para que um banco de dados garanta a integridade dos seus dados deve possuir quatro características,conhecidas como ACID: Atomicidade, Consistência, Isolamento, Durabilidade. Figura 19 - Estados do sistema durante uma transação13.1 Ambientes Gerenciados e Não Gerenciados As seções seguintes referem-se às definições dos conceitos relacionados a transações JDBC e JTA, ondeaparecem os termos ambientes gerenciados e não gerenciados. Esta seção destina-se a explicar sucintamente o que são esses termos. Os ambientes gerenciados são aqueles caracterizados pela gerência automática de transaçõesrealizadas por algum container. Exemplos de ambientes gerenciados são componentes EJB (Enteprise JavaBeans) executando emservidores de aplicações (JBoss, Geronimo, etc). Já os ambientes não gerenciados são cenários onde não há nenhuma gerência de transação, como porexemplo: Servlets, aplicações desktop, etc.. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 93 de 140
    • _____________________Curso Struts & Hibernate______________13.2 Transações JDBC Uma transação JDBC é controlada pelo gerenciador de transações SGBD e geralmente é utilizada porambientes não gerenciados. Utilizando um driver JDBC, o início de uma transação é feito implicitamente pelomesmo. Embora alguns bancos de dados necessitem invocar uma sentença “begin transaction” explicitamente,com a API JDBC não é preciso fazer isso. Uma transação é finalizada após a chamada do método commit(). Caso algo aconteça de errado, para desfazer o que foi feito dentro de uma transação, basta chamar ométodo rollback(). Ambos, commit() e rollback(), são invocados a partir da conexão JDBC. A conexão JDBC possui um atributo auto-commit que especifica quando a transação será finalizada. Seeste atributo for definido como true, ou seja, se na conexão JDBC for invocado setAutoCommit(true), ativa-se omodo de auto commit. O modo auto commit significa que para cada instrução SQL uma nova transação écriada e o commit é realizado imediatamente após a execução e finalização da mesma, não havendo anecessidade de após cada transação invocar explicitamente o método commit(). Em alguns casos, uma transação pode envolver o armazenamento de dados em vários bancos dedados. Nessas situações, o uso apenas do JDBC pode não garantir a atomicidade. Dessa maneira, é necessárioum gerenciador de transações com suporte a transações distribuídas. A comunicação com esse gerenciador de transações é feita usando JTA (Java Transaction API).13.3 Transações JTA As transações JTA são usadas em um ambiente gerenciável, onde existem transações CMT (ContainerManaged Transactions). Neste tipo de transação não há a necessidade de programação explícita dasdelimitações das transações, esta tarefa é realizada automaticamente pelo próprio container. Para isso, énecessário informar nos descritores dos EJBs a necessidade de suporte transacional às operações e como eledeve gerenciá-lo. O gerenciamento de transações é feito pelo Hibernate a partir da interface Transaction.13.4 API para Transações do Hibernate A interface Transaction fornece métodos para a declaração dos limites de uma transação. A Tabela 51apresenta um exemplo de uso de transações com a interface Transaction.A transação é iniciada a partir da invocação ao método session.beginTransaction(). No caso de um ambiente não gerenciado, uma transação JDBC na conexãoJDBC é iniciada. Já no caso de um ambiente gerenciado, uma nova transação JTA é criada, caso não existanenhuma já criada. Caso já exista uma transação JTA, essa nova transação une-se a existente. A chamada ao método tx.commit() faz com que os dados em memória sejam sincronizados com a basede dados. O Hibernate só realiza efetivamente o commit se o comando beginTransaction() iniciar uma novatransação (em ambos ambientes gerenciado ou não gerenciado). Se o beginTransaction() não iniciar uma nova transação (no caso de transações JTA isso é possível),então o estado em sessão é apenas sincronizado com o banco de dados e a finalização da transação éfeita de acordo com a primeira parte do código fonte que a criou. Se ocorrer algum erro durante a execução do método acaoExecutada(), o método tx.rollback() éexecutado, desfazendo o que foi feito até o momento em que o erro ocorreu. Observa-se que no final do código a sessão é finalizada a partir do comando session.close(), liberando aconexão JDBC e devolvendo-a para o pool de conexões. Tabela 51 - Usando a Interface Transaction do Hibernate Session session = sessions.openSession(); Transaction tx = null; try { Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 94 de 140
    • _____________________Curso Struts & Hibernate______________ tx = session.beginTransaction(); acaoExecutada(); tx.commit(); } catch (Exception e) { if (tx != null) { try { tx.rollback(); } catch (HibernateException he) { //log he and rethrow e } } } finally { try { session.close(); } catch (HibernateException he) { throw he; } }13.5 Flushing Flushing é o processo de sincronizar os dados em sessão (ou em memória) com o banco de dados. Asmudanças nos objetos de domínio em memória feitas dentro do escopo de uma sessão (Session) não sãoimediatamente propagadas para o banco de dados. Isso permite ao Hibernate unir um conjunto de alterações e fazer um número mínimo de interaçõescom o banco de dados, ajudando a minimizar a latência na rede. A operação de flushing ocorre apenas em três situações: quando é dado commit na transação, algumasvezes antes de uma consulta ser executada (em situações que alterações podem influenciar em seu resultado)e quando o método Session.flush() é invocado. O HIbernate possui um modo flush que pode ser definido a partir do comando session.setFlushMode().Este modo pode assumir os seguintes valores: FlushMode.AUTO: valor padrão. Faz com que o Hibernate não realize o processo de flushing antes de todasas consultas, somente realizará se as mudanças dentro da transação alterar seu resultado. FlushMode.COMMIT: especifica que os estados dos objetos em memória somente serão sincronizados com abase de dados ao final da transação, ou seja, quando o método commit() é chamado. FlushMode.NEVER: especifica que a sincronização só será realizado diante da chamada explícita ao métodoflush().13.6 Níveis de Isolamento de uma Transação As bases de dados tentam assegurar que uma transação ocorra de forma isolada, ou seja, mesmo queestejam acontecendo outras transações simultaneamente, é como se ela estivesse ocorrendo sozinha. O nível de isolamento de uma transação especifica que dados estão visíveis a uma sentença dentro deuma transação. Eles impactam diretamente no nível de acesso concorrente a um mesmo alvo no banco dedados por transações diferentes. Geralmente, o isolamento de transações é feito usando locking, que significa que uma transação podebloquear temporariamente um dado para que outras transações não o acessem no momento que ela o estáutilizando. Muitos bancos de dados implementam o nível de isolamento de uma transação através do modelo decontrole concorrente multi-versões (MCC – Multiversion Concorrency Control). Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 95 de 140
    • _____________________Curso Struts & Hibernate______________ Dentre alguns fenômenos que podem ocorrer devido à quebra de isolamentode uma transação estão três: Dirty Read (Leitura Suja): uma transação tem acesso a dados modificados por uma outra transação aindanão finalizada que ocorre concorrentemente. Isso pode causar problema, pois pode ocorrer um erro dentro datransação que está modificando os dados e as suas alterações serem desfeitas antes de confirmadas, então épossível que a transação que acessa os dados já modificados esteja trabalhando se baseando em dadosincorretos. Nonrepeatable Read (Leitura que não pode ser repetida): uma transação lê mais de uma vez ummesmo dado e constata que há valores distintos em cada leitura. Por exemplo, uma transação A lê uma linhado banco; uma transação B modifica essa mesma linha e é finalizada (commit) antes que a transação A; atransação A lê novamente esta linha e obtém dados diferentes. Phantom Read (Leitura Fantasma): em uma mesma transação uma consulta pode ser executada mais deuma vez e retornar resultados diferentes. Isso pode ocorrer devido a uma outra transação realizar mudançasque afetem os dados consultados. Por exemplo, uma transação A lê todas as linhas que satisfazem umacondição WHERE; uma transação B insere uma nova linha que satisfaz a mesma condição antes da transação Ater sido finalizada; a transação A reavalia a condição WHERE e encontra uma linha “fantasma” na mesmaconsulta feita anteriormente. Existem quatro níveis de isolamento da transação em SQL. Eles se diferenciam de acordo com aocorrência ou não dos fenômenos anteriormente descritos, como mostrado na Tabela 52. Tabela 52 - Níveis de Isolamento da Transação em SQLObs. Esses comentários em vermelho são para deixar em negrito. A escolha do nível de isolamento Read Uncommited não é recomendada para banco de dadosrelacionais, já que permite ler inconsistências e informações parciais (mudanças realizadas por uma transaçãoainda não finalizada podem ser lidas por outra transação). Se a primeira transação não for concluída, mudançasna base de dados realizadas pela segunda transação podem deixá-la com um estado inconsistente. Com o nível Read Commited, uma transação somente visualiza mudanças feitas por outras transaçõesquando confirmadas, permitindo que transações só acessem estados consistentes do banco. No caso de uma atualização/exclusão de uma linha de alguma tabela por uma transação, pode ser quea mesma tenha acabado de ser modificada por uma transação concorrente. Nesta situação, a transação que pretende atualizar fica esperando a transação de atualização queiniciou primeiro ser efetivada ou desfeita. Se as atualizações da primeira transação forem desfeitas, seus efeitos serão desconsiderados e asegunda transação efetivará suas mudanças considerando a linha da tabela anteriormente lida. Caso contrário, a segunda transação irá ignorar a atualização caso a linha tenha sido excluída ouaplicará a sua atualização na versão atualizada da linha. O nível Repeatable Read não permite que uma transação sobrescreva os dados alterados por umatransação concorrente. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 96 de 140
    • _____________________Curso Struts & Hibernate______________ Uma transação pode obter uma imagem completa da base de dados quando iniciada. Este nível é idealpara a geração de relatórios, pois em uma mesma transação, um registro é lido diversas vezes e seu valor semantém o mesmo até que a própria transação altere seu valor. Em relação ao nível Serializable, ele fornece o nível de isolamento de transação mais rigoroso. Elepermite uma execução serial das transações, como se todas as transações fossem executadas uma atrás daoutra. Dessa forma, pode-se perder muita performance da aplicação, principalmente em ambientesmultiusuários.13.9 Configurando o nível de isolamentoNo Hibernate cada nível de isolamento é identificado por um número: 1: Read Uncommited 2: Read Commited 4: Repeatable Read 8: Serializable Para configurá-lo basta incluir a linha presente na Tabela 53 no arquivo de configuração *.cfg.xml.Neste exemplo, o nível de isolamento foi definido como Repeatable Read. Tabela 53 – Configuração do Nível de Isolamento hibernate.connection.isolation = 414. Concorrência Em algumas situações pode acontecer que duas ou mais transações que ocorrem paralelamente leiam eatualizem o mesmo dado. Considerando que duas transações leiam um mesmo dado x quase que simultaneamente.Ambas as transações vão manipular esse mesmo dado com operações diferentes e atualizá-lo na base dedados. Para exemplificar, a Tabela 54 apresenta um exemplo de duas transações concorrentes manipulando omesmo dado x. No primeiro passo, ambas as transações lêem o dado x com o mesmo valor (2). Em seguida, T1 soma ovalor x que leu com 1 e o valor de x para T1 passa a ser 3 (2 + 1). Já T2, soma o valor de x lido a 3 e x passaa ter o valor 5 (2 + 3). Por fim, ambos T1 e T2 gravarão os novos valores de x calculados na base de dados, respectivamente.Como não há controle de concorrência de acesso ao dado x, o seu valor final corresponderá a 5, ou seja, ovalor calculado por T2, significando que as alterações feitas por T1 foram descartadas. Tabela 54 – Exemplo de Transação Concorrente1) Transação 1 (T1) lê x = 22) Transação 2 (T2) lê x = 23) T1 faz x = x + 14) T2 faz x = x + 35) T1 armazena o valor de x na base de dados6) T2 armazena o valor de x na base de dados Para evitar a situação descrita anteriormente, deve-se controlar o acesso concorrente ao dado, ou seja,deve-se implementar o mecanismo de Locking. O gerenciamento de locking e da concorrência pode ser feito de duas formas: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 97 de 140
    • _____________________Curso Struts & Hibernate______________ Pessimista: utilizar o controle pessimista significa que se uma transação T1 lê um dado e tem a intenção deatualizá-lo, esse dado será bloqueado (nenhuma outra transação poderá lê-lo) até que T1 o libere, ormalmenteapós a sua atualização. Otimista: utilizar o controle otimista significa que se T1 lê e altera um dado ele não será bloqueado duranteo intervalo entre a leitura e atualização. Caso uma outra transação T2 tenha lido esse mesmo dado antes de T1o atualizá-lo tente alterá-lo em seguida na base de dados, um erro de violação de concorrência deve sergerado.14.1 Lock Otimista Para ilustrar o gerenciamento do tipo otimista, um exemplo é dado a partir das Figura 20 e Figura 21.O problema é mostrado na Figura 20, onde, inicialmente, duas transações (ilustradas por Thread 1 e Thread 2)acessam um mesmo dado na base de dados (SELECT Dado), uma seguida da outra. Logo em seguida, aprimeira transação (Thread 1) atualiza este dado na base de dados e depois quem também o atualiza é asegunda transação (Thread 2). Nesta abordagem otimista, acontece que a atualização do dado feita pela segunda transaçãosobrescreve a atualização realizada pela primeira, ou seja, a atualização feita pela primeira transação éperdida. Figura 20 - Locking Otimista 1 Para resolver o problema descrito anteriormente com a abordagem otimista, pode-se utilizar o conceitode Version Number, que é um padrão utilizado para versionar numericamente os dados de uma linha de umatabela na base de dados. Por exemplo, na Figura 21, também, inicialmente, duas transações (ilustradas por App 1 e App 2)acessam um mesmo dado na base de dados (SELECT Dado), uma seguida da outra. Com isso, esse mesmo dado nas duas transações são rotulados com a versão atual dele na base dedados, no caso, Versão 1. Logo em seguida, a segunda transação atualiza este dado.Quando a atualização vai ser feita, é verificado se a versão do dado na transação corresponde à versão dele nabase de dados. Nesta primeira atualização, a versão da transação é 1 e a da base de dados também. Como elas são iguais, a atualização é efetivada e a versão do dado na base de dados passa a ser aVersão 2. Por fim, a primeira transação vai também atualizar este mesmo dado. Dessa forma, também é feitauma comparação entre as versões do dado na transação e na base de dados. Neste caso, a versão na transação é a 1 e na base de dados é 2, ou seja, as versões não correspondem. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 98 de 140
    • _____________________Curso Struts & Hibernate______________Assim, um erro é disparado e a atualização desejada pela primeira transação não é concretizada, evitando quea atualização feita pela segunda transação não seja desfeita. Figura 21 - Locking Otimista 2 Com o Hibernate, uma forma de utilizar o versionamento dos dados é utilizar o elemento version nomapeamento das tabelas.Para exemplificar o seu uso, considera-se a classe ContaCorrente na Tabela 55 que será mapeada para a tabelaCONTA_CORRENTE na base de dados. Dentre os diversos atributos da classe, está o atributo denominado versao que irá justamente guardar aversão atual das linhas da tabela. A tabela CONTA_CORRENTE também deve ter uma coluna para onde esseatributo versao será mapeado. Tabela 55 – Classe de Domínio: ContaCorrente 1 package modelo; public class ContaCorrente{ //Atributo utilizado para o versionamento private long versao; //Demais atributos private long id; private double saldo; private Correntista correntista; //Outros atributos //... public long getVersao(){ return versao; } public setVersao(long versao){ this.versao = versao; } //Demais métodos de acesso e modificação de dados //...} No arquivo de mapeamento da classe ContaCorrente, ContaCorrente.hbm.xml (ver Tabela 56), oatributo version é utilizado para mapear o atributo versao da classe ContaCorrente para a coluna VERSAO da Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 99 de 140
    • _____________________Curso Struts & Hibernate______________tabela CONTA_CORRENTE. Com esse mapeamento, toda vez que uma determinada linha for atualizada na basede dados, a sua coluna VERSAO será incrementada de uma unidade, indicando a nova versão dos dados. Tabela 56 - ContaCorrente.hbm.xml 1<hibernate-mapping> <class name=" modelo.ContaCorrente" table="CONTA_CORRENTE"> <id name="id" column="ID_CONTA" type="long"> <generator class="sequence"> <param name="sequence">conta_seq</param> </generator> </id> <version name="versao" column="VERSAO"/> <property name="saldo" type="double" column="SALDO"/> <many-to-one name="correntista" class="modelo.Correntista" column="ID_CORRENTISTA"/> <!-- Demais Atributos --> </class></hibernate-mapping> Outra forma de implementar o lock otimista é utilizando o atributo timestamp no mapeamento databela. Neste caso, a classe ContaCorrente do exemplo anterior ao invés de ter um atributo inteiro para guardara versão do dado, teria uma atributo do tipo java.util.Date para guardar o instante no tempo da últimaatualização. Neste caso, a classe de domínio seria equivalente à mostrada na Tabela 57 e seu mapeamento aoexibido na Tabela 58. Neste exemplo, a tabela CONTA_CORRENTE deve conter uma coluna do tipo timestampdenominada DATA_ULTIMA_ATUALIZACAO. Tabela 57 – Classe de Domínio: ContaCorrente 2 package modelo; public class ContaCorrente{ //Atributo utilizado para o versionamento private Date ultimaAtualizacao; //Demais atributos //... public Date getUltimaAtualizacao(){ return ultimaAtualizacao; } public setUltimaAtualizacao(Date ultimaAtualizacao){ this.ultimaAtualizacao = ultimaAtualizacao; } //Demais métodos de acesso e modificação de dados //... } Tabela 58 - ContaCorrente.hbm.xml 2 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 100 de 140
    • _____________________Curso Struts & Hibernate______________<hibernate-mapping> <class name="modelo.ContaCorrente" table="CONTA_CORRENTE"> <id name="id" column="ID_CONTA" type="long"> <generator class="sequence"> <param name="sequence">conta_seq</param> </generator> </id> <timestamp name="ultimaAtualizacao" column="DATA_ULTIMA_ATUALIZACAO"/> <!-- Demais Atributos --> </class></hibernate-mapping> Se a tabela não possuir uma coluna para guardar a versão do dado ou a data da última atualização,com Hibernate, há uma outra forma de implementar o lock otimista, porém essa abordagem só deve serutilizada para objetos que são modificados e atualizados em uma mesma sessão (Session). Se este não for o caso, deve-se utilizar uma das duas abordagens citadas anteriormente. Com essa última abordagem, quando uma determinada linha vai ser atualizada, o Hibernate verifica seos dados dessa linha correspondem aos mesmos dados que foi recuperado. Caso afirmativo, a atualização é efetuada. Para isso, no mapeamento da tabela, deve-se incluir oatributo optimistic-lock (Tabela 59). Por exemplo, no mapeamento da classe ContaCorrente, na tag class apareceria este atributo. Tabela 59 - ContaCorrente.hbm.xml 3<hibernate-mapping> <class name="modelo.ContaCorrente" table="CONTA_CORRENTE" optimist-lock="all"> <id name="id" column="ID_CONTA" type="long"> <generator class="sequence"> <param name="sequence">conta_seq</param> </generator> </id> <property name="saldo" type="double" column="SALDO"/> <property name="descricao" type="java.lang.String" column="DESCRICAO"/> <many-to-one name="correntista" class="modelo.Correntista" column="ID_CORRENTISTA"/> <!-- Demais Atributos --> </class></hibernate-mapping> Dessa maneira, quando uma linha dessa tabela fosse atualizada, o SQL equivalente gerado para aatualização seria o exibido na Tabela 60. Neste exemplo, considera-se a atualização do saldo para R$ 1.500,00 de uma determinadaconta de saldo R$ 1.000,00.Tabela 60 – Exemplo optimist-lock="all" UPDATE CONTA_CORRENTE SET SALDO = 1500 WHERE ID_CONTA = 104 AND SALDO = 1000 AND DESCRICAO = "DESCRICAO DA CONTA" AND ID_CORRENTISTA = 23 Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 101 de 140
    • _____________________Curso Struts & Hibernate______________14.2 Lock Pessimista A estratégia de lock pessimista para proibir o acesso concorrente a um mesmo dado da base de dados éfeita bloqueando o mesmo até que a transação seja finalizada. Alguns banco de dados, como o Oracle e PostgreSQL, utilizam a construção SQL SELECT FOR UPDATEpara bloquear o dado até que o mesmo seja atualizado. O Hibernate fornece um conjunto de modos de lock (constantes disponíveis na classe LockMode) quepodem ser utilizados para implementar o lock pessimista. Considerando o exemplo da Tabela 61, onde um determinado aluno é consultado na base de dados etem seu nome atualizado.Neste caso, não há um bloqueio ao dado, então qualquer outra transação pode acessar este mesmo dadoconcorrentemente e modifica-lo, de forma que poderá ocorrer uma incosistência dos dados. Na Tabela 62, há um exemplo de uso do lock pessimista para resolver este problema, bastando passara constante LockMode.UPGRADE como terceiro argumento do método get do objeto Session. Tabela 61 – Transação sem LockTransaction tx = session.beginTransaction();Aluno aluno = (Aluno) session.get(Aluno.class, alunoId);aluno.setNome("Novo Nome");tx.commit(); Tabela 62 – Transação com Lock Pessimista: LockMode.UPGRADETransaction tx = session.beginTransaction();Aluno aluno =(Aluno) session.get(Aluno.class, alunoId, LockMode.UPGRADE);aluno.setNome("Novo Nome");tx.commit(); O método get do objeto Session pode receber como terceiro argumento para implementar o lockpessimista as seguintes constantes: Lock.NONE: Só realiza a consulta ao banco se o objeto não estiver no cache1. Lock.READ: Ignora os dados no cache e faz verificação de versão para assegurar-se de que o objeto emmemória é o mesmo que está no banco. Lock.UPDGRADE: Ignora os dados no cache, faz verificação de versão (se aplicável) e obtém lockpessimista do banco (se suportado). Lock.UPDGRADE_NOWAIT: Mesmo que UPGRADE, mas desabilita a espera por liberação de locks, edispara uma exceção se o lock não puder ser obtido. Caso especial do Oracle que utiliza a cláusula SELECT ...FOR UPDATE NOWAIT para realizar locks. Lock.WRITE: Obtida automaticamente quando o Hibernate realiza alguma inserção ou atualização na basede dados. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 102 de 140
    • _____________________Curso Struts & Hibernate______________15. Busca de Dados A busca de dados utilizando Hibernate pode se dar através do uso de HQL (Hibernate QueryLanguange), Criteria, SLQ Nativo ou Query By Example, que serão apresentados neste capítulo.15.1 SQL Nativo SQL Nativo deve ser usado em Hibernate quando este não prover uma forma para realizar a consultadesejada, como, por exemplo, uma consulta hierárquica, pois Hibernate não suporta. Quando isto acontecer, aAPI JDBC pode ser utilizada diretamente.15.2 Hibernate Query Language - HQL HQL é uma linguagem de consulta semelhante à OQL (Object Query Language), no entanto voltadapara bancos de dados relacionais. Pertence a família do SQL, podendo ser facilmente compreendida através de algum conhecimento emSQL. HQL suporta polimorfismo, herança e associações, pode incluir na consulta, restrições nas propriedadesda classe e associações, suporta ainda agregação, ordenação, paginação, subconsultas, outer joins, chamadasde funções SQL e projeção, que permite buscar apenas os dados necessários, não sendo necessário carregartodo o objeto e suas associações, a projeção é muito utilizada por relatórios. Como SQL, esta linguagem é utilizada apenas para consulta, isto é, não é uma linguagem demanipulação de dados (DML). Uma simples consulta usando HQL pode ser realizada através da cláusula from, mostrada na Tabela63, onde temos a consulta à lista de todos os alunos, se desejar usar Aluno em outra parte da consulta bastacriar um “alias”, neste caso usamos aluno, a palavra chave as pode ser omitida e podemos ter vários aliases. Por padronização é indicado usar o modelo Java de variáveis locais. Tabela 63 – HQL: Cláusula from from Aluno from Aluno as aluno from Aluno aluno from Aluno as aluno, Professor as prof Em HQL, como SQL, há o suporte a operadores matemáticos (+, -, * e /), operadores de comparação(<, >, <>, <=, >=, =, between, not between, in e not in), operadores lógicos (or, and e parênteses paraagrupar expressões), o operador LIKE e o símbolo ‘%’ também podem ser utilizados para pesquisas em String,além de poder ordenar sua pesquisa em ordem descendente ou ascendente. Vejamos alguns exemplos em HQLna Tabela 64. Tabela 64 - Expressões HQLfrom Aluno aluno where aluno.matricula >= 35from Endereco end where ( end.rua in ("Bernardo Vieira", "Prudente de Morais") ) or ( end.numero between 1 and 100 )from Professor p where p.nome like "João%"from Aluno aluno order by aluno.nome asc Com HQL também é possível utilizar joins para associar dados de duas ou mais relações. Como porexemplo as tabelas Curso e Aluno. Para exemplificar os casos de joins, serão utilizados os dados abaixo dastabelas ALUNO e CURSO (Tabela 65 e Tabela 66). As consultas e resultados são apresentados as Tabela 67 e Tabela 68. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 103 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 65 - Dados da tabela ALUNO id_aluno nome Matricula cpf id_curso 1 João 123 055.352.254-33 1 2 Maria 124 321.055.321-22 2 3 Fernanda 125 125 254.365.654-36 1 4 André 126 126 354.254.256-65 1 Tabela 66 - - Dados da tabela CURSO id_curso codigo nome sigla departamento 1 1111 CURSO 1 C1 1 2 2222 CURSO 2 C2 1 3 3333 CURSO 3 C3 1 Tabela 67 - Inner Join ou Joinfrom Curso c inner join Aluno a on c.id = a.curso.idOu:from Curso c join Aluno a on c.id = a.curso.idResultado (omitidos matrícula e cpf de Aluno e código, sigla e departamento de Curso): id_curso nome id_aluno nome id_curso 1 CURSO 1 1 João 1 2 CURSO 2 2 Maria 2 1 CURSO 1 3 Fernanda 1 1 CURSO 1 4 André 1 Tabela 68 - Left outer join ou left joinfrom Curso c left outer join Aluno a on c.id = a.curso.idOu:from Curso c left join Aluno a on c.id = a.curso.idResultado (omitido matricula e cpf de Aluno e código, sigla e departamento deCurso): id_curso nome id_aluno nome id_curso 1 CURSO 1 1 João 1 2 CURSO 2 2 Maria 2 1 CURSO 1 3 Fernanda 1 1 CURSO 1 4 André 1 3 CURSO 3 As consultas HQL normalmente não explicitam os joins. As associações já são informadas nomapeamento das classes Java, o Hibernate com a informação no documento do mapeamento deduz os joinsnecessários nas tabelas. Isto facilita as escritas das consultas. Existem quatro maneiras de realizar os joins, são: Joinordinários (no from), Fetch Joins (usado para coleções), Estilos Theta (entre classes não associadas) e Joinsimplícitos, quando se utiliza o operador de acesso ‘.’. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 104 de 140
    • _____________________Curso Struts & Hibernate______________ Para enviar uma consulta HQL para o banco de dados, uma interface chamada Query é utilizada pararepresentar a consulta. A Tabela 69 apresenta um objeto Query sendo instanciado para fazer consultas da tabela ALUNO. Ocomando q.list() faz com que todos os alunos cadastrados sejam retornados, já que a HQL utilizada foi “fromAluno”. Tabela 69 - Obtendo o resultado de uma consulta ao banco usando QueryQuery q = session.createQuery("from Aluno");q.list(); A Tabela 70 apresenta em exemplo de consulta que retorna todos os cursos que possuem nomescomeçados pela letra A. Já a consulta da Tabela 71 retorna todos os cursos que possui departamento com identificador igual a2. Tabela 70 - Exemplo com QueryString hql = "from Curso c where c.nome like ‘A%’";Query q = session.createQuery(hql);q.list(); Tabela 71 - Exemplo com QueryString hql = "from Curso c where c.departamento.id = 2";Query q = session.createQuery(hql);q.list(); A Tabela 72 apresenta um exemplo de consulta com a interface Query no estilo Theta. Tabela 72 - Exemplo com Query no Estilo Theta String hql = "from Aluno a, LogRecord log where a.id = log.aluno.id"; Query q = session.createQuery(hql); Iterator it = q.list.iterator(); while ( i.hasNext() ) { Object[] obj = (Object[]) i.next(); Aluno aluno = (Aluno) obj[0]; LogRecord log = (LogRecord) obj[1]; } Com o estilo Theta obtemos dados por meio de Projeções, que é uma maneira de se recuperar apenasalguns dados da classe mapeada. A Tabela 73 apresenta um exemplo dessa consulta. Tabela 73 - Exemplo Consulta de ProjeçãoString hql = "select c.nome, a.nome from Curso c, Aluno a where a.curso.id = c.id";Query q = session.createQuery(hql);ArrayList resultado = new ArrayList(); Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 105 de 140
    • _____________________Curso Struts & Hibernate______________Iterator it = q.list.iterator(); while ( i.hasNext() ) { Object[] obj = (Object[]) i.next(); Curso curso = new Curso(); curso.setNome(obj[0].toString()); Aluno aluno = new Aluno(); aluno.setNome(obj[1].toString()); aluno.setCurso(curso); resultado.add(aluno);} HQL suporta ainda funções agregadas como: avg(...), sum(...), min(... ), max(...), count(*), count(...), count(distinct ...) e count(all ...). A consulta que retorna valores agregados permite que estes sejam agrupados por classes ou mesmopor atributos. A cláusula utilizada é group by. A Tabela 74 mostra exemplos com funções de agregação e group by. Tabela 74 - Exemplos HQL: Agregação e Group Byselect count(*) from Alunoselect min(a.matricula), max(a.matricula) from Aluno aselect c.nome, count(c.id_departamento) from Curso c group by c.nome Com HQL também é possível informar parâmetros da consulta após a criação das Query, basta queesses parâmetros recebam nomes. Por exemplo, no exemplo da Tabela 75, deseja-se saber todos os alunos que possuem determinadonome. Na criação da Query, o nome dos alunos buscados é nomeado a partir do parâmetro :nome que éinformado posteriormente usando-se o comando q.setString("nome","João"). Assim, q.list() retornará todos os alunos de nome João. Resumindo, nomeia-se um parâmetro através de ":<nome_parametro>" e em seguida, define-se o seuvalor. Tabela 75 - Exemplo Query: Nomeação de ParâmetrosQuery q = createQuery("from Aluno a where a.nome = :nome");q.setString("nome", "João");q.list();15.3 Criteria A API Query By Criteria (QBC) permite realizar consultas por manipulação de critérios em tempo deexecução. Esta abordagem permite definir restrições dinamicamente sem que haja manipulação de Strings, a suaflexibilidade e poder é bem menor do que HQL e não suporta agregações nem projeções. Nas tabelas abaixo podemos ver simples exemplo utilizando Criteria, o Session é uma fábrica de criaçãode objetos Criteria. Um objeto Criteria é obtido a partir do objeto Session, como mostrado no exemplo da Tabela 76. Nesse exemplo todas as instâncias de alunos presentes na tabela ALUNO são retornadas. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 106 de 140
    • _____________________Curso Struts & Hibernate______________ Tabela 76 - Obtendo um CriteriaCriteria criteria = session.createCriteria(Aluno.class);criteria.list(); As Tabela 77 e Tabela 78 apresentam exemplos de consultas utilizando o objeto Criteria. Tabela 77 – Exemplo de Criteria com RestriçõesCriteria criteria = session.createCriteria(Aluno.class);criteria.add(Expression.eq("nome", "Maria");criteria.add(Order.asc(“matricula”);criteria.list(); Tabela 78 – Exemplo de Criteria com Restrições LikeCriteria criteria = session.createCriteria(Aluno.class);criteria.add(Expression.like("nome", "Maria%");criteria.add(Order.asc("matricula");criteria.list(); Com Criteria é possível consultar associações de classes usando createCriteria(). Podendo existir váriosníveis de subcriterias. Veja um exemplo na Tabela 79. Tabela 79 – Sub-CriteriaCriteria criteria = session.createCriteria(Centro.class);Criteria subCrit = criteria.createCriteria("universidade");subCrit.add(Expression.eq("id", 1);criteria.list();15.4 Query By Example Uma extensão da API Criteria, o Query By Example (QBE), cria uma instância da classe utilizada comalguns valores das propriedades setados, retornando todos os objetos persistentes que possuam os valores daspropriedades. Veja exemplo na Tabela 80. Tabela 80 – Query By ExampleAluno aluno = new Aluno();aluno.setNome("João");Criteria criteria = session.createCriteria(Aluno.class);Criteria.add(Example.create(aluno);criteria.list();15.5 Paginação Paginação é uma forma de limitar uma consulta muito grande ao banco de dados. A paginação pode serrealizada utilizando a interface Query ou mesmo utilizando a API Criteria. Nas Tabela 81 e Tabela 82 seguem exemplos utilizando paginação com o Query e o Criteria,respectivamente. Nesses exemplos, o resultado será os alunos encontrados a partir do décimo até o quadragésimo. Tabela 81 - Paginação QueryQuery q = session.createQuery(“from Aluno”);q.setFirstResult(10); Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 107 de 140
    • _____________________Curso Struts & Hibernate______________q.setMaxResults(30);q.list(); Tabela 82 - Paginação CriteriaCriteria criteria = session.createCriteria(Aluno.class);criteria.setFirstResult(10);criteria.setMaxResults(30);criteria.list();15.6 Named Query Qual é o melhor lugar para colocar as consultas HQL? 1. Digitar o HQL “hard coded”, isto é, no meio do código fonte? Ou: 2. Colocar as consultas em um arquivo xml, podendo tais consultas serem modificadas sem precisar recompilar todo o sistema? Nem sempre é tão fácil responder a esta questão, mas para a segunda opção, o Hibernate fornece uma alternativa chamada named query (consulta nomeada). Esse mecanismo permite você declarar as consultas HQL dentro de um arquivo hbm.xml e atribuir um nome à mesma. Na tabela 83 pode-se verificar dois exemplos de named queries. Notar que as consultas aparecem no meio de tags <![CDATA[...]]>. Isto é necessário porque muitas vezes em HQL precisaremos utilizar sinais que para o interpretador de XML podem parecer elementos de tags (Sinais de <, > ou <> por exemplo). Na tabela 84 verificamos como recuperar e executar uma consulta. Notar que as named queries devem ficar fora do elemento <class> de um arquivo hbm.xml. Tabela 83 – Exemplos de declarações de named queries ... </class> <!— Consultar usuário por login --> <query name="validarLogin"> <![CDATA[from Usuario u where u.login = :login]]> </query> <!— Consultar todos usuarios --> <query name="listarUsuarios"> <![CDATA[from Usuario]]> </query> </hibernate-mapping> Tabela 84 – Recuperação, parametrização e execução de uma named query Session session = HibernateUtility.getSession(); Query query = session.getNamedQuery("validarLogin"); query.setString("login", usr.getLogin()); return query.list(); Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 108 de 140
    • _____________________Curso Struts & Hibernate______________16. Hibernate com Anotações e JPA16.1 IntroduçãoRecentemente, o mapeamento objeto relacional utilizando Hibernate passou a ser feito também a partir deanotações, de forma que se tornou mais simples, possibilitando uma maior produtividade no desenvolvimentode aplicações.Sobre a JPAPosteriormente devido ao grande sucesso obtido pelo Hibernate, o mesmo foi adotado como base para aespecificação JPA (Java Persistence API, vide http://www.jcp.org/en/jsr/detail?id=317), especificação esta quese tornou a principal engrenagem da tecnologia EJB versão 3.0. Atualmente existem duas implementações da especificação JPA: A implementação do próprio Hibernate (a qualserá abordada neste curso) e a implementação TopLink desenvolvida pela Oracle(http://www.oracle.com/technology/products/ias/toplink/index.html).O que é uma anotação? As anotações podem ser definidas como metadados que aparecem no código fonte e são ignorados pelocompilador. Qualquer símbolo em um código Java que comece com uma @ (arroba) é uma anotação. Esterecurso foi introduzido na linguagem Java a partir da versão Java SE 5.0. Em outras palavras, as anotaçõesmarcam partes de objetos de forma que tenham algum significado especial.A Listagem 2 apresenta um exemplo de um tipo de anotação denominado de TesteAnotacao e do seu uso emum método qualquer (metodoTeste), respectivamente. O exemplo é meramente ilustrativo, de forma que otipo de anotação definido não agrega nenhum significado especial ao código fonte.@TesteAnotacaopublic void metodoTeste{ ...}Listagem 1 – Exemplo ilustrativo para o uso de um tipo de anotaçãoInicialmente, o mapeamento objeto relacional com Hibernate era feito a partir de um conjunto de configuraçõesem arquivos XMLs. Com o surgimento das anotações no Java SE 5.0, o framework Hibernate anexou esterecurso, permitindo que as classes Java fossem mapeadas a partir de anotações, simplificando o seu uso. Apróxima seção apresentará um exemplo simples do uso da persistência de uma classe com HibernateAnnotations.Ativando o JPA no seu projeto HibernatePara que o Hibernate com anotações e JPA seja ativado, devem ser copiados as seguintes bibliotecas parao seu classpath:ejb3-persistence.jarhibernate-annotations.jarlucene-core-2.0.0.jarPara que tudo funcione será necessário instanciar um objeto do tipoorg.hibernate.cfg.AnnotationConfiguration ao invés de um org.hibernate.cfg.Configuration, ou utilizaras API´s específicas da JPA: javax.persistence.PersistenceManager ejavax.persistence.EntityManagerFactory, que substituem respecitivamente as classes Session eSessionFactory. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 109 de 140
    • _____________________Curso Struts & Hibernate______________16.2 Exemplo Simples com AnotaçõesInicialmente, para que o Hibernate soubesse como carregar e armazenar objetos de classes persistentes, eramutilizados apenas arquivos de mapeamento XML. Dessa forma, era possível informar que tabela do banco dedados se refere uma dada classe persistente e quais colunas na tabela são referentes a quais atributos daclasse. Com o surgimento das anotações no Java 5.0, tornou-se possível substituir os arquivos XML para omapeamento objeto relacional. Através do uso de um conjunto de anotações no código fonte das classesmapeadas.Neste primeiro exemplo, será apresentado como realizar o mapeamento objeto relacional da classe Aluno(Classe ilustrada na Figura 1) utilizando anotações. Dessa forma, informando ao Hibernate que tabela no bancode dados a representa e quais atributos correspondem as quais colunas desta tabela.Figura 1 - Classe AlunoA classe Java que representa a entidade Aluno está ilustrada na Listagem 3.package modelo;public class Aluno { //Atributos da classe private int id; private int matricula; private String nome; private long cpf; //Construtor padrão public void Aluno(){} //Métodos getters e setters //... } }Listagem 3 - Classe de Domínio: AlunoTodas as classes persistentes mapeadas com anotações Hibernate são declaradas usando a anotação @Entity,aplicada em nível de classes, como mostrado na Listagem 5. Observa-se que com o uso de anotações, não hámais a necessidade de se utilizar arquivos de mapeamento XML adicionais.Quando o nome da classe é diferente do nome da tabela para a qual é mapeada é necessário informar naanotação @Table qual o nome da tabela, usando o atributo name. No caso do mapeamento da classe Aluno,não havia a necessidade de se informar o nome da tabela, pois ela e a classe possuem o mesmo nome. Como atabela pertence a um esquema do banco de dados (anotacoes), no mapeamento da classe, também énecessário informar em que esquema a tabela mapeada se encontra, utilizando o atributo schema da anotação Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 110 de 140
    • _____________________Curso Struts & Hibernate______________@Table. No caso, a linha do código fonte @Table(name="aluno", schema="anotacoes") está informandoo nome e o esquema da tabela para a qual está mapeada a classe aluno.A chave primária da tabela é mapeada na classe através da anotação @Id. O valor atribuído à chave primáriapode ser dado tanto pela aplicação quanto por um mecanismo do Hibernate que o gere automaticamente. Aanotação @GeneratedValue permite a definição automática para o valor do identificador, utilizando um dosmecanismos de geração apresentados anteriormente. Neste caso, utilizou-se a estratégia a partir de umaseqüência, como feito na linha de código @GeneratedValue(strategy = GenerationType.SEQUENCE).Dessa forma, na hora de persistir uma linha na tabela aluno, o Hibernate vai pegar como valor para a chaveprimária o próximo valor disponível por uma seqüência padrão chamada hibernate_sequence. Deve-sesalientar que o programador deverá criar uma seqüência com este nome na base de dados. Ainda em relaçãoao identificador, como o nome da coluna mapeada é diferente do nome do atributo, é necessário utilizar aanotação @Column informando o nome da coluna, através do atributo name. Neste exemplo, o nome dacoluna mapeada para o identificador é id_aluno, mapeada da seguinte forma:@Column(name="id_aluno").Observa-se que nos demais atributos da classe não há nenhuma anotação de mapeamento. Isso pode ser feitoquando o nome do atributo é igual ao nome da coluna da tabela mapeada, de forma que não há a necessidadede mapeamento explícito.Por fim, para se utilizar as anotações para mapeamento das classes, é preciso importá-las de algum lugar,neste caso do pacote javax.persistence, como mostrado no início do código fonte da Listagem 10.package modelo;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;//Anotação que informa que a classe mapeada é persistente@Entity//Informando nome e esquema da tabela mapeada@Table(name="aluno", schema="anotacoes")public class Aluno { //Definição da chave primária @Id //Definição do mecanismo de definição da chave primária @GeneratedValue(strategy = GenerationType.SEQUENCE) //Informa o nome da coluna mapeada para o atributo @Column(name="id_aluno") private int id; private int matricula; private String nome; private long cpf; public void Aluno(){} //Métodos getters e setters //...}Listagem 10 – Mapeamento da classe Aluno com anotações Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 111 de 140
    • _____________________Curso Struts & Hibernate______________Depois de criar todas as classes persistentes com seus respectivos mapeamentos com anotacoes, deve-serealizar algumas configurações do Hibernate, mostradas na listagem 11.<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <session-factory> <!-- properties --> <property name="connection.driver_class"> org.postgresql.Driver </property> <property name="connection.url"> jdbc:postgresql://localhost:5432/jeebrasil </property> <property name="dialect"> org.hibernate.dialect.PostgreSQLDialect </property> <property name="show_sql">true</property> <property name="connection.username">postgres</property> <property name="connection.password">postgres</property> <property name="connection.pool_size">10</property> <!-- mapping classes --> <mapping class="modelo.Aluno"/> </session-factory></hibernate-configuration>Listagem 11 – Configurações do arquivo hibernate.cfg.xml16.3 Outro Exemplo com Anotações JPAA classe Cliente, ilustrada pela Listagem 2, possui exemplos de mapeamentos de atributos a partir dasanotações: @Column, @Transient, @Temporal. As anotações @Id e @GeneratedValue também sãoutilizadas e servem para mapear a chave primária da tabela correspondente e definir como o seu valor serágerado, respectivamente, como explicado no tutorial anterior.package modelo;import javax.persistence.*;@Entity@Table(name="cliente", schema="anotacoes")public class Cliente { @Transient private int temporaria; @Id Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 112 de 140
    • _____________________Curso Struts & Hibernate______________ @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name="id_cliente") private int id; @Column(unique=true, nullable=false, insertable=true, updatable=true) private long cpf; @Column(nullable=false, length=40, insertable=true, updatable=true) private String nome; @Column(length=100) private String endereco; @Column(name="total_compras", precision=2) private double totalCompras; @Column(name="data_nascimento", nullable=false) @Temporal(TemporalType.DATE) private Date dataNascimento; @Column(name="data_cadastro") @Temporal(TemporalType.TIMESTAMP) private Date dataCadastro; public Cliente(){} //Métodos getters e setters}Listagem 2 – Mapeamento da Classe Cliente com AnotaçõesA seguir uma breve descrição das anotações utilizadas: • Anotação @Transient: informa que o atributo mapeado não possui correspondente na tabela mapeada pela classe, ou seja, não é um atributo persistente; • Atributos da anotação @Column utilizados: o name: nome da coluna na tabela do banco de dados que representa o atributo; o unique: indica se a coluna na tabela que representa o atributo possui a restrição de unicidade ou não. Por padrão, assume o valor false; o nullable: indica se a coluna na tabela que representa o atributo pode assumir valor nulo ou não. Por padrão, assume o valor true, indicando que pode assumir valores nulos; o length: informa o tamanho máximo assumido pelo valor da coluna na tabela; o precision: informa a precisão decimal dos possíveis valores para a coluna mapeada pelo atributo; o insertable: indica se o atributo será inserido no momento da inserção de uma linha na tabela. Por padrão assume o valor true; o updatable: indica se o atributo será atualizado no momento da atualização de uma linha na tabela. Por padrão assume o valor true. o Anotação @Temporal: utilizada para mapeamento de datas e hora. Recebe um valor como argumento que pode ser: TemporalType.DATE: usado para mapear datas; TemporalType.TIME: usado para mapear datas e hora; TemporalType.TIMESTAMP: usado para mapear hora. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 113 de 140
    • _____________________Curso Struts & Hibernate______________16.4 Definição de Chave Primária Utilizando uma SeqüênciaPrópria Nos mapeamentos apresentado na seção anterior, a definição dos valores das chaves primárias foi feita apenas utilizando a seqüência hibernate_sequence. O exemplo presente na Listagem 3 mostra o mapeamento da chave primária da tabela cliente utilizando a seqüência de nome cliente_seq. Para isso, utilizou-se as anotações @SequenceGenerator e @GeneratedValue. Na anotação @SequenceGenerator define-se qual seqüência criada na base de dados será utilizada para o mapeamento. No caso, nomeia-se a seqüência com o nome SEQ_CLIENTE (name = “SEQ_CLIENTE”). Para definir qual seqüência será utilizada no mapeamento da chave primária, utiliza-se a anotação @GeneratedValue, onde é informado que a definição do valor do atributo será através de seqüências (strategy = GenerationType.SEQUENCE) e o nome da mesma (generator = "SEQ_CLIENTE"). package modelo; import javax.persistence.*; @Entity @Table(name="cliente", schema="anotacoes") public class Cliente { @Id @SequenceGenerator(name = "SEQ_CLIENTE", sequenceName = " anotacoes.cliente_seq") @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "SEQ_CLIENTE") @Column(name="id_cliente") private int id; //... } Listagem 3 – Mapeamento de Chave Primária Usando Seqüência Própria Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 114 de 140
    • _____________________Curso Struts & Hibernate______________16.4 Mapeando relacionamento entre classesO termo associação é utilizado para se referir aos relacionamentos entre as entidades. Os relacionamentos n-para-n, n-para-1 e 1-para-n são os mais comuns entre as entidades de um banco de dados.16.4.1 Associações 1-n (one-to-many)Para exemplificar o relacionamento 1-n, considere o relacionamento entre a entidade Centro e a entidadeUniversidade da Figura 1. O relacionamento diz que uma universidade possui um conjunto de n centros e umcentro está associado a apenas uma única universidade. Considere as classes de domínio Java de umauniversidade e de um centro, respectivamente, mostradas na Listagem 1 e na Listagem 2. Ambas as classes jápossuem o seu mapeamento via anotações inserido.Figura 1 - Relacionamento entre Centro e Universidadepackage modelo;import java.util.Collection;import javax.persistence.*;@Entity @Table(schema="anotacoes")public class Universidade { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name="id_universidade") private int id; private String nome; @OneToMany(mappedBy="universidade", fetch = FetchType.LAZY , cascade=CascadeType.ALL) private Collection centros; //Métodos getters e setters ...}Listagem 1 – Classe de Domínio: Universidade Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 115 de 140
    • _____________________Curso Struts & Hibernate______________package modelo;import javax.persistence.*;@Entity @Table(schema="anotacoes")public class Centro { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name="id_centro") private int id; private String nome; @ManyToOne(fetch = FetchType.EAGER ,cascade=CascadeType.PERSIST) @JoinColumn(name="id_universidade",insertable=true, updatable=true) private Universidade universidade; //Métodos getters e setters //...}Listagem 2 – Classe de Domínio: CentroA classe de domínio Universidade é a que possui um mapeamento do tipo 1-n através do atributo coleção decentros. O seu mapeamento foi feito na Listagem 1 a partir da anotação @OneToMany. Como a coleçãoconterá objetos do tipo Centro, então está classe também deverá ser uma classe persistente da aplicação. Naanotação @OneToMany, existe um atributo denominado mappedBy que deverá receber como valor o nomedo atributo na classe Centro (classe dos tipos de objetos da coleção) que se refere à classe Universidade(onde há o mapeamento 1-n). Em outras palavras, a tabela centro possui uma chave estrangeira para a tabelauniversidade, representada pelo atributo Universidade universidade da classe Centro, que corresponderáao atributo mappedBy da anotação @OneToMany, ou seja, mappedBy=”universidade”.Já o atributo fecth indica quando o conteúdo do atributo será trazido da base de dados, é equivalente aoatributo lazy no mapeamento com xml. Pode assumir dois valores: • FetchType.EAGER: sempre que o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.EAGER fará com que o seu conteúdo também seja trazido; • FetchType.LAZY: sempre que o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.LAZY fará com que o seu conteúdo somente seja trazido quando acessado pela primeira vez.O atributo cascade, também utilizado no mapeamento da coleção centros, serve para indicar com que açãoem cascata o relacionamento será tratado, ou seja, especifica quais operações deverão ser em cascata doobjeto pai para o objeto associado. Podendo assumir um dos valores abaixo: • CascadeType.PERSIST: os objetos associados vão ser inseridos automaticamente quando o objeto "pai" for inserido, equivalente ao save-update da versão em xml; • CascadeType.REMOVE: os objetos associados ao objeto "pai" vão ser removidos, quando o mesmo for removido; • CascadeType.REFRESH: Se o objeto for sincronizado com a base de dados, os filhos também serão; • CascadeType.MERGE: Se um objeto tiver suas modificações mescladas em uma sessão, os filhos também terão; • CascadeType.ALL: junção de todos os tipos de cascade. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 116 de 140
    • _____________________Curso Struts & Hibernate______________16.4.2 Associações n-1 (many-to-one)O relacionamento n-1 será apresentado a partir do relacionamento existente entre as classes Centro eUniversidade, mostrado também na Figura 1. Neste caso, o relacionamento está presente no mapeamento daclasse Centro, como mostrado na Listagem 2, a través da anotação @ManyToOne. Para facilitar oentendimento, o trecho de mapeamento many-to-one do atributo universidade da classe Centro pode servisto também na Listagem 12.//...@Entity @Table(schema="anotacoes")public class Centro { //... @ManyToOne(fetch = FetchType.EAGER ,cascade=CascadeType.PERSIST) @JoinColumn(name="id_universidade",insertable=true, updatable=true) private Universidade universidade; //Métodos getters e setters //...}Listagem 12 - Mapeamento ManyToOneA anotação @ManyToOne também possui o atributo fetch, que possui o mesmo comportamento apresentadoanteriormente. A anotação @JoinColumn é utilizada para informar qual o nome da coluna que corresponde àchave estrangeira do mapeamento, no caso, name=”id_universidade”. Nesta anotação também sãoaceitáveis os atributos insertable e updatable que se assumirem true indica que o atributo deve ser inserido(insertable) ou atualizado (updatable) no momento em que o objeto que possui o relacionamento é inseridoou atualizado, respectivamente. O atributo do relacionamento não será inserido se insertable = false e nãoserá atualizado se updatable = false.16.4.3 Demais AssociaçõesAs demais associações para o Hibernate JPA são equivalentes ao que já existe para os arquivos hbm.xml,porém a linguagem Java facilita bastante a configuração de classes JPA com anotações. Para maiores detalhessobre anotações JPA veja:http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.htmlAnotações Descrição@OneToOne Efetua uma associação one-to-one.@ManyToMany Efetua uma associação many-to-many@EmbeddedId Efetua um mapeamento com chave composta@Embeddable@Inheritance(strategy=InheritanceType) Efetua um mapeamento com herança@DiscriminatorColumn@DiscriminatorValueTabela 1.6.4.3 – Demais associações utilizadas com anotações JPA. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 117 de 140
    • _____________________Curso Struts & Hibernate______________ APÊNDICE “A” CADERNO DE EXERCÍCIOS Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 118 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 1 – Welcome1- No browser, acessar a url http://localhost:8080/hello;2- Entender o diagrama de colaboração abaixo, o qual explica a dinâmica da aplicação struts-blank; Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 119 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 2 - Registro de usuários1- Criar um projeto register;2- Aplicar o struts-blank.war à pasta web;3- Copiar do temporário os arquivos register.jsp, success.html, failure.html(c:struts_hibernateregisterweb) para a pasta web do projeto;4- Colocar o arquivo WEB-INFlibstruts.jar como biblioteca do projeto;5- Criar uma classe chamada app.RegisterForm , o qual extenda ActionForm, essa classe dever ser um Java Bean,com os parâmetros username, password1, password2 , todos do tipo String. Logo em seguida, visualize o arquivoregister.jsp, e diga o que eles têm comum. Não se esqueça de criar os get e sets na classe RegisterForm;6- Criar uma classe chamada app.RegisterAction, a qual extende Action;7- Abrir o o struts-config.xml, e criar um Form Beans;name: registerFormtype: app.RegisterForm8- Abrir o struts-config.xml, criar um Action Mapping;Path: /registerType: app.RegisterActionForm Bean: registerForminput: /register.jspforwards:Name:successPath: /success.htmlName: failurePath: /failure.html9- Completar o TODO do register.jsp;10- No RegisterAction , sobrescrever o método execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)11- Ainda no RegisterAction, efetuar um cast de form para uma variável do tipo RegisterForm, chamadaregisterForm;12- Utilizando a variável registerForm criada, testar (if) se o atributo password1 igual a password2 , sesim , utilizar mapping.findForward("success"), senão , utilizar mapping.findForward("failure"). Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 120 de 140
    • _____________________Curso Struts & Hibernate______________13 – Criar um Global Forward:Name: indexPath: /register.jsp14- Na página /index.jsp , redirecionar para o forward index15- Entender o funcionamento do fluxo da aplicação, tendo como base o diagrama de colaboração abaixo. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 121 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 3 – Criação do projeto cadastro e menus 1- Criar um projeto chamado “cadastro” no Eclipse, com o plugin Sysdeo, depois, expandir o arquivo struts-blank.war no diretório web, e por último, copiar para o seu diretório de projetos o diretório cadastro, fornecido pelo professor. Para maiores detalhes de como criar um projeto Struts no Eclipse, consultar a página 9 da apostila. 2- Acompanhar a explicação do professor para a estrutura do projeto fornecido, conforme figura abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 122 de 140
    • _____________________Curso Struts & Hibernate______________ 3- Dado o diagrama de comunicação abaixo, analisar junto com o professor o fluxo da aplicação: 4 – Crie um Global Forward: name: menu path: /menu.do 5 – Crie uma Action Mapping: path: /menu forward: /pages/index.jsp 6 – Complete o TODO na página /index.jsp Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 123 de 140
    • _____________________Curso Struts & Hibernate______________ 7- Crie um Action Mapping: path: /menuinclude include: /pages/menu.jsp 8- Completar os TODO contidos na página /pages/index.jsp; 9 - Crie dois Action Mappings: cadastro e listagem. Os dois irão apontar (forward) provisoriamente para menu.do; 10- Completar os TODO contidos na página /pages/menu.jsp; 11- Testar o funcionamento em http://localhost:8080/cadastro Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 124 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 4 – Criação da tela de dados pessoais1- Analisar o diagrama de comunicação abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 125 de 140
    • _____________________Curso Struts & Hibernate______________2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace doEclipse;3- No Windows, menu iniciar, opção Configurações/Painel de Controle/FerramentasAdministrativas/Fontes de Dados ODBC/Fontes de dados do sistema, cadastrar uma fonte de dadosAccess, com o nome “cadastro”, apontando para o arquivo cadastro.mdb contido no diretório data do seuprojeto cadastro;4- Modificar o Action Mapping /cadastro:type: app.CadastroActionforward name: sucesso path: /pages/pessoa.jsp5- Ir na classe app.CadastroAction e completar os TODO;6- Na classe app.CadastroForm , completar os 2 primeiros TODO;7- Criar um ActionForm: Name: cadastroform Type: app.CadastroForm8 – Criar um Action Mapping: Path: /submitpessoa Type: app.SubmitPessoaAction Form: cadastroform (name se for editar diretamente o struts-config.xml) Validate: true Input: /cadastro.do Scope: session Forward: Name: continue Path: /formacao.do9- Ir na pagina /pages/pessoa.jsp e completar os TODO. Após concluir este passo, teste a opção de menu“Cadastro” no browser;10 – Modificar o Action Mapping /formacao Forward: /pages/formacao.jsp11 – Na classe app.AdaptadorCadastro, completar os TODO;12- Na classe app.SubmitPessoaAction, completar os TODO; Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 126 de 140
    • _____________________Curso Struts & Hibernate______________13- Teste o botão continuar no formulário de cadastro, e verifique se a tabela pessoa do arquivocadastro.mdb recebeu um novo registro com os dados digitados anteriormente;14- Na classe app.CadastroForm, descomente o metodo public ActionErrors validate, e completeos TODO;15 – De volta ao formulário de cadastro, entre com valores inválidos e verifique se o Struts irá validar asua entrada. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 127 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 5 – Criação da tela de formação1- Analisar o diagrama de comunicação abaixo:2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace doEclipse; Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 128 de 140
    • _____________________Curso Struts & Hibernate______________3- Modificar o Action Mapping /formacao: type: app.FormacaoAction forward: sucesso path: /pages/formacao.jsp4- Completar os TODO da classe app.FormacaoAction5- Cadastrar um Action Form: name: formacaoform type: DynaActionForm id Long idPessoa Long idNivelEscolaridade Integer instituicao String anoInicio Integer anoConclusao Integer method String6- Cadastrar um Action Mapping: path: /submitformacao type: app.SubmitFormacaoAction name: formacaoform input: /formacao.do parameter: method scope: request validate: true forward: continuar -> /pages/experiencia.jsp forward: adicionar -> /formacao.do forward: voltar -> /cadastro.do7- Criar um atributo chamado formacoes, do tipo java.util.Collections na clase app.CadastroForm. Gerar gettter esetter, e inicializa-lo com um java.util.LinkedList vazio.8- Completar os TODO da página /pages/formacao.jsp. Após concluir este passo, teste a opção de menu“Cadastro/Continuar” no browser. Deverá aparecer a tela de entrada de dados de formação acadêmica.9- Completar os TODO na classe app.SubmitFormacaoAction10- Criar um Global Forward: name: erro path: /pages/erro.jsp Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 129 de 140
    • _____________________Curso Struts & Hibernate______________11- Completar os TODO na página /pages/erro.jsp12- Teste as funcionalidades da tela de formação, e verifique se as informações constam na tabelaformação no banco de dados.Exercício 6 – Criação da tela de experiências1- Analisar o diagrama de comunicação abaixo: Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 130 de 140
    • _____________________Curso Struts & Hibernate______________2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace doEclipse;3- Modificar no Action Mapping /submitformacao: name: continuar path: /experiencia.do4- Criar um Action Mapping name: /experiencia type: app.ExperienciaAction forward: name: sucesso path: /pages/experiencia.jsp5- Criar um Form name: experienciaform type: DynaActionForm atributos: id Long empresa String dataInicioDisplay String dataTerminoDisplay String atribuicoes String idPessoa Long method String6- Criar um atributo chamado experiencias, do tipo java.util.Collections na clase app.CadastroForm.Gerar gettter e setter, e inicializa-lo com um java.util.LinkedList vazio.7- Completar os TODO da classe ExperienciaAction8- Criar um ActionMapping/submitexperiencia type: app.SubmitExperienciaAction parameter: method name: experienciaform input: /experiencia.do scope: request validate: true forwards: name: concluir path: /cadastro.do Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 131 de 140
    • _____________________Curso Struts & Hibernate______________ name: adicionar path: /experiencia.do name: voltar path: /formacao.do9- Completar os TODO da pagina /pages/experiencia.jsp. Após concluir este passo, teste o botão decontinuar no /formacao.do no browser. Deverá aparecer a tela de entrada de dados de experiênciaprofissional.10- Completar os TODO da classe app.SubmitExperienciaAction12- Testar as funcionalidades da tela de experiência profissional, e verifique se as informações constamna tabela experiencia no banco de dados. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 132 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 7 – Listagem de Currículos Cadastrados1- Analisar o diagrama de comunicação abaixo:2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace doEclipse. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 133 de 140
    • _____________________Curso Struts & Hibernate______________3- Abrir o arquivo para_inserir_em_struts-config.xml.txt, e inserir o conteúdo do mesmo noarquivo struts-config.xml, entre os elementos <form-bean> e <action-mapping>.4-Testar a funcionalidade “Listagem”.Exercício 8 – Transformando o Cadastro de Currículos em uma aplicação globalizada1- Analisar o diagrama de comunicação abaixo:2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace do Eclipse.3- Criar um novo Form: name: formlocale type: DynaActionForm atributos: language String country String4- Completar os TODO em app.LocaleAction5- Completar os TODO em menu.jsp6- Criar um novo Action Mapping: name: /locale type: app.LocaleAction form: formlocale Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 134 de 140
    • _____________________Curso Struts & Hibernate______________ validate: false scope: requestforward: name= sucesso path= /menu.do 7- Testar a nova funcionalidade, clicando nas bandeirinhas que irão aparecer no menu principal. PARABÉNS!! VOCÊ ACABOU DE CONCLUIR TODO O FLUXO NAVEGACIONAL DA APLICAÇÃO!! Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 135 de 140
    • _____________________Curso Struts & Hibernate______________ Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 136 de 140
    • _____________________Curso Struts & Hibernate______________Exercício 9 – Aplicando validação declarativa com o framework Validator 1- No arquivo validation.xml, cadastrar o seguinte form: (Obs. O conjunto de elementos do validation.xml é bastante complexodevido aos seus diversos aninhamentos e atributos, então para agilizar a aula éfortemente recomendado o uso da ferramenta visual.) name: formacaoform field: instituicao depends: required,minlength Arg0: formacao.instituicao Vars: minlength: 3 Arg1: minlength: ${var:minlength} resource=false field: idNivelEscolaridade depends: required, short,intRange Arg0: formacao.idNivelEscolaridade Arg1: intRange: ${var:min} resource=false Arg2: intRange: ${var:max} resource=false Vars: min: 1 Vars: max: 6 field: anoInicio depends: required, short, intRange Arg0: formacao.anoInicio Arg1: intRange: ${var:min} resource=false Arg2: intRange: ${var:max} resource=false Vars: min: 1900 Vars: max: 2015 field: anoConclusao depends: short, intRange Arg0: formacao.anoInicio Arg1: intRange: ${var:min} resource=false Arg2: intRange: ${var:max} resource=false Vars: min: 1900 Vars: max: 20152- Na página formacao.jsp: 2.1 - Coloque na declaracao <html:form> o atributo onsubmit= “return validateFormacaoform(this)”. Isto fará com que a rotina em javascript validateFormacaoform seja executada antes do formulário seja submetido. 2.2 - Declare uma tag <html:javascript formName=”formacaoform” /> no final do arquivoformacao.jsp Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 137 de 140
    • _____________________Curso Struts & Hibernate______________ 2.3 – Para dar um “bypass” na validação de um formulário vazio, modifique nos atributos onclick abCancel para true, nos botões voltar, continuar e cancelar.Ex.: onClick=”bCancel=true; document.formacaoform.method.value=continuar”3- No struts-config.xml modificar os tipos dos formulários formacaoform e experienciaform paraDynaValidatorForm.4- Testar o cadastro de formações com valores que violem as restrições de validação recém cadastradas.6- Desabilitar a validação do Action Mapping /submitformacao.do, e efetuar uma validação manual nométodo SubmitFormacaoAction.adicionar, com o método form.validate(mapping,request). Testar osbotões cancelar, voltar, continuar .7- No arquivo validation.xml, cadastrar o seguinte form: name: experienciaform field: empresa depends: required,minlength Arg1: minlength: ${var:minlength} resource=false Arg0: experiencia.empresa Vars: minlength: 3 field: dataInicioDisplay depends: required, date Arg0: experiencia.dataInicio field: dataTerminoDisplay depends: required, date Arg0: experiencia.dataTermino field: atribuicoes depends: required, minlength,maxlength Arg0: experiencia.atribuicoes Arg1: minlength: ${var:minlength} resource=false Arg1: maxlength: ${var:maxlength} resource=false Vars: minlength: 4 Vars: maxlength: 10008- Na página experiencia.jsp: 8.1 - Coloque na declaracao <html:form> o atributo onsubmit= “return validateExperienciaform(this)”. Isto fará com que a rotina em javascript validateFormacaoform seja executada antes do formulário seja submetido. Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 138 de 140
    • _____________________Curso Struts & Hibernate______________ 8.2 - Declare uma tag <html:javascript formName=”experienciaform” /> no final do arquivoexperiencia.jsp 8.3 – Para dar um “bypass” na validação de um formulário vazio, modifique nos atributos onclick abCancel para true, nos botões voltar, continuar e cancelar.Ex.: onClick=”bCancel=true”9- Testar o cadastro de experiências com valores que violem as restrições de validação recém cadastradas.10- Desabilitar a validação do Action Mapping /submitexperiencia.do, e efetuar uma validação manual nométodo SubmitExperienciaAction.adicionar, com o método form.validate(mapping,request). Testar osbotões voltar, cancelar, concluir.Exercicio 10 – Criando novas regras de validação no framework Validator 1- Copiar o diretório cadastro2 fornecido pelo professor para o seu workspace. Criar um novo Tomcat Project, com o nome cadastro2, não se esqueca de definir o raiz de sua aplicação web como /web 2- Inserir o conteúdo do arquivo para_inserir_em_validation.xml.txt entre os elementos <formset></formset>. 3- Inserir o conteúdo do arquivo para_inserir_em_validation-rules.xml.txt entre os elementos <form-validation></form-validation>, e entender o conteúdo do que foi inserido, com a ajuda do professor. 4- Visualizar o que foi modificado na classe app.CadastroForm, método validate(). 5- Testar o cadastro de pessoas com um cpf inválido.Exercicio 11 – Refactoring: Convertendo o cadastro de currículos para o Tiles1- Copiar a pasta do seu projeto para o mesmo diretorio do workspace,com o nome cadastrotiles. Também copiar por cima o diretorio cadastrotiles fornecido pelo professor.2- Criar um novo Tomcat Project, com o nome cadastrotiles, não se esqueca de definiro raiz de sua aplicacao web como /web3- Resolver os TODOS contidos no arquivo tiles-defs.xml4- Resolver os TODOS contidos nos arquivos do diretorio webpageslayout Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 139 de 140
    • _____________________Curso Struts & Hibernate______________5- Retirar todo o conteudo antes (inclusive) de <jsp:include page="/menuinclude.do" /> e depois(inclusive) de </body>das paginas jsp contidas no diretorio webpages, exceto nos arquivos do diretorio layout.MANTER AS DECLARACOES DE TAGLIB!6- No arquivo struts-config.xml , trocar tudo que for "/pages/*.jsp" por "*" , exemploonde existe "/pages/pessoa.jsp" vai ficar somente "pessoa" . FIM Interplan Soluções em Conectividade Ltda. Avenida Presidente Vargas, 962 grupo 1414 – Centro – Rio de Janeiro. Tels: 21-3473-2210 / 21-2516-2257 / 21-9471-2330 site: www.interplan.com.br email: interplan@interplan.com.br site: www.ensina.com.br email: treinamento@interplan.com.br Página 140 de 140