SlideShare uma empresa Scribd logo
Versão 2.0 – Março - 2009
Revisada 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 oferecer
facilidade de desenvolvimento de aplicativos Web com padrão Java Enterprise Edition (JEE). Oferece uma série
de 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 API
convencional, conhecida como "Biblioteca de classes"?
         Com uma API ou biblioteca de classes, você simplesmente utiliza fazendo chamadas às suas classes e
interfaces.
         Em um framework de desenvolvimento, além da utilização de classes e interfaces, você também pode
estender suas funcionalidades e alterar comportamentos. Tudo isso é possível através de um modelo de trabalho
conhecido 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 de
interfaces, 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 dos
serviócs técnicos especializados descritos acima. Se o desenvolvedor tivesse que se preocupar com todas as
questõ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ápida
revisão.
        O padrão de arquitetura M.V.C. é o mais utilizado atualmente para soluções Web JEE e está presente nas
principais soluções JEE de grandes empresas. Este padrão determina a divisão do aplicativo em três principais
partes:

       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ão
capazes de crescer sem qualquer dificuldade. A complexidade, ou o que chamamos de responsabilidade de
componentes, é dividida de maneira mais inteligente, propiciando fraco acoplamento entre camadas, garantindo
ao
desenvolvedor 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 grande
credibilidade e flexibilidade para desenvolvimento de aplicações Web em Java. Veja no diagrama abaixo, o
relacionamento 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 Web
Funciona assim:

A IDA...
VIEW
         Um usuário digita uma URL, no browser. A página é localizada em um Servidor web, e este devolve para o
browser uma página que é, por exemplo, um formulário. Esta página , o formulário, representa a camada de
interface com o usuário: a camada View (visão). Ela interage com o usuário tanto na entrada, isto é, no momento
que o usuário está preenchendo um cadastro, ou acionando um Hiperlink dentro de um site de compras, quanto na
saí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 é enviado
para o Servidor Web, através do protocolo HTTP, junto com um objeto "Request" , que leva junto todos os campos
do formulário preenchidos pelo usuário. Estes campos são apresentados a um "servlet" desenvolvido com a
missão de "descascar" os dados fornecidos pelo usuário na outra ponta da Web (browser cliente) além de
identificar "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 desenvolvidas
para atender ao negócio. Este "servlet" está agindo como um Controlador (Controller). Esta é a camada de
Controle.

MODEL
        A classe de negócio, acionada pelo Controlador, é uma classe especializada para exercer a função para a
qual ela foi escrita. Por exemplo, para o formulário enviado pelo usuário na camada de apresentação e cujos
dados 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", efetuar
cálculos...

E A VOLTA....
MODEL
        A classe de negócios aí de cima, ao terminar sua tarefa, prepara os dados para serem enviados pelo
Controlador 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 da
classe 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 classe
de 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 o
STRUTS.
       Veja o diagrama abaixo:


                                                  Jakarta Struts Framework – Modelo MVC




                                                                                                                                            3




Na 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.x
5.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) ou
integrado 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" que
deverá 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 dentro
da 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, conforme
as 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 CLICAR
NO BOTÃO "NEXT".




3. Depois de informar o nome do projeto, deixe o nome do contexto (o nome que vem depois da porta 8080 na
URL digitada no browser) como o nome do projeto; deixe selecionada a opção “Can update server.xml file” , e na
opçã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 um
diretó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ção
em 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 o
que o aluno precisará fazer é:
          1) Copiar o arquivo "Struts-Blank.war" da pasta "webapps" do diretório struts-1.2.8 , criado com a
descompactaçã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 de
arquivo "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 no
Eclipse (projeto "logon" página 10), podendo sobrescrever os arquivos pré-existentes. Logo em seguida você deve
dar “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" deve
ficar 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 container's "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ções
importantes 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 é consultado
pelo "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 Servlets
devem ser carregados pelo conteiner. Desta forma, o "ActionServlet" é carregado automáticamente e fica na
memó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 compreender
definitivamente, 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 o
usuário confirma a senha. Ao final do processo, aciona o botão "OK", que é o botão de "Submit". Não se
esqueç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 pela
clá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 uma
tag <action> que possua uma cláusula "path" que possua a palavra "/register", que coincida com a palavra indicada na tag
action 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 a
senha 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ários
criar 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" que
sã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 classe
java, um JavaBean para ser mais exato. Esta classe, deve "estender" a classe org.apache.struts.ActionForm e
como já explicamos antes, este objeto captura os parâmetros do formulário trazido pelo Request. Para funcionar
corretamente, é necessário que o RegisterForm possua as variáveis de instância coincidindo com os nomes dos
campos 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 o
ActionForm (RegisterForm no nosso aplicativo) ele aciona um Action, entregando para ele o ActionForm
preenchido, para que ele, Action, valide os campos do ActionForm, depois decida quais outras informações de
negócios serão recuperadas/criadas/alteradas e no final do processamento, a classe Action retorna um outro
objeto chamado "ActionForward" (que indica um "caminho" de um recurso, podendo ser uma página JSP de
resposta, 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ência
de vários objetos como ActionMapping, ActionForm, HttpServeltRequest e HttpServletResponse). Este método é o
coraçã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 encontra

name=”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 da
pá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 o
Servidor.
        O TomCat sabe através da leitura do arquivo "web.xml" que, pelo padrão ".do" ele deve entregar estes
dados para um ActionServlet, mais específicamente o "RegisterAction". Esta solicitação (request) é então
processada pelo "RegisterAction".
        O "RegisterAction" lê o arquivo struts-config.xml procurando por uma tag <action> que possua a
cláusula "path" coincidindo com o padrão register.do como indicado no arquivo Register.jsp. Mas procura apenas
por "/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 o
controle da execução para a classe Action, indicada na cláusula "type" dentro da tag <action> " e disponibiliza o
JavaBean (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 ser
chamada. No exemplo, a cláusula input aponta para “/Register.jsp”, indicando que chama novamente o
formulá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. Geralmente
este 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 e
as 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 a
solicitaçã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 e
facilitarão outras ações.
          Se outras bibliotecas de tags fossem utilizadas pela aplicação, estas seriam configuradas neste mesmo
local, 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 site
com mensagens em várias línguas , utilizará este arquivo de recursos para, fácil e rápidamente criar várias
versõ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 de
internacionalizaçã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 é o
MessageResources.properties. Ele é um arquivo que pode ser editado por qualquer editor de texto (até o
NotePad) 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 de
propriedades 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 arquivo
MessageResources.
      Isto indica para o Struts que ele deverá buscar, debaixo do diretório/pacote "resources", um arquivo
MessageResources.properties

         Para cada novo idioma deve ser criado um arquivo MessageResources_yy_XX.properties, onde yy é a
sigla da língua e XX, a sigla o País, por exemplo MessageResource_fr_FR.properties, informa que o conteúdo das
mensagens é da lingua francesa da FRANÇA, ou MessageResource_es_ES.properties , informa que o conteúdo
das mensagens é da lingua espanhola da ESPANHA

        Também podemos informar no arquivo Struts-config.xml, que existe um arquivo de propriedades para
internacionalizaçã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 o
seguinte 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 - BeanUtils
O 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ócio
Commons 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, tem
reduzido isso.
        Você pode adcionar alguns métodos simples a uma classe de base ActionForm e facilitar a
transferência dos dados para, e , a partir de qualquer outro componente usando a reflexão. Os métodos
são apenas componentes em torno dos métodos da classe BeanUtils usados em outro lugar no
framework. 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 pacote
Commons 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 em
qualquer direção. O novo copyProperties facilitará a "ida e volta" de seus ActionForms e dos
componentes 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 em
myBusinessBeans, permite que a operação de negócio atualize os valores e então transfere os tipos
nativos de volta para String myActionForm

17.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 na
linha 141, um forward indicando que a página Welcome.jsp, no diretório "pages" referente ao contexto , deve ser
apresentada assim que o URI "logon.do" for aplicado pelo browser. Da mesma forma, na linha 143, podemos
observar 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 da
execução da classe de negócio LogonAction caso o método execute( ) do Action encaminhe de volta ao Servlet
para procurar um ActionForward com o nome lógico de success, o fluxo de execução do programa será desviado
para outro Action : o welcome.do. O professor deve explicar que, dentro do struts-config.xml, deverá existir uma
outra 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 num
hyperlink 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 o
padrão, sem o ".do" (como vimos anteriormente).
          Os objetos ActionMapping ficam catalogados dentro da tag <ActionMappings, que é uma coleção de
ActionMapping.

                                                       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 pelo
browser 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 as
informaçõ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 passam
grande 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 que
indica qual o servlet carregar, lembra?) analisa a URI digitada ou informada pela cláusula action do HTML que
deve 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 uma
tag 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 pela
implementaçã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 objetos
para 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 de
negócio.

       Para isto, o Action pode dispor do objeto ActionForm, que é passado como parâmetro. Lembrem-se de
que o objeto ActionForm possuem os parâmetros do formulário e ficam desta forma, disponíveis para o Action.

Separar as camadas
IMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!!!! IMPORTANTE !!!!!

        É importante EVITAR colocar qualquer lógica de negócio na própria class Action. A classe Action deve
simplesmente reunir qualquer dado que os métodos de negócio e classes Action precisarem, e transmiti-los. Os
mé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 em
muito o “acoplamento” entre as camadas de Modelo (Regras de Negócio) e a
camada de Controle (ActionServlet e Action).
        O que deve ser feito é que outras classes extendam Action e executem o método execute( ). Este
método sim, é que deve chamar as classes que iremos construir e que implementam as regras de negócio

Tratamento de Exceções
        As classes Action também detectam os erros que possam acontecer. O processo envolve a utilização de
dois objetos: ActionMessages e ActionError. Este assunto será coberto e apresentado em exemplos em alguns
capí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 de
uma maneira consistente em todos os objetos Action, o programador poderá registrar um ExceptionHandler com o
arquivo 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 o
caminho 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 é o
objeto Action que seleciona qual ActionForward deve ser executado. O ActionForward define o "para onde";o
objeto Action define o "quando".
        A maneira mais comum de uma classe Action selecionar um envio é através do método findForward do
ActionMapping, desta forma:

       return mapping.findForward("sucesso");


DispatchAction
        Uma estratégia comum entre os desenvolvedores Struts é usar a mesma classe Action para lidar com
várias tarefas afins.
        Um bom exemplo é executar as operações CRUD (create, Read, Update e Delete) básicas em um registro
de 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 diversos
mé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, HttpServletRequest
request, 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=update

18. Como exibir conteúdo dinâmico - Tag Libs
O 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 novos
componentes

        logic          Tags para gerenciar a geração condicional de saída, fazer um loop nas coleções de
objetos para uma geração repetida da saída e o gerenciamento de fluxo da aplicação

18.1 Instalando as extensões da tag do Struts
• Assim como qualquer outra biblioteca de tags, as existentes no Struts precisam ser declaradas no descritor
web.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 beans
e 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âmetros
apropriados
Exemplo 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 nesta
coleçã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 um
arquivo 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. Isto
porque um único arquivo struts-config.xml, tende a ficar indisponível por muito tempo com um mesmo
desenvolvedor.

20 - Tiles Framework – Gerenciamento de Layouts
• O Tiles apresenta-se como um framework de gerenciamento de layout de aplicações web. O mesmo pode ser
utilizado 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áginas
web. É comum a reutilização em outras camadas do modelo MVC, porém não há nenhum motivo para não
beneficiarmos 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ário
do sistema solicita uma mudança no padrão visual do sistema, como mudar o logotipo da empresa. Sem o uso de
um mecanismo de templates como o Tiles, você teria que alterar todas as páginas de sua aplicação. Com o Tiles
dependendo 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ão
dinâ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 facilitar
a criação de templates. Assim como para qualquer outro conjunto de tags, devemos declarar no descritor web.xml
a 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 este
aquivo no diretório "WEB-INF",da aplicação. Após salvar o arquivo podemos então declarar a utilização da taglib
em 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. O
arquivo tiles-defs.xml (conforme declarado anteriormente), irá conter a estrutura de cada um dos templates
utilizados pelo Tiles. Observe o exemplo abaixo:


<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles
Configuration//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. A
página de template padrao.jsp está divida em quatro áreas distintas (topo, menu, conteúdo e rodapé). Estes
por 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 de
herança de layouts. Para este propósito utilizamos o argumento extends da tag definition. Desta forma
podemos 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 forward
de 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 Struts
Configuration 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 mapeamento
portal.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ágina
corresponde 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 do
código deverá fazer a inclusão dinâmica das demais páginas (topo,conteúdo,menu e rodapé). Todas as definições
de 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><font
color="#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 foi
implementada, 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 e
validator-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 retorno

Quando criamos botões do tipo <html:cancel> ou até botões de “voltar” que venham a submeter o formulário, não
queremos que a validação de Javascript seja executada. Neste caso, atribuímos o valor false à variável de
Javascript 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ção




web 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 das
solicitaçõ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ÍTICO
1. Conceitos Gerais ------------------------------------------------------------------------------------------------52
  1.1 Persistência ---------------------------------------------------------------------------------------------- 52
  1.2 Entidades ------------------------------------------------------------------------------------------------- 52
  1.3 Mapeamento Objeto Relacional ---------------------------------------------------------------- 53
1.3.1 Mapeamento de um objeto com tipos primitivos -------------------------- 53
1.3.2 Mapeamento de objetos que contém uma coleção de objetos ------------- 54
2. Introdução ao Hibernate-------------------------------------------------------------------------------------56
3. 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 ----------------------------------------------------------------------- 59
4. Classes Persistentes -------------------------------------------------------------------------------------------59
  4.1 Identidade/Igualdade entre Objetos --------------------------------------------------------- 61
  4.2 Escolhendo Chaves Primárias ------------------------------------------------------------------- 61
5. Objetos Persistentes, Transientes e Detached ----------------------------------------------------62
6. Instalando o Hibernate ---------------------------------------------------------------------------------------63
8. Configurando o Hibernate-----------------------------------------------------------------------------------68
9. Manipulando Objetos Persistentes ----------------------------------------------------------------------71
10. 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 --------------------------------------------------------------- 81
10.4.1 Composite-id---------------------------------------------------------------- 82
  10.5 Associações 1-1 (one-to-one) ----------------------------------------------------------------- 83
11. Coleções ----------------------------------------------------------------------------------------------------------85
  11.1 Set --------------------------------------------------------------------------------------------------------- 85
  11.2 List--------------------------------------------------------------------------------------------------------- 87
  11.3 Map-------------------------------------------------------------------------------------------------------- 88
  12. Herança --------------------------------------------------------------------------------------------------- 88
13. 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 -------------------------------------------------------- 97
14. Concorrência ----------------------------------------------------------------------------------------------------97
  14.1 Lock Otimista ----------------------------------------------------------------------------------------- 98
  14.2 Lock Pessimista ------------------------------------------------------------------------------------- 102
15. 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 ---------------------------------------------------------------------------------------- 108
16. 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 Gerais
1.1 Persistência
        Imagine um usuário fazendo uso de uma aplicação, por exemplo, um sistema para controlar suas
finanças.
        Ele passa a fornecer como dados de entrada todos os seus gastos mensais para que a aplicação lhe
gere, 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 se
encontra. Imagine agora que o usuário teve novos gastos, voltou a ligar o computador, acessou
novamente o sistema de finanças e que gostaria de realizar novas análises com todos os seus gastos
acumulados.
        Se a aplicação não armazenar, de alguma forma, os primeiros gastos fornecidos, o usuário teria que
informá-los novamente e em seguida, acrescentar os novos gastos para fazer a nova análise, causando
grande 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 cada
vez 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 de
execução do software, os objetos das classes entity (classes de entidade) irão representar a ocorrência dessas
entidades do mundo real. Também são conhecidas como classes de domínio da aplicação. Exemplos:

Cliente;
Pessoa;
Curso
Notificaçã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 ambiente
de execução. Os objetos de "classes de entidade" precisam ser não-voláteis ou persistentes, isto é, precisam
se manter entre diversas sessões de utilização de software - sessões que podem ser estabelecidas por usuários
diferentes.
        Um objeto pode ser considerado persistente quando seus atributos podem ser armazenados ao término
de 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 de
dados orientadas a objeto do software. As demais, não sendo orientadas a objetos, conseguirão representar
uma estrutura OO através de processos de adaptação ou mapeamento de estruturas de dados. Em todos os
casos 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 a
comunicaçã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 de
dados de arquivos.

        Para esse tipo de base de dados foi criada uma linguagem, a SQL = Structured Query Language. Essa
linguagem foi toda baseada na lógica relacional e por isso contava com diversas otimizações em suas tarefas se
comparadas 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 um
grande volume de dados.

        Entretanto, essa linguagem não propiciava aos desenvolvedores uma facilidade para que a
produtividade fosse aumentada.

        Uma solução que surgiu no início da década de 90 foi à criação de um modelo de banco de dados
baseado no conceito de orientação a objetos. Este modelo visava facilitar, para os desenvolvedores, a
implementação da camada de persistência da aplicação, pois eles já estavam familiarizados com o paradigma
de
orientaçã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 um
volume de dados muito grande e esse modelo era ineficiente em termos de tempo de resposta, pois ao
contrário dos bancos de dados relacionais, eles não tinham um modelo matemático que facilitasse as suas
operações de
persistências.

        Então a solução foi usar os BDR e desenvolver ferramentas para que o seu uso seja facilitado. Uma
dessas 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 da
tabela (tupla) em um objeto da aplicação.

        A seguir, mostraremos alguns tipos de mapeamentos entre objetos e tipos, primitivos ou tipos não
primitivos 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 salientar
que se entende por tipos básicos aqueles que possuem um correspondente em SQL, ou seja, o tipo String da
linguagem 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 banco
de dados.
       Caso a aplicação deseje saber o veículo da cor vermelha, por exemplo, então o objeto que tem o Palio
como 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 esse
conceito é 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 de
veí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, como
mostrado 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 ao
seu 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 uma
alteração no modelo do banco de dados.

        Primeiramente, o vínculo que foi realizado entre um fabricante e um veículo deverá ser implementado
através de uma chave estrangeira (FK = referência a uma outra tabela, pois em Banco de Dados Relacionais
não existe o conceito de coleções) que se localizará na tabela VEICULO, caracterizando o mapeamento 1 para
N, ou seja, uma instância da entidade veículo "possui" (está relacionado) a uma instância da entidade
fabricante 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 atributo
fabricante 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 tabelas
no BDR.

        Nele observa-se que cada veículo está associado a um fabricante, isso implica dizer que na tabela de
VEICULO existe uma referência para a tabela FABRICANTE (chave estrangeira na entidade Veículo que é chave
primá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 ao
seu respectivo fabricante, no momento da inserção.

       Para recuperar os veículos inseridos o desenvolvedor terá que implementar uma busca que retorne as
informaçõ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 buscar
o 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 que
buscará 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 a
outros objetos.

        Com a idéia do MOR (do inglês ORM = Object Relational Modeling) vários projetos de ferramenta
começaram a ser desenvolvidas, visando facilitar a implementação da camada de persistência, dentre elas o
framework Hibernate, que é um software livre de código aberto e que está tendo uma forte adesão de novos
projetos corporativos.


2. Introdução ao Hibernate
        O Hibernate é uma ferramenta de mapeamento objeto/relacional para Java, e recentemente foi
disponibilizada para a plataforma "dot net". Ela transforma os dados tabulares de um banco de dados em um
conjunto de objetos definido pelo desenvolvedor. Usando o Hibernate, o desenvolvedor se livra de escrever
muito do código de acesso a banco de dados e de SQL que ele escreveria não usando a ferramenta, acelerando
a 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 uso
extensivo de stored procedures, triggers ou que implementam a maior parte da lógica da aplicação no banco de
dados, 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 de
negó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 plataforma
de 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 dados
enquanto 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 fazendo
necessário todo um design de tabelas antes de desenvolver seu projeto que pode ser muito bem utilizado em
projetos pequenos.

         Já projetos grandes onde o plano de ação padrão tomado pelo Hibernate não satisfaz as necessidades
da empresa (como o uso de select *, joins etc), ele possui dezenas de otimizações que podem ser feitas para
atingir tal objetivo.

         O projeto open-source Hibernate (www.hibernate.org) vem se consolidando entre a comunidade de
desenvolvedores Java como o melhor framework de persistência - levando em consideração os seguintes
fatores:

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 que
este framework oferece para otimizar a construção de aplicações robustas, onde o programador vai dedicar
maior 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, é uma
ferramenta 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ém
disponibiliza um poderoso mecanismo de consulta de dados, permitindo uma redução considerável no tempo de
desenvolvimento 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 apresenta
as 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 a
separaçã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 de
dados: 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 de
uma 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 como
fá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 que
este 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. Com
ele, define-se diversas configurações do Hibernate, como por exemplo: o driver do banco de dados a ser
utilizado, 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 de
banco 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 de
manipulação de dados. O uso dessa interface em aplicações que usam Hibernate é opcional. Essa interface
abstrai 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 de
negó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, e
mé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, o
Hibernate pode instanciá-las simplesmente chamando Construtor.newInstance();

   Observe que a classe Pessoa apresenta métodos setters e getters para acessar ou retornar todos os seus
atributos. 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 utilizar
Hibernate, todos os objetos persistentes possuam um identificador e que eles sejam independentes da lógica de
negó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 se
obj1.equals(obj2), retorna um booleano 'true' .
        Incluindo o conceito de persistência, passa a existir um novo conceito de identidade, a identidade de
banco de dados.
        Dois objetos armazenados em um banco de dados são idênticos se forem mapeados em uma mesma
linha 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 de
chaves primárias.
       Uma chave primária é uma coluna ou um conjunto de colunas que identifica unicamente uma linha de
uma 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 essas
propriedades.
        Se a tabela possui um único atributo que a identifique, ele é por definição a sua chave primária. Se
possuir várias chaves que atendem a estas características, elas são chamadas de chaves candidatas e, apenas
uma (um campo, uma coluna) deve ser escolhida para representar a chave primária e as demais colunas
devem 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 de
negócio. Por exemplo, o atributo cpf da tabela Pessoa (associada à classe Pessoa). Essa estratégia pode não
ser muito boa em longo prazo, já que uma chave primária adequada deve ser constante, única e não nula. Se
uma Pessoa, não possuir cpf (muitas mulheres utilizam o cpf do marido e existem pessoas que não possuem
cpf)
        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. Um
problema 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 uma
camada de persistência. Isto é feito, invocando o gerenciador de persistência e as interfaces de consultas do
Hibernate.
        Quando interagindo com o mecanismo de persistência, é necessário para a aplicação ter conhecimento
sobre 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 mesmo
após a destruição do processo que o criou. Na verdade, o que continua a existir é seu estado, já que pode ser
armazenado 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 o
instanciou. Em relação às classes persistentes, nem todas as suas instâncias possuem necessariamente
um 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 algum
contexto persistente. Eles são instanciados, utilizados e após a sua destruição não podem ser reconstruídos
automaticamente;

  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 que
por 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 site
http://hibernate.org, disponível em um arquivo compactado.
        Por fim, este arquivo deve ser descompactado e seu conteúdo consiste em um conjunto de arquivos
JARs (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 driver
do banco de dados utilizado. Depois de fazer o download, adicione o arquivo hibernate3.jar e os seguintes
arquivos 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 scripts
SQL pra gerar as tabelas podem ser facilmente adaptados para outros bancos. Usando o MySQL você também
vai 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 de
ser capaz de montar um ambiente de desenvolvimento Java com todas as configurações necessárias.objetos
do 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 ser
acessada 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 sem
argumento 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 ao
má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 um
endereç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 possui
um 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 seu
coordenador, 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 que
pertence.




                                                         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 o
Hibernate utiliza para saber que tabela no banco de dados a representa. Os arquivos de mapeamentos XML
entre classes e tabelas do banco de dados devem ser nomeados como *.hbm.xml (convenção definida pela
comunidade 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 Hibernate
possuem a estrutura básica mostrada na Tabela 4. O arquivo XML começa normalmente com as definições da
DTD (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 partir
deste 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 se
refere 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 nome
da classe for diferente do nome da tabela a que se referencia, o nome da tabela é informado a partir do
atributo 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 da
tabela.
          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 ilustrado
na tabela 2, para esse exemplo, a estratégia utilizada foi sequence. Dessa forma, o nome da seqüência
també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 de
mapeamento. 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 seus
wrappers, 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 propriedade
pelo atributo XML type e a coluna da tabela a que se refere, pelo atributo XML column. Observe que a
propriedade nome não possui seu tipo e coluna a que se referenciam definidos. Se o atributo column não
aparece no mapeamento da propriedade, o Hibernate considera que a coluna na tabela do banco de dados a
que
se referencia possui o mesmo nome que o definido pelo atributo name. Então pode-se concluir que a
propriedade "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 da
coluna na tabela, converter para o tipo adequado Java.

        O atributo not-null presente no mapeamento do atributo cpf serve para informar se a coluna pode
ser 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 tem
com a classe Curso ( um Aluno pode fazer muitos Cursos). Uma descrição mais detalhada desta
tag 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 Hibernate
Pode-se configurar o Hibernate de três maneiras distintas:

  Instanciar um objeto de configuração (org.hibernate.cfg.Configuration) e inserir suas propriedades
programaticamente;




                                                       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 mapeamento
programaticamente;

  Usar um arquivo XML (hibernate.cfg.xml) com as propriedades de inicialização e os caminhos dos arquivos
de 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 ser
configurados. 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 para
identificar as particularidades do banco de dados;

   hibernate.connection.driver_class: Nome da classe do driver JDBC do banco de dados que está sendo
utilizado;

  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 o
SessionFactory é 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íveis
valores para os dilates estão presentes na Tabela 9:

                  Tabela 9 - Possíveis valores de dialetos

DB2 - org.hibernate.dialect.DB2Dialect
HypersonicSQL - org.hibernate.dialect.HSQLDialect
Informix - org.hibernate.dialect.InformixDialect
Ingres - org.hibernate.dialect.IngresDialect
Interbase - org.hibernate.dialect.InterbaseDialect
Pointbase - org.hibernate.dialect.PointbaseDialect
PostgreSQL - org.hibernate.dialect.PostgreSQLDialect
Mckoi SQL - org.hibernate.dialect.MckoiDialect
Microsoft SQL Server - org.hibernate.dialect.SQLServerDialect
MySQL - org.hibernate.dialect.MySQLDialect
Oracle (any version) - org.hibernate.dialect.OracleDialect
Oracle 9 - org.hibernate.dialect.Oracle9Dialect
Progress - org.hibernate.dialect.ProgressDialect
FrontBase - org.hibernate.dialect.FrontbaseDialect
SAP DB - org.hibernate.dialect.SAPDBDialect
Sybase - org.hibernate.dialect.SybaseDialect
Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect

        O final do arquivo hibernate.cfg.xml é onde devem ser informados os arquivos de mapeamentos das
classes que o Hibernate deve processar. Se algum arquivo de mapeamento não for definido neste local, a classe
a 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 ser
considerado 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ência
1.     try{
2.                //SessionFactory deve ser criado uma única vez durante a execução
3.                //da aplicação
4.             SessionFactory sf = new
Configuration().configure("/hibernate.cfg.xml").buildSessionFactory();
5.                Session session = sf.openSession(); //Abre sessão
6.                Transaction tx = session.beginTransaction(); //Cria transação
7.
8.                //Cria objeto Aluno
9.                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 e
14.               //recuperado para ser atribuído neste momento.
15.               aluno.setCurso(curso);
16.
17.          session.save(aluno); //Realiza persistência
18.          tx.commit(); //Fecha transação
19.          session.close(); //Fecha sessão
20.    } 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. O
objeto SessionFactory armazena os mapeamentos e configurações do Hibernate. É um objeto pesado e lento de
se criar. Pode-se pensar em colocar estas instruções em um Bloco Estático para minimizar o desperdício de
tempo.

       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 sabe
se o objeto em questão já existe ou não no banco de dados, ou seja, se ele deve ser criado ou atualizado?”. A
resposta é 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 chave
primá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 do
objeto 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. 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. Todos os exemplos apresentados nesta seção baseiam-se no diagrama de classes mostrado na Figura
6.

10.1 Associações 1-n (one-to-many)
        Para exemplificar o relacionamento 1-n, considere o relacionamento entre a entidade Centro e a
entidade Universidade da Figura 7. O relacionamento diz que "uma universidade possui um conjunto de n
centros" e "um centro está associado a apenas uma única universidade". Considere as classes de domínio Java
de 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 ser
visto 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. O
atributo key representa a coluna da tabela relacionada (Centro) que possui a chave estrangeira para a classe
Universidade.

       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 o
Hibernate saiba como tratar a associação entre duas tabelas. Quando um lado da associação define o atributo
inverse 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 da
universidade) 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. A
coleçã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 da
chamada ao método getCentros().


10.1.1 - O atributo inverse
        Considerando o relacionamento entre uma universidade e seus centros, no mapeamento do conjunto de
centros em universidade, o atributo inverse é igual a true. Dessa forma, a criação ou atualização do
relacionamento entre um centro e uma universidade será feita durante a persistência ou atualização de um
objeto Centro.

       A partir do exemplo apresentado na Tabela 18, cria-se uma instância da classe Universidade e define-se
um valor para o atributo nome.

        Em seguida, uma instância da classe Centro também é criada, definindo o atributo nome e o atributo
universidade (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 como
false. O que acontece é que o Hibernate insere uma linha na tabela UNIVERSIDADE e em seguida tenta
atualizar o relacionamento entre uma universidade e um centro, no caso a partir de um UPDATE na tabela
CENTRO, 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 o
relacionamento entre uma universidade e um centro logo após a inserção da universidade. Neste caso, como o
relacionamento 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 tabela
CENTRO 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 o
có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 da
inserção de uma universidade o Hibernate não atualiza o relacionamento entre ela e seus centros, pois espera
que ele seja feito no momento da inserção/atualização de um objeto Centro.

Tabela 21 - SQL gerado pelo Hibernate com atributo inverse=true
Hibernate: 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 dos
dois lados foi atualizado, ou seja, vai sempre atualizar os dois lados de uma vez, uma atualização para cada
classe da relação, o que seria desnecessário. Caso contrário, o Hibernate passa, a saber, de qual lado fazer a
atualizaçã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 programador




10.2 Associações n-1 (many-to-one)
        O relacionamento n-1 será apresentado a partir do relacionamento <manyto-one> existente entre a
tabela Centro e a tabela Universidade. Neste caso, o relacionamento está presente no mapeamento da classe
Centro, 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 apresentados
na 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 retirado
da 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 Curso
mostrado 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 de
dados. 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 de
departamentos. 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 de
determinado curso, mas se for realmente necessário, o Hibernate apresenta outros mecanismos para a
obtençã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 mapeamento
da 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ção
departamentos 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 chave
estrangeira 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 mapeamento
da entidade Departamento o atributo inverse é igual a true, significando que na tabela DEPARTAMENTO_CURSO
só será inserido o relacionamento entre as duas entidades, quando um curso for inserido no banco de dados
associado a um departamento.

         Neste caso, não seria necessário mapear a coleção de cursos em Departamento, pois não está sendo
utilizada para popular a tabela de relacionamento.

       Como já citado, para recuperar a coleção de cursos de um departamento, o Hibernate apresenta outros
mecanismos.

        Em outros relacionamentos n-n, pode ser que seja necessário inserir/atualizar o relacionamento na
tabela 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 recupera
um objeto persistente da classe Curso com identificador igual a 1, adiciona esse objeto Curso na coleção de
cursos 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 da
coleçã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 persistente
Departamento de identificador 1 na base de dados, adiciona o departamento à coleção de departamentos do
objeto Curso e realiza a sua persistência.

         O SQL presente na Tabela 31 mostra que um SELECT foi feito na tabela DEPARTAMENTO, um INSERT
na tabela CURSO e um outro INSERT na tabela DEPARTAMENTO_CURSO. Nesse caso, o relacionamento foi
persistido, pois no mapeamento da coleção departamentos da classe Curso, como o atributo inverse
nã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_ where
departamen0_.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 curso
e 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 de
departamento, mas sim também pela data.

       Para essa situação, os mapeamentos dos relacionamentos <many-to-many> nas tabelas Curso e
Departamento 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ária
dupla.




                                         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 atributo
DepartamentoCursoID 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 name
informa 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 da
chave composta dentro da classe DepartamentoCursoID.

       Para exemplificar o relacionamento n-n com atributos, observe o exemplo da Tabela 35. Primeiro um
departamento 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 a
chave composta. Os valores que compõem a chave, curso e departamento, são atribuídos. Finalmente, cria-se
um 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_ where
curso1x0_.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, uma
universidade 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 apresenta
nenhuma 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 ser
inserido ou atualizado automaticamente quando o objeto Universidade for inserido ou atualizado. Nesse
mapeamento aparece o atributo unique, que quando assume valor true implica em ter apenas uma
universidade
por endereço.

        A outra abordagem é ao invés de inserir o código da Tabela 39 no mapeamento de
Universidade.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, o
mapeamento do endereço em Endereco.hbm.xml deve ser feito como mostrado na
Tabela 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 da
tag generator agora é foreign. A tag param de name igual a property permite a associação 1-1 da classe
Endereco com a classe Universidade, o que acontece é que um parâmetro é passado para a classe geradora do
identificador, 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 de
Endereco (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ção
entre a chave primária de Endereco e de Universidade, informando ao Hibernate que um endereço não pode
existir 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 é feito
através da tag set e possui o conjunto de atributos mostrado na Tabela 42. Esses atributos são semelhantes
para 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 o
mapeamento de um Set de tipos primitivos considere o mapeamento de uma coleção de String’s para
armazenar 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 esta
tabela é separada da tabela ALUNO, mas para o Hibernate, ele cria a ilusão de uma única entidade. A tag key
indica a chave estrangeira da entidade pai (ID_ALUNO). A tag element indica o tipo da coleção (String) e a
coluna 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_TELEFONE
consiste 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 inserido
em sua coleção de String’s.
        Por fim, o objeto Aluno é persistido. O resultado é mostrado na Tabela 45, onde primeiro é inserida
uma 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 lista
requer 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 da
coleçã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 de
dados 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 as
colunas 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 fato
de 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 chave
primária da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e CHAVE, também permitindo a
presenç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 de
dados;
  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 Professor
herdam 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ça

As Figuras Figura 16, Figura 17 e Figura 18 mostram as tabelas que devem ser criadas para as estratégias de
mapeamento 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 os
conhecimentos 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. Neste
caso, as sub-classes são mapeadas em tabelas diferentes, portanto uma associação polimórfica para a classe
mãe não seria possível através de chave estrangeira.
        Outro problema conceitual é que várias colunas diferentes de tabelas distintas compartilham da mesma
semântica, podendo tornar a evolução do esquema mais complexo, por exemplo, a mudança de um tipo de
uma 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. O
mapeamento 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. No
caso, 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 na
representação do polimorfismo. É importante saber que restrições ,"não nulas", não são permitidas para o
mapeamento 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 o
exemplo citado, essa estratégia de mapeamento pode ser vista na Tabela 50. Nessa estratégia as tabelas filhas
contêm apenas colunas que não são herdadas e suas chaves primárias são também chaves estrangeiras para a
tabela 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 da
classe mãe são persistidos em uma linha da tabela PESSOA e apenas os valores correspondentes à classe Aluno
são persistidos em uma linha da tabela ALUNO.

         Em momentos posteriores essa instância de aluno persistida pode ser recuperada de um join entre a
tabela 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 por
sub-classe. A tag key declara as chaves primárias das sub-classes que são também chaves estrangeiras para a
chave 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ções
Uma transação é uma unidade de execução indivisível (ou atômica). Isso significa dizer que todas as etapas
pertencentes 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 entre
contas 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 A
2º) 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ção



13.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, onde
aparecem 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ções
realizadas por algum container.
        Exemplos de ambientes gerenciados são componentes EJB (Enteprise JavaBeans) executando em
servidores 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 por
exemplo: 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 por
ambientes não gerenciados. Utilizando um driver JDBC, o início de uma transação é feito implicitamente pelo
mesmo. 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 o
mé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. Se
este atributo for definido como true, ou seja, se na conexão JDBC for invocado setAutoCommit(true), ativa-se o
modo 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 a
necessidade 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 de
dados. Nessas situações, o uso apenas do JDBC pode não garantir a atomicidade. Dessa maneira, é necessário
um 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 (Container
Managed Transactions). Neste tipo de transação não há a necessidade de programação explícita das
delimitaçõ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 ele
deve 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 51
apresenta 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ão
JDBC é iniciada. Já no caso de um ambiente gerenciado, uma nova transação JTA é criada, caso não exista
nenhuma 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 base
de dados. O Hibernate só realiza efetivamente o commit se o comando beginTransaction() iniciar uma nova
transaçã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 a
conexã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. As
mudanças nos objetos de domínio em memória feitas dentro do escopo de uma sessão (Session) não são
imediatamente 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ções
com 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, algumas
vezes 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 todas
as 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 a
base 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étodo
flush().

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 que
estejam 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 de
uma transação. Eles impactam diretamente no nível de acesso concorrente a um mesmo alvo no banco de
dados por transações diferentes.
         Geralmente, o isolamento de transações é feito usando locking, que significa que uma transação pode
bloquear 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 de
controle 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 isolamento
de uma transação estão três:

  Dirty Read (Leitura Suja): uma transação tem acesso a dados modificados por uma outra transação ainda
não finalizada que ocorre concorrentemente. Isso pode causar problema, pois pode ocorrer um erro dentro da
transaçã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 dados
incorretos.

  Nonrepeatable Read (Leitura que não pode ser repetida): uma transação lê mais de uma vez um
mesmo dado e constata que há valores distintos em cada leitura. Por exemplo, uma transação A lê uma linha
do banco; uma transação B modifica essa mesma linha e é finalizada (commit) antes que a transação A; a
transaçã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 de
uma vez e retornar resultados diferentes. Isso pode ocorrer devido a uma outra transação realizar mudanças
que afetem os dados consultados. Por exemplo, uma transação A lê todas as linhas que satisfazem uma
condição WHERE; uma transação B insere uma nova linha que satisfaz a mesma condição antes da transação A
ter sido finalizada; a transação A reavalia a condição WHERE e encontra uma linha “fantasma” na mesma
consulta feita anteriormente.

       Existem quatro níveis de isolamento da transação em SQL. Eles se diferenciam de acordo com a
ocorrência ou não dos fenômenos anteriormente descritos, como mostrado na Tabela 52.

                  Tabela 52 - Níveis de Isolamento da Transação em SQL




Obs. 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 dados
relacionais, já que permite ler inconsistências e informações parciais (mudanças realizadas por uma transação
ainda não finalizada podem ser lidas por outra transação). Se a primeira transação não for concluída, mudanças
na 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ções
quando 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 que
a 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 que
iniciou primeiro ser efetivada ou desfeita.
         Se as atualizações da primeira transação forem desfeitas, seus efeitos serão desconsiderados e a
segunda 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 ou
aplicará 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 uma
transaçã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 é ideal
para a geração de relatórios, pois em uma mesma transação, um registro é lido diversas vezes e seu valor se
manté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. Ele
permite uma execução serial das transações, como se todas as transações fossem executadas uma atrás da
outra. Dessa forma, pode-se perder muita performance da aplicação, principalmente em ambientes
multiusuários.

13.9 Configurando o nível de isolamento
No 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 = 4


14. Concorrência
        Em algumas situações pode acontecer que duas ou mais transações que ocorrem paralelamente leiam e
atualizem 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 de
dados. Para exemplificar, a Tabela 54 apresenta um exemplo de duas transações concorrentes manipulando o
mesmo dado x.

         No primeiro passo, ambas as transações lêem o dado x com o mesmo valor (2). Em seguida, T1 soma o
valor 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 passa
a 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, o
valor calculado por T2, significando que as alterações feitas por T1 foram descartadas.


                               Tabela 54 – Exemplo de Transação Concorrente

1)   Transação 1 (T1) lê x =         2
2)   Transação 2 (T2) lê x =         2
3)   T1 faz x = x + 1
4)   T2 faz x = x + 3
5)   T1 armazena o valor de          x na base de dados
6)   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 de
atualizá-lo, esse dado será bloqueado (nenhuma outra transação poderá lê-lo) até que T1 o libere, ormalmente
após a sua atualização.

   Otimista: utilizar o controle otimista significa que se T1 lê e altera um dado ele não será bloqueado durante
o intervalo entre a leitura e atualização. Caso uma outra transação T2 tenha lido esse mesmo dado antes de T1
o atualizá-lo tente alterá-lo em seguida na base de dados, um erro de violação de concorrência deve ser
gerado.

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, a
primeira transação (Thread 1) atualiza este dado na base de dados e depois quem também o atualiza é a
segunda transação (Thread 2).
        Nesta abordagem otimista, acontece que a atualização do dado feita pela segunda transação
sobrescreve 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 conceito
de Version Number, que é um padrão utilizado para versionar numericamente os dados de uma linha de uma
tabela 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 de
dados, 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 na
base 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 a
Versão 2.
        Por fim, a primeira transação vai também atualizar este mesmo dado. Dessa forma, também é feita
uma 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 que
a 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 no
mapeamento das tabelas.
Para exemplificar o seu uso, considera-se a classe ContaCorrente na Tabela 55 que será mapeada para a tabela
CONTA_CORRENTE na base de dados.
        Dentre os diversos atributos da classe, está o atributo denominado versao que irá justamente guardar a
versão atual das linhas da tabela. A tabela CONTA_CORRENTE também deve ter uma coluna para onde esse
atributo 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), o
atributo 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 base
de 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 da
tabela. Neste caso, a classe ContaCorrente do exemplo anterior ao invés de ter um atributo inteiro para guardar
a versão do dado, teria uma atributo do tipo java.util.Date para guardar o instante no tempo da última
atualização.
        Neste caso, a classe de domínio seria equivalente à mostrada na Tabela 57 e seu mapeamento ao
exibido na Tabela 58. Neste exemplo, a tabela CONTA_CORRENTE deve conter uma coluna do tipo timestamp
denominada 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 ser
utilizada 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 se
os 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 o
atributo 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 a
atualização seria o exibido na Tabela 60.
                Neste exemplo, considera-se a atualização do saldo para R$ 1.500,00 de uma determinada
conta 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 UPDATE
para bloquear o dado até que o mesmo seja atualizado.

      O Hibernate fornece um conjunto de modos de lock (constantes disponíveis na classe LockMode) que
podem ser utilizados para implementar o lock pessimista.

       Considerando o exemplo da Tabela 61, onde um determinado aluno é consultado na base de dados e
tem seu nome atualizado.

Neste caso, não há um bloqueio ao dado, então qualquer outra transação pode acessar este mesmo dado
concorrentemente 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 passar
a constante LockMode.UPGRADE como terceiro argumento do método get do objeto Session.

                                                      Tabela 61 – Transação sem Lock

Transaction 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.UPGRADE

Transaction 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 lock
pessimista 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 em
memó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 lock
pessimista do banco (se suportado).

   Lock.UPDGRADE_NOWAIT: Mesmo que UPGRADE, mas desabilita a espera por liberação de locks, e
dispara 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 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 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 Query
Languange), 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 consulta
desejada, como, por exemplo, uma consulta hierárquica, pois Hibernate não suporta. Quando isto acontecer, a
API JDBC pode ser utilizada diretamente.

15.2 Hibernate Query Language - HQL
        HQL é uma linguagem de consulta semelhante à OQL (Object Query Language), no entanto voltada
para bancos de dados relacionais.
        Pertence a família do SQL, podendo ser facilmente compreendida através de algum conhecimento em
SQL.
        HQL suporta polimorfismo, herança e associações, pode incluir na consulta, restrições nas propriedades
da classe e associações, suporta ainda agregação, ordenação, paginação, subconsultas, outer joins, chamadas
de funções SQL e projeção, que permite buscar apenas os dados necessários, não sendo necessário carregar
todo 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 de
manipulação de dados (DML).
        Uma simples consulta usando HQL pode ser realizada através da cláusula from, mostrada na Tabela
63, onde temos a consulta à lista de todos os alunos, se desejar usar Aluno em outra parte da consulta basta
criar 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 para
agrupar 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 HQL
na Tabela 64.

                  Tabela 64 - Expressões HQL

from Aluno aluno where aluno.matricula >= 35
from 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 por
exemplo as tabelas Curso e Aluno. Para exemplificar os casos de joins, serão utilizados os dados abaixo das
tabelas 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 Join

from Curso c inner join Aluno a on c.id = a.curso.id

Ou:

from Curso c join Aluno a on c.id = a.curso.id

Resultado (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 join

from Curso c left outer join Aluno a on c.id = a.curso.id

Ou:

from Curso c left join Aluno a on c.id = a.curso.id

Resultado (omitido matricula 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
                3                    CURSO 3

       As consultas HQL normalmente não explicitam os joins. As associações já são informadas no
mapeamento das classes Java, o Hibernate com a informação no documento do mapeamento deduz os joins
necessários nas tabelas.

         Isto facilita as escritas das consultas. Existem quatro maneiras de realizar os joins, são: Join
ordinários (no from), Fetch Joins (usado para coleções), Estilos Theta (entre classes não associadas) e Joins
implí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 para
representar a consulta.

        A Tabela 69 apresenta um objeto Query sendo instanciado para fazer consultas da tabela ALUNO. O
comando q.list() faz com que todos os alunos cadastrados sejam retornados, já que a HQL utilizada foi “from
Aluno”.

                        Tabela 69 - Obtendo o resultado de uma consulta ao banco usando Query

Query q = session.createQuery("from Aluno");
q.list();

      A Tabela 70 apresenta em exemplo de consulta que retorna todos os cursos que possuem nomes
começados pela letra A.

       Já a consulta da Tabela 71 retorna todos os cursos que possui departamento com identificador igual a
2.


                  Tabela 70 - Exemplo com Query

String hql = "from Curso c where c.nome like ‘A%’";
Query q = session.createQuery(hql);
q.list();

                  Tabela 71 - Exemplo com Query

String 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 apenas
alguns dados da classe mapeada. A Tabela 73 apresenta um exemplo dessa consulta.

                  Tabela 73 - Exemplo Consulta de Projeção

String 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 mesmo
por 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 By
select count(*) from Aluno
select min(a.matricula), max(a.matricula) from Aluno a
select 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 que
esses parâmetros recebam nomes.
       Por exemplo, no exemplo da Tabela 75, deseja-se saber todos os alunos que possuem determinado
nome.
       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 seu
valor.

                   Tabela 75 - Exemplo Query: Nomeação de Parâmetros

Query 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 de
execução.
          Esta abordagem permite definir restrições dinamicamente sem que haja manipulação de Strings, a sua
flexibilidade 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ção
de 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 Criteria

Criteria 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ções
Criteria 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 Like
Criteria 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ários
níveis de subcriterias.
        Veja um exemplo na Tabela 79.


                   Tabela 79 – Sub-Criteria
Criteria 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 com
alguns valores das propriedades setados, retornando todos os objetos persistentes que possuam os valores das
propriedades. Veja exemplo na Tabela 80.

                   Tabela 80 – Query By Example
Aluno 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 ser
realizada 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 Query
Query 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 Criteria
Criteria 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 JPA
16.1 Introdução
Recentemente, o mapeamento objeto relacional utilizando Hibernate passou a ser feito também a partir de
anotações, de forma que se tornou mais simples, possibilitando uma maior produtividade no desenvolvimento
de aplicações.

Sobre a JPA
Posteriormente devido ao grande sucesso obtido pelo Hibernate, o mesmo foi adotado como base para a
especificação JPA (Java Persistence API, vide http://www.jcp.org/en/jsr/detail?id=317), especificação esta que
se 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 qual
será 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 pelo
compilador. Qualquer símbolo em um código Java que comece com uma @ (arroba) é uma anotação. Este
recurso foi introduzido na linguagem Java a partir da versão Java SE 5.0. Em outras palavras, as anotações
marcam 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 em
um método qualquer (metodoTeste), respectivamente. O exemplo é meramente ilustrativo, de forma que o
tipo de anotação definido não agrega nenhum significado especial ao código fonte.

@TesteAnotacao
public void metodoTeste{
           ...
}
Listagem 1 – Exemplo ilustrativo para o uso de um tipo de anotação
Inicialmente, o mapeamento objeto relacional com Hibernate era feito a partir de um conjunto de configurações
em arquivos XMLs. Com o surgimento das anotações no Java SE 5.0, o framework Hibernate anexou este
recurso, permitindo que as classes Java fossem mapeadas a partir de anotações, simplificando o seu uso. A
próxima seção apresentará um exemplo simples do uso da persistência de uma classe com Hibernate
Annotations.

Ativando o JPA no seu projeto Hibernate
Para que o Hibernate com anotações e JPA seja ativado, devem ser copiados as seguintes bibliotecas para
o seu classpath:

ejb3-persistence.jar
hibernate-annotations.jar
lucene-core-2.0.0.jar

Para que tudo funcione será necessário instanciar um objeto do tipo
org.hibernate.cfg.AnnotationConfiguration ao invés de um org.hibernate.cfg.Configuration, ou utilizar
as API´s específicas da JPA: javax.persistence.PersistenceManager e
javax.persistence.EntityManagerFactory, que substituem respecitivamente as classes Session e
SessionFactory.




                                                       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ções
Inicialmente, para que o Hibernate soubesse como carregar e armazenar objetos de classes persistentes, eram
utilizados apenas arquivos de mapeamento XML. Dessa forma, era possível informar que tabela do banco de
dados se refere uma dada classe persistente e quais colunas na tabela são referentes a quais atributos da
classe. Com o surgimento das anotações no Java 5.0, tornou-se possível substituir os arquivos XML para o
mapeamento objeto relacional. Através do uso de um conjunto de anotações no código fonte das classes
mapeadas.

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 banco
de dados a representa e quais atributos correspondem as quais colunas desta tabela.




Figura 1 - Classe Aluno

A 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: Aluno


Todas 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 na
anotaçã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 a
tabela 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á informando
o 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ária
pode ser dado tanto pela aplicação quanto por um mecanismo do Hibernate que o gere automaticamente. A
anotação @GeneratedValue permite a definição automática para o valor do identificador, utilizando um dos
mecanismos de geração apresentados anteriormente. Neste caso, utilizou-se a estratégia a partir de uma
seqüê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 chave
primária o próximo valor disponível por uma seqüência padrão chamada hibernate_sequence. Deve-se
salientar que o programador deverá criar uma seqüência com este nome na base de dados. Ainda em relação
ao identificador, como o nome da coluna mapeada é diferente do nome do atributo, é necessário utilizar a
anotação @Column informando o nome da coluna, através do atributo name. Neste exemplo, o nome da
coluna 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 feito
quando o nome do atributo é igual ao nome da coluna da tabela mapeada, de forma que não há a necessidade
de 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-se
realizar 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.xml


16.3 Outro Exemplo com Anotações JPA
A classe Cliente, ilustrada pela Listagem 2, possui exemplos de mapeamentos de atributos a partir das
anotações: @Column, @Transient, @Temporal. As anotações @Id e @GeneratedValue também são
utilizadas 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ções


A 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üência
Pró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 classes
O 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 entidade
Universidade da Figura 1. O relacionamento diz que uma universidade possui um conjunto de n centros e um
centro está associado a apenas uma única universidade. Considere as classes de domínio Java de uma
universidade 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 Universidade


package 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: Centro


A classe de domínio Universidade é a que possui um mapeamento do tipo 1-n através do atributo coleção de
centros. O seu mapeamento foi feito na Listagem 1 a partir da anotação @OneToMany. Como a coleção
conterá objetos do tipo Centro, então está classe também deverá ser uma classe persistente da aplicação. Na
anotação @OneToMany, existe um atributo denominado mappedBy que deverá receber como valor o nome
do 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 tabela
universidade, 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 ao
atributo 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ção
em cascata o relacionamento será tratado, ou seja, especifica quais operações deverão ser em cascata do
objeto 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 e
Universidade, mostrado também na Figura 1. Neste caso, o relacionamento está presente no mapeamento da
classe Centro, como mostrado na Listagem 2, a través da anotação @ManyToOne. Para facilitar o
entendimento, o trecho de mapeamento many-to-one do atributo universidade da classe Centro pode ser
visto 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 ManyToOne


A anotação @ManyToOne também possui o atributo fetch, que possui o mesmo comportamento apresentado
anteriormente. 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ão
aceitá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 é inserido
ou atualizado, respectivamente. O atributo do relacionamento não será inserido se insertable = false e não
será atualizado se updatable = false.


16.4.3 Demais Associações
As 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 detalhes
sobre anotações JPA veja:
http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html
Anotaçõ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
@DiscriminatorValue

Tabela 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 – Welcome

1- 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ários

1- 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 arquivo
register.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: registerForm
type: app.RegisterForm

8- Abrir o struts-config.xml, criar um Action Mapping;

Path: /register
Type: app.RegisterAction
Form Bean: registerForm
input: /register.jsp
forwards:

Name:success
Path: /success.html
Name: failure
Path: /failure.html

9- 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, chamada
registerForm;

12- Utilizando a variável registerForm criada, testar (if) se o atributo password1 igual a password2 , se
sim , 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: index
Path: /register.jsp

14- Na página /index.jsp , redirecionar para o forward index

15- 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 pessoais

1- 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 do
Eclipse;

3- No Windows, menu iniciar, opção Configurações/Painel de Controle/Ferramentas
Administrativas/Fontes de Dados ODBC/Fontes de dados do sistema, cadastrar uma fonte de dados
Access, com o nome “cadastro”, apontando para o arquivo cadastro.mdb contido no diretório data do seu
projeto cadastro;

4- Modificar o Action Mapping /cadastro:

type: app.CadastroAction
forward
      name: sucesso
      path: /pages/pessoa.jsp

5- 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.CadastroForm

8 – 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.do

9- 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.jsp

11 – 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 arquivo
cadastro.mdb recebeu um novo registro com os dados digitados anteriormente;

14- Na classe app.CadastroForm, descomente o metodo public ActionErrors validate, e complete
os TODO;

15 – De volta ao formulário de cadastro, entre com valores inválidos e verifique se o Struts irá validar a
sua 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ção


1- 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;


                                                       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.jsp

4- Completar os TODO da classe app.FormacaoAction

5- Cadastrar um Action Form:

       name: formacaoform
       type: DynaActionForm
       id                 Long
       idPessoa           Long
       idNivelEscolaridade       Integer
       instituicao        String
       anoInicio          Integer
       anoConclusao              Integer
       method             String

6- 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.do

7- Criar um atributo chamado formacoes, do tipo java.util.Collections na clase app.CadastroForm. Gerar gettter e
setter, 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.SubmitFormacaoAction

10- 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.jsp

12- Teste as funcionalidades da tela de formação, e verifique se as informações constam na tabela
formação no banco de dados.



Exercício 6 – Criação da tela de experiências

1- 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 do
Eclipse;

3- Modificar no Action Mapping /submitformacao:

       name:         continuar
       path:         /experiencia.do

4- Criar um Action Mapping

       name: /experiencia
       type: app.ExperienciaAction
       forward:
            name: sucesso
            path: /pages/experiencia.jsp

5- Criar um Form

       name: experienciaform
       type: DynaActionForm
       atributos:
            id               Long
            empresa          String
            dataInicioDisplay     String
            dataTerminoDisplay    String
            atribuicoes           String
            idPessoa         Long
            method                String

6- 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 ExperienciaAction

8- 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.do


9- Completar os TODO da pagina /pages/experiencia.jsp. Após concluir este passo, teste o botão de
continuar no /formacao.do no browser. Deverá aparecer a tela de entrada de dados de experiência
profissional.

10- Completar os TODO da classe app.SubmitExperienciaAction

12- Testar as funcionalidades da tela de experiência profissional, e verifique se as informações constam
na 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 Cadastrados

1- 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.




                                                       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 no
arquivo 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 globalizada

1- 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 String

4- Completar os TODO em app.LocaleAction

5- Completar os TODO em menu.jsp

6- 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: request
forward:
   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 complexo
devido 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: 2015

2- 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 arquivo
formacao.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 a
bCancel 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 para
DynaValidatorForm.

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 no
método SubmitFormacaoAction.adicionar, com o método form.validate(mapping,request). Testar os
botõ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: 1000

8- 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 arquivo
experiencia.jsp

  8.3 – Para dar um “bypass” na validação de um formulário vazio, modifique nos atributos onclick a
bCancel 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 no
método SubmitExperienciaAction.adicionar, com o método form.validate(mapping,request). Testar os
botõ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 Tiles
1- 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 definir
o raiz de sua aplicacao web como /web

3- Resolver os TODOS contidos no arquivo tiles-defs.xml

4- 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 "*" , exemplo
onde 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

Mais conteúdo relacionado

PPS
Lenguajes De Programación Web
PDF
Simulado concurso professor de educacao fisica questoes concurso pedagogia s...
DOC
Mitos del aprendizaje de segundas lenguas
PPTX
Presentación sobre java lenguaje de programacion
PDF
Wampserver caracteristicas y especificaciones
PPTX
Problema do Caixeiro Viajante
PPTX
SERVIDORES – WINDOWS SERVER
PDF
Dinâmica de predadores e presas
Lenguajes De Programación Web
Simulado concurso professor de educacao fisica questoes concurso pedagogia s...
Mitos del aprendizaje de segundas lenguas
Presentación sobre java lenguaje de programacion
Wampserver caracteristicas y especificaciones
Problema do Caixeiro Viajante
SERVIDORES – WINDOWS SERVER
Dinâmica de predadores e presas

Destaque (8)

PPTX
Predação
PDF
Introdução a predação
PPT
Predação
PDF
Predação
PDF
Evidencias da predação
PDF
Lince e Lebre
PDF
O modelo de Lotka e Volterra da predação
PPTX
Fundamento de Ecologia - fluxo de energia (nível superior)
Predação
Introdução a predação
Predação
Predação
Evidencias da predação
Lince e Lebre
O modelo de Lotka e Volterra da predação
Fundamento de Ecologia - fluxo de energia (nível superior)
Anúncio

Semelhante a Curso struts e hibernate (20)

PDF
Framework struts2v2.5
PDF
Tutorial struts
PPT
Spring & Struts
PPT
PDF
Apache Struts
PPTX
PDF
Arquitetura paralela
PDF
1409243945064
PDF
Sis avionico
PDF
White Paper da Spin para o SIMPASE 2013
PDF
Gerência de redes utilizando o cacti
PDF
ThingProvider-Proposal
PDF
Documento de arquitetura do software
PDF
Emacs - Arquitetura E Design Com Foco No Desenv De Plugins
PDF
31283575 protocolos-de-transporte-tcp-e-udp
PDF
Testes em aplicações JEE: Montando sua infra de testes automatizados
PDF
Cactus xp
PDF
Curso completo-de-fix-32
PPT
Trabalho camadas final+ (1)
Framework struts2v2.5
Tutorial struts
Spring & Struts
Apache Struts
Arquitetura paralela
1409243945064
Sis avionico
White Paper da Spin para o SIMPASE 2013
Gerência de redes utilizando o cacti
ThingProvider-Proposal
Documento de arquitetura do software
Emacs - Arquitetura E Design Com Foco No Desenv De Plugins
31283575 protocolos-de-transporte-tcp-e-udp
Testes em aplicações JEE: Montando sua infra de testes automatizados
Cactus xp
Curso completo-de-fix-32
Trabalho camadas final+ (1)
Anúncio

Mais de Carlos Antonio Castro Oliveira (10)

PDF
O emprego do_rup_na_uml_-_trabalho_poo_2012
PDF
Bancos de dados relacionais
PDF
Engenharia de Software - Pontos de função
PDF
Aplicando logica orientada_a_objeto_em_java
PDF
Estudo de caso da adoção das práticas e valores do extreme programming
PDF
Revista Engenharia de Software n° 44
PDF
Es06 teste de software
PPTX
Qualidade de software site bb
O emprego do_rup_na_uml_-_trabalho_poo_2012
Bancos de dados relacionais
Engenharia de Software - Pontos de função
Aplicando logica orientada_a_objeto_em_java
Estudo de caso da adoção das práticas e valores do extreme programming
Revista Engenharia de Software n° 44
Es06 teste de software
Qualidade de software site bb

Último (19)

PDF
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
PDF
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
PPTX
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
PDF
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
PPTX
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
PDF
Apple Pippin Uma breve introdução. - David Glotz
PDF
Custos e liquidação no SAP Transportation Management, TM130 Col18
PPTX
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
PDF
Aula04-Academia Heri- Tecnologia Geral 2025
PPTX
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
PDF
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
PPTX
Aula 18 - Manipulacao De Arquivos python
PDF
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
PDF
COBITxITIL-Entenda as diferença em uso governança TI
PPTX
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
PDF
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14
PDF
Processos na gestão de transportes, TM100 Col18
PPTX
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
PDF
Gestão de transportes básica no SAP S/4HANA, S4611 Col20
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
Apple Pippin Uma breve introdução. - David Glotz
Custos e liquidação no SAP Transportation Management, TM130 Col18
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
Aula04-Academia Heri- Tecnologia Geral 2025
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
Aula 18 - Manipulacao De Arquivos python
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
COBITxITIL-Entenda as diferença em uso governança TI
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14
Processos na gestão de transportes, TM100 Col18
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
Gestão de transportes básica no SAP S/4HANA, S4611 Col20

Curso struts e hibernate

  • 1. Versão 2.0 – Março - 2009 Revisada por Mauro de Souza Guimarães
  • 2. _____________________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
  • 3. _____________________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 oferecer facilidade de desenvolvimento de aplicativos Web com padrão Java Enterprise Edition (JEE). Oferece uma série de 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 API convencional, conhecida como "Biblioteca de classes"? Com uma API ou biblioteca de classes, você simplesmente utiliza fazendo chamadas às suas classes e interfaces. Em um framework de desenvolvimento, além da utilização de classes e interfaces, você também pode estender suas funcionalidades e alterar comportamentos. Tudo isso é possível através de um modelo de trabalho conhecido 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 de interfaces, 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 dos serviócs técnicos especializados descritos acima. Se o desenvolvedor tivesse que se preocupar com todas as questõ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
  • 4. _____________________Curso Struts & Hibernate______________ 2. O padrão de arquitetura M-V-C (Model – View – Controller). Uma rápida revisão. O padrão de arquitetura M.V.C. é o mais utilizado atualmente para soluções Web JEE e está presente nas principais soluções JEE de grandes empresas. Este padrão determina a divisão do aplicativo em três principais partes: 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ão capazes de crescer sem qualquer dificuldade. A complexidade, ou o que chamamos de responsabilidade de componentes, é dividida de maneira mais inteligente, propiciando fraco acoplamento entre camadas, garantindo ao desenvolvedor 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 grande credibilidade e flexibilidade para desenvolvimento de aplicações Web em Java. Veja no diagrama abaixo, o relacionamento 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
  • 5. _____________________Curso Struts & Hibernate______________ 3. O mecanismo do M-V-C em uma aplicação Web Funciona assim: A IDA... VIEW Um usuário digita uma URL, no browser. A página é localizada em um Servidor web, e este devolve para o browser uma página que é, por exemplo, um formulário. Esta página , o formulário, representa a camada de interface com o usuário: a camada View (visão). Ela interage com o usuário tanto na entrada, isto é, no momento que o usuário está preenchendo um cadastro, ou acionando um Hiperlink dentro de um site de compras, quanto na saí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 é enviado para o Servidor Web, através do protocolo HTTP, junto com um objeto "Request" , que leva junto todos os campos do formulário preenchidos pelo usuário. Estes campos são apresentados a um "servlet" desenvolvido com a missão de "descascar" os dados fornecidos pelo usuário na outra ponta da Web (browser cliente) além de identificar "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 desenvolvidas para atender ao negócio. Este "servlet" está agindo como um Controlador (Controller). Esta é a camada de Controle. MODEL A classe de negócio, acionada pelo Controlador, é uma classe especializada para exercer a função para a qual ela foi escrita. Por exemplo, para o formulário enviado pelo usuário na camada de apresentação e cujos dados 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", efetuar cálculos... E A VOLTA.... MODEL A classe de negócios aí de cima, ao terminar sua tarefa, prepara os dados para serem enviados pelo Controlador 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 da classe 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 classe de 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
  • 6. _____________________Curso Struts & Hibernate______________ 4. O mecanismo do M-V-C em uma aplicação Web, com o STRUTS. Veja o diagrama abaixo: Jakarta Struts Framework – Modelo MVC 3 Na 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
  • 7. _____________________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.x 5.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
  • 8. _____________________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
  • 9. _____________________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) ou integrado 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" que deverá 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
  • 10. _____________________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 dentro da 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
  • 11. _____________________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, conforme as 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 CLICAR NO BOTÃO "NEXT". 3. Depois de informar o nome do projeto, deixe o nome do contexto (o nome que vem depois da porta 8080 na URL digitada no browser) como o nome do projeto; deixe selecionada a opção “Can update server.xml file” , e na opçã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
  • 12. _____________________Curso Struts & Hibernate______________ 4.Estas ações irão criar um projeto com as devidas bibliotecas "servlet/jsp" provenientes do tomcat e irá criar um diretó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
  • 13. _____________________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ção em 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 o que o aluno precisará fazer é: 1) Copiar o arquivo "Struts-Blank.war" da pasta "webapps" do diretório struts-1.2.8 , criado com a descompactaçã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 de arquivo "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 no Eclipse (projeto "logon" página 10), podendo sobrescrever os arquivos pré-existentes. Logo em seguida você deve dar “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" deve ficar 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
  • 14. _____________________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
  • 15. _____________________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 container's "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
  • 16. _____________________Curso Struts & Hibernate______________ 9. Agora, os detalhes do mecanismo... O Framework Struts inaugura o conceito de “Programação Declarativa", isto é, muitas informações importantes 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 é consultado pelo "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 Servlets devem ser carregados pelo conteiner. Desta forma, o "ActionServlet" é carregado automáticamente e fica na memó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 compreender definitivamente, 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 o usuário confirma a senha. Ao final do processo, aciona o botão "OK", que é o botão de "Submit". Não se esqueç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
  • 17. _____________________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 pela clá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 uma tag <action> que possua uma cláusula "path" que possua a palavra "/register", que coincida com a palavra indicada na tag action 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 a senha 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
  • 18. _____________________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ários criar 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" que sã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 classe java, um JavaBean para ser mais exato. Esta classe, deve "estender" a classe org.apache.struts.ActionForm e como já explicamos antes, este objeto captura os parâmetros do formulário trazido pelo Request. Para funcionar corretamente, é necessário que o RegisterForm possua as variáveis de instância coincidindo com os nomes dos campos 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
  • 19. _____________________Curso Struts & Hibernate______________ Action Um Action é uma classe java que extende org.jakarta.struts.Action. Após o ActionServlet, preencher o ActionForm (RegisterForm no nosso aplicativo) ele aciona um Action, entregando para ele o ActionForm preenchido, para que ele, Action, valide os campos do ActionForm, depois decida quais outras informações de negócios serão recuperadas/criadas/alteradas e no final do processamento, a classe Action retorna um outro objeto chamado "ActionForward" (que indica um "caminho" de um recurso, podendo ser uma página JSP de resposta, 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ência de vários objetos como ActionMapping, ActionForm, HttpServeltRequest e HttpServletResponse). Este método é o coraçã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
  • 20. _____________________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 encontra name=”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
  • 21. _____________________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 da pá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 o Servidor. O TomCat sabe através da leitura do arquivo "web.xml" que, pelo padrão ".do" ele deve entregar estes dados para um ActionServlet, mais específicamente o "RegisterAction". Esta solicitação (request) é então processada pelo "RegisterAction". O "RegisterAction" lê o arquivo struts-config.xml procurando por uma tag <action> que possua a cláusula "path" coincidindo com o padrão register.do como indicado no arquivo Register.jsp. Mas procura apenas por "/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 o controle da execução para a classe Action, indicada na cláusula "type" dentro da tag <action> " e disponibiliza o JavaBean (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 ser chamada. No exemplo, a cláusula input aponta para “/Register.jsp”, indicando que chama novamente o formulá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. Geralmente este 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 e as 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
  • 22. _____________________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 a solicitaçã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 e facilitarão outras ações. Se outras bibliotecas de tags fossem utilizadas pela aplicação, estas seriam configuradas neste mesmo local, 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
  • 23. _____________________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
  • 24. _____________________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 site com mensagens em várias línguas , utilizará este arquivo de recursos para, fácil e rápidamente criar várias versõ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 de internacionalizaçã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 é o MessageResources.properties. Ele é um arquivo que pode ser editado por qualquer editor de texto (até o NotePad) 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 de propriedades 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 arquivo MessageResources. Isto indica para o Struts que ele deverá buscar, debaixo do diretório/pacote "resources", um arquivo MessageResources.properties Para cada novo idioma deve ser criado um arquivo MessageResources_yy_XX.properties, onde yy é a sigla da língua e XX, a sigla o País, por exemplo MessageResource_fr_FR.properties, informa que o conteúdo das mensagens é da lingua francesa da FRANÇA, ou MessageResource_es_ES.properties , informa que o conteúdo das mensagens é da lingua espanhola da ESPANHA Também podemos informar no arquivo Struts-config.xml, que existe um arquivo de propriedades para internacionalizaçã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 o seguinte 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
  • 25. _____________________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
  • 26. _____________________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
  • 27. _____________________Curso Struts & Hibernate______________ 17.1 Jakarta Commons - BeanUtils O 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ócio Commons 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
  • 28. _____________________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, tem reduzido isso. Você pode adcionar alguns métodos simples a uma classe de base ActionForm e facilitar a transferência dos dados para, e , a partir de qualquer outro componente usando a reflexão. Os métodos são apenas componentes em torno dos métodos da classe BeanUtils usados em outro lugar no framework. 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 pacote Commons 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 em qualquer direção. O novo copyProperties facilitará a "ida e volta" de seus ActionForms e dos componentes 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 em myBusinessBeans, permite que a operação de negócio atualize os valores e então transfere os tipos nativos de volta para String myActionForm 17.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
  • 29. _____________________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 na linha 141, um forward indicando que a página Welcome.jsp, no diretório "pages" referente ao contexto , deve ser apresentada assim que o URI "logon.do" for aplicado pelo browser. Da mesma forma, na linha 143, podemos observar 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 da execução da classe de negócio LogonAction caso o método execute( ) do Action encaminhe de volta ao Servlet para procurar um ActionForward com o nome lógico de success, o fluxo de execução do programa será desviado para outro Action : o welcome.do. O professor deve explicar que, dentro do struts-config.xml, deverá existir uma outra 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 num hyperlink 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 o padrão, sem o ".do" (como vimos anteriormente). Os objetos ActionMapping ficam catalogados dentro da tag <ActionMappings, que é uma coleção de ActionMapping. 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
  • 30. _____________________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 pelo browser 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 as informaçõ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 passam grande 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 que indica qual o servlet carregar, lembra?) analisa a URI digitada ou informada pela cláusula action do HTML que deve 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 uma tag 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 pela implementaçã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
  • 31. _____________________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 objetos para 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 de negócio. Para isto, o Action pode dispor do objeto ActionForm, que é passado como parâmetro. Lembrem-se de que o objeto ActionForm possuem os parâmetros do formulário e ficam desta forma, disponíveis para o Action. Separar as camadas IMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!! IMPORTANTE !!!!! IMPORTANTE !!!!! IMPORTANTE !!!!! É importante EVITAR colocar qualquer lógica de negócio na própria class Action. A classe Action deve simplesmente reunir qualquer dado que os métodos de negócio e classes Action precisarem, e transmiti-los. Os mé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 em muito o “acoplamento” entre as camadas de Modelo (Regras de Negócio) e a camada de Controle (ActionServlet e Action). O que deve ser feito é que outras classes extendam Action e executem o método execute( ). Este método sim, é que deve chamar as classes que iremos construir e que implementam as regras de negócio Tratamento de Exceções As classes Action também detectam os erros que possam acontecer. O processo envolve a utilização de dois objetos: ActionMessages e ActionError. Este assunto será coberto e apresentado em exemplos em alguns capí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
  • 32. _____________________Curso Struts & Hibernate______________ As classes Action também executam o tratamento de exceções. Para isto, a fim de tratar uma exceção de uma maneira consistente em todos os objetos Action, o programador poderá registrar um ExceptionHandler com o arquivo 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 o caminho 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 é o objeto Action que seleciona qual ActionForward deve ser executado. O ActionForward define o "para onde";o objeto Action define o "quando". A maneira mais comum de uma classe Action selecionar um envio é através do método findForward do ActionMapping, desta forma: return mapping.findForward("sucesso"); DispatchAction Uma estratégia comum entre os desenvolvedores Struts é usar a mesma classe Action para lidar com várias tarefas afins. Um bom exemplo é executar as operações CRUD (create, Read, Update e Delete) básicas em um registro de 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 diversos mé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, HttpServletRequest request, 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
  • 33. _____________________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=update 18. Como exibir conteúdo dinâmico - Tag Libs O 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 novos componentes logic Tags para gerenciar a geração condicional de saída, fazer um loop nas coleções de objetos para uma geração repetida da saída e o gerenciamento de fluxo da aplicação 18.1 Instalando as extensões da tag do Struts • Assim como qualquer outra biblioteca de tags, as existentes no Struts precisam ser declaradas no descritor web.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
  • 34. _____________________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 beans e 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
  • 35. _____________________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
  • 36. _____________________Curso Struts & Hibernate______________ • Logic tags para fazer um pouco de lógica sem scriptlets, apenas através de parâmetros apropriados Exemplo 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 nesta coleçã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
  • 37. _____________________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 um arquivo 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. Isto porque um único arquivo struts-config.xml, tende a ficar indisponível por muito tempo com um mesmo desenvolvedor. 20 - Tiles Framework – Gerenciamento de Layouts • O Tiles apresenta-se como um framework de gerenciamento de layout de aplicações web. O mesmo pode ser utilizado 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áginas web. É comum a reutilização em outras camadas do modelo MVC, porém não há nenhum motivo para não beneficiarmos 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ário do sistema solicita uma mudança no padrão visual do sistema, como mudar o logotipo da empresa. Sem o uso de um mecanismo de templates como o Tiles, você teria que alterar todas as páginas de sua aplicação. Com o Tiles dependendo 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ão dinâ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
  • 38. _____________________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 facilitar a criação de templates. Assim como para qualquer outro conjunto de tags, devemos declarar no descritor web.xml a 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 este aquivo no diretório "WEB-INF",da aplicação. Após salvar o arquivo podemos então declarar a utilização da taglib em 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
  • 39. _____________________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. O arquivo tiles-defs.xml (conforme declarado anteriormente), irá conter a estrutura de cada um dos templates utilizados pelo Tiles. Observe o exemplo abaixo: <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration//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. A página de template padrao.jsp está divida em quatro áreas distintas (topo, menu, conteúdo e rodapé). Estes por 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 de herança de layouts. Para este propósito utilizamos o argumento extends da tag definition. Desta forma podemos 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
  • 40. _____________________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 forward de 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 Struts Configuration 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 mapeamento portal.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
  • 41. _____________________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ágina corresponde 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 do código deverá fazer a inclusão dinâmica das demais páginas (topo,conteúdo,menu e rodapé). Todas as definições de 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><font color="#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
  • 42. _____________________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
  • 43. _____________________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
  • 44. _____________________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 foi implementada, 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
  • 45. _____________________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
  • 46. _____________________Curso Struts & Hibernate______________ •A tag <html:javascript> gera código de acordo com configurações determinadas nos arquivos validation.xml e validator-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 retorno Quando criamos botões do tipo <html:cancel> ou até botões de “voltar” que venham a submeter o formulário, não queremos que a validação de Javascript seja executada. Neste caso, atribuímos o valor false à variável de Javascript 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ção web 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
  • 47. _____________________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
  • 48. _____________________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 das solicitaçõ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
  • 49. _____________________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
  • 50. _____________________Curso Struts & Hibernate______________ ÍNDICE ANALÍTICO 1. Conceitos Gerais ------------------------------------------------------------------------------------------------52 1.1 Persistência ---------------------------------------------------------------------------------------------- 52 1.2 Entidades ------------------------------------------------------------------------------------------------- 52 1.3 Mapeamento Objeto Relacional ---------------------------------------------------------------- 53 1.3.1 Mapeamento de um objeto com tipos primitivos -------------------------- 53 1.3.2 Mapeamento de objetos que contém uma coleção de objetos ------------- 54 2. Introdução ao Hibernate-------------------------------------------------------------------------------------56 3. 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 ----------------------------------------------------------------------- 59 4. Classes Persistentes -------------------------------------------------------------------------------------------59 4.1 Identidade/Igualdade entre Objetos --------------------------------------------------------- 61 4.2 Escolhendo Chaves Primárias ------------------------------------------------------------------- 61 5. Objetos Persistentes, Transientes e Detached ----------------------------------------------------62 6. Instalando o Hibernate ---------------------------------------------------------------------------------------63 8. Configurando o Hibernate-----------------------------------------------------------------------------------68 9. Manipulando Objetos Persistentes ----------------------------------------------------------------------71 10. 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 --------------------------------------------------------------- 81 10.4.1 Composite-id---------------------------------------------------------------- 82 10.5 Associações 1-1 (one-to-one) ----------------------------------------------------------------- 83 11. Coleções ----------------------------------------------------------------------------------------------------------85 11.1 Set --------------------------------------------------------------------------------------------------------- 85 11.2 List--------------------------------------------------------------------------------------------------------- 87 11.3 Map-------------------------------------------------------------------------------------------------------- 88 12. Herança --------------------------------------------------------------------------------------------------- 88 13. 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
  • 51. _____________________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 -------------------------------------------------------- 97 14. Concorrência ----------------------------------------------------------------------------------------------------97 14.1 Lock Otimista ----------------------------------------------------------------------------------------- 98 14.2 Lock Pessimista ------------------------------------------------------------------------------------- 102 15. 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 ---------------------------------------------------------------------------------------- 108 16. 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
  • 52. _____________________Curso Struts & Hibernate______________ 1. Conceitos Gerais 1.1 Persistência Imagine um usuário fazendo uso de uma aplicação, por exemplo, um sistema para controlar suas finanças. Ele passa a fornecer como dados de entrada todos os seus gastos mensais para que a aplicação lhe gere, 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 se encontra. Imagine agora que o usuário teve novos gastos, voltou a ligar o computador, acessou novamente o sistema de finanças e que gostaria de realizar novas análises com todos os seus gastos acumulados. Se a aplicação não armazenar, de alguma forma, os primeiros gastos fornecidos, o usuário teria que informá-los novamente e em seguida, acrescentar os novos gastos para fazer a nova análise, causando grande 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 cada vez 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 de execução do software, os objetos das classes entity (classes de entidade) irão representar a ocorrência dessas entidades do mundo real. Também são conhecidas como classes de domínio da aplicação. Exemplos: Cliente; Pessoa; Curso Notificaçã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 ambiente de execução. Os objetos de "classes de entidade" precisam ser não-voláteis ou persistentes, isto é, precisam se manter entre diversas sessões de utilização de software - sessões que podem ser estabelecidas por usuários diferentes. Um objeto pode ser considerado persistente quando seus atributos podem ser armazenados ao término de 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 de dados orientadas a objeto do software. As demais, não sendo orientadas a objetos, conseguirão representar uma estrutura OO através de processos de adaptação ou mapeamento de estruturas de dados. Em todos os casos 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
  • 53. _____________________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 a comunicaçã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 de dados de arquivos. Para esse tipo de base de dados foi criada uma linguagem, a SQL = Structured Query Language. Essa linguagem foi toda baseada na lógica relacional e por isso contava com diversas otimizações em suas tarefas se comparadas 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 um grande volume de dados. Entretanto, essa linguagem não propiciava aos desenvolvedores uma facilidade para que a produtividade fosse aumentada. Uma solução que surgiu no início da década de 90 foi à criação de um modelo de banco de dados baseado no conceito de orientação a objetos. Este modelo visava facilitar, para os desenvolvedores, a implementação da camada de persistência da aplicação, pois eles já estavam familiarizados com o paradigma de orientaçã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 um volume de dados muito grande e esse modelo era ineficiente em termos de tempo de resposta, pois ao contrário dos bancos de dados relacionais, eles não tinham um modelo matemático que facilitasse as suas operações de persistências. Então a solução foi usar os BDR e desenvolver ferramentas para que o seu uso seja facilitado. Uma dessas 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 da tabela (tupla) em um objeto da aplicação. A seguir, mostraremos alguns tipos de mapeamentos entre objetos e tipos, primitivos ou tipos não primitivos 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 salientar que se entende por tipos básicos aqueles que possuem um correspondente em SQL, ou seja, o tipo String da linguagem 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
  • 54. _____________________Curso Struts & Hibernate______________ Na Figura 1, abaixo, observa-se o mapeamento de três objetos do tipo Veículo na tabela de um banco de dados. Caso a aplicação deseje saber o veículo da cor vermelha, por exemplo, então o objeto que tem o Palio como 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 esse conceito é 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 de veí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, como mostrado 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
  • 55. _____________________Curso Struts & Hibernate______________ O atributo "fabricante" adicionado à classe Veiculo, serve simplesmente para relacionar um veículo ao seu 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 uma alteração no modelo do banco de dados. Primeiramente, o vínculo que foi realizado entre um fabricante e um veículo deverá ser implementado através de uma chave estrangeira (FK = referência a uma outra tabela, pois em Banco de Dados Relacionais não existe o conceito de coleções) que se localizará na tabela VEICULO, caracterizando o mapeamento 1 para N, ou seja, uma instância da entidade veículo "possui" (está relacionado) a uma instância da entidade fabricante 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 atributo fabricante 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 tabelas no BDR. Nele observa-se que cada veículo está associado a um fabricante, isso implica dizer que na tabela de VEICULO existe uma referência para a tabela FABRICANTE (chave estrangeira na entidade Veículo que é chave primá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 ao seu respectivo fabricante, no momento da inserção. Para recuperar os veículos inseridos o desenvolvedor terá que implementar uma busca que retorne as informaçõ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
  • 56. _____________________Curso Struts & Hibernate______________ Por exemplo, caso a aplicação deseje as informações do veículo do modelo Palio, então para se buscar o 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 que buscará 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 a outros objetos. Com a idéia do MOR (do inglês ORM = Object Relational Modeling) vários projetos de ferramenta começaram a ser desenvolvidas, visando facilitar a implementação da camada de persistência, dentre elas o framework Hibernate, que é um software livre de código aberto e que está tendo uma forte adesão de novos projetos corporativos. 2. Introdução ao Hibernate O Hibernate é uma ferramenta de mapeamento objeto/relacional para Java, e recentemente foi disponibilizada para a plataforma "dot net". Ela transforma os dados tabulares de um banco de dados em um conjunto de objetos definido pelo desenvolvedor. Usando o Hibernate, o desenvolvedor se livra de escrever muito do código de acesso a banco de dados e de SQL que ele escreveria não usando a ferramenta, acelerando a 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 uso extensivo de stored procedures, triggers ou que implementam a maior parte da lógica da aplicação no banco de dados, 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 de negó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 plataforma de 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 dados enquanto 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 fazendo necessário todo um design de tabelas antes de desenvolver seu projeto que pode ser muito bem utilizado em projetos pequenos. Já projetos grandes onde o plano de ação padrão tomado pelo Hibernate não satisfaz as necessidades da empresa (como o uso de select *, joins etc), ele possui dezenas de otimizações que podem ser feitas para atingir tal objetivo. O projeto open-source Hibernate (www.hibernate.org) vem se consolidando entre a comunidade de desenvolvedores Java como o melhor framework de persistência - levando em consideração os seguintes fatores: 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
  • 57. _____________________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 que este framework oferece para otimizar a construção de aplicações robustas, onde o programador vai dedicar maior 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, é uma ferramenta 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ém disponibiliza um poderoso mecanismo de consulta de dados, permitindo uma redução considerável no tempo de desenvolvimento 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
  • 58. _____________________Curso Struts & Hibernate______________ 3. Arquitetura do Hibernate A arquitetura do Hibernate é formada basicamente por um conjunto de interfaces. A Figura 4 apresenta as 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 a separaçã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 de dados: 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
  • 59. _____________________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 de uma 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 como fá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 que este 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. Com ele, define-se diversas configurações do Hibernate, como por exemplo: o driver do banco de dados a ser utilizado, 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 de banco 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 de manipulação de dados. O uso dessa interface em aplicações que usam Hibernate é opcional. Essa interface abstrai 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 de negó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, e mé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
  • 60. _____________________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
  • 61. _____________________Curso Struts & Hibernate______________ Considerações: O Hibernate requer que toda classe persistente possua um construtor padrão sem argumentos, assim, o Hibernate pode instanciá-las simplesmente chamando Construtor.newInstance(); Observe que a classe Pessoa apresenta métodos setters e getters para acessar ou retornar todos os seus atributos. 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 utilizar Hibernate, todos os objetos persistentes possuam um identificador e que eles sejam independentes da lógica de negó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 se obj1.equals(obj2), retorna um booleano 'true' . Incluindo o conceito de persistência, passa a existir um novo conceito de identidade, a identidade de banco de dados. Dois objetos armazenados em um banco de dados são idênticos se forem mapeados em uma mesma linha 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 de chaves primárias. Uma chave primária é uma coluna ou um conjunto de colunas que identifica unicamente uma linha de uma 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 essas propriedades. Se a tabela possui um único atributo que a identifique, ele é por definição a sua chave primária. Se possuir várias chaves que atendem a estas características, elas são chamadas de chaves candidatas e, apenas uma (um campo, uma coluna) deve ser escolhida para representar a chave primária e as demais colunas devem 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 de negócio. Por exemplo, o atributo cpf da tabela Pessoa (associada à classe Pessoa). Essa estratégia pode não ser muito boa em longo prazo, já que uma chave primária adequada deve ser constante, única e não nula. Se uma Pessoa, não possuir cpf (muitas mulheres utilizam o cpf do marido e existem pessoas que não possuem cpf) 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. Um problema 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
  • 62. _____________________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 uma camada de persistência. Isto é feito, invocando o gerenciador de persistência e as interfaces de consultas do Hibernate. Quando interagindo com o mecanismo de persistência, é necessário para a aplicação ter conhecimento sobre 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 mesmo após a destruição do processo que o criou. Na verdade, o que continua a existir é seu estado, já que pode ser armazenado 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 o instanciou. Em relação às classes persistentes, nem todas as suas instâncias possuem necessariamente um 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 algum contexto persistente. Eles são instanciados, utilizados e após a sua destruição não podem ser reconstruídos automaticamente; 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 que por 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
  • 63. _____________________Curso Struts & Hibernate______________ 6. Instalando o Hibernate Instalar o Hibernate é uma tarefa bastante simples. O primeiro passo é copiar sua versão do site http://hibernate.org, disponível em um arquivo compactado. Por fim, este arquivo deve ser descompactado e seu conteúdo consiste em um conjunto de arquivos JARs (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 driver do banco de dados utilizado. Depois de fazer o download, adicione o arquivo hibernate3.jar e os seguintes arquivos 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 scripts SQL pra gerar as tabelas podem ser facilmente adaptados para outros bancos. Usando o MySQL você também vai 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 de ser capaz de montar um ambiente de desenvolvimento Java com todas as configurações necessárias.objetos do 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
  • 64. _____________________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 ser acessada 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 sem argumento 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 ao má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 um endereç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 possui um 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 seu coordenador, 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 que pertence. 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
  • 65. _____________________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
  • 66. _____________________Curso Struts & Hibernate______________ Neste primeiro exemplo, será apresentado o mapeamento da classe Aluno em um arquivo XML, que o Hibernate utiliza para saber que tabela no banco de dados a representa. Os arquivos de mapeamentos XML entre classes e tabelas do banco de dados devem ser nomeados como *.hbm.xml (convenção definida pela comunidade 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 Hibernate possuem a estrutura básica mostrada na Tabela 4. O arquivo XML começa normalmente com as definições da DTD (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
  • 67. _____________________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 partir deste 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 se refere 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 nome da classe for diferente do nome da tabela a que se referencia, o nome da tabela é informado a partir do atributo 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 da tabela. 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 ilustrado na tabela 2, para esse exemplo, a estratégia utilizada foi sequence. Dessa forma, o nome da seqüência també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
  • 68. _____________________Curso Struts & Hibernate______________ Agora as declarações das propriedades persistentes das classes serão incluídas no arquivo de mapeamento. 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 seus wrappers, 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 propriedade pelo atributo XML type e a coluna da tabela a que se refere, pelo atributo XML column. Observe que a propriedade nome não possui seu tipo e coluna a que se referenciam definidos. Se o atributo column não aparece no mapeamento da propriedade, o Hibernate considera que a coluna na tabela do banco de dados a que se referencia possui o mesmo nome que o definido pelo atributo name. Então pode-se concluir que a propriedade "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 da coluna na tabela, converter para o tipo adequado Java. O atributo not-null presente no mapeamento do atributo cpf serve para informar se a coluna pode ser 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 tem com a classe Curso ( um Aluno pode fazer muitos Cursos). Uma descrição mais detalhada desta tag 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 Hibernate Pode-se configurar o Hibernate de três maneiras distintas: Instanciar um objeto de configuração (org.hibernate.cfg.Configuration) e inserir suas propriedades programaticamente; 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
  • 69. _____________________Curso Struts & Hibernate______________ Usar um arquivo .properties com as suas configurações e indicar os arquivos de mapeamento programaticamente; Usar um arquivo XML (hibernate.cfg.xml) com as propriedades de inicialização e os caminhos dos arquivos de 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 ser configurados. 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
  • 70. _____________________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 para identificar as particularidades do banco de dados; hibernate.connection.driver_class: Nome da classe do driver JDBC do banco de dados que está sendo utilizado; 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 o SessionFactory é 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íveis valores para os dilates estão presentes na Tabela 9: Tabela 9 - Possíveis valores de dialetos DB2 - org.hibernate.dialect.DB2Dialect HypersonicSQL - org.hibernate.dialect.HSQLDialect Informix - org.hibernate.dialect.InformixDialect Ingres - org.hibernate.dialect.IngresDialect Interbase - org.hibernate.dialect.InterbaseDialect Pointbase - org.hibernate.dialect.PointbaseDialect PostgreSQL - org.hibernate.dialect.PostgreSQLDialect Mckoi SQL - org.hibernate.dialect.MckoiDialect Microsoft SQL Server - org.hibernate.dialect.SQLServerDialect MySQL - org.hibernate.dialect.MySQLDialect Oracle (any version) - org.hibernate.dialect.OracleDialect Oracle 9 - org.hibernate.dialect.Oracle9Dialect Progress - org.hibernate.dialect.ProgressDialect FrontBase - org.hibernate.dialect.FrontbaseDialect SAP DB - org.hibernate.dialect.SAPDBDialect Sybase - org.hibernate.dialect.SybaseDialect Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect O final do arquivo hibernate.cfg.xml é onde devem ser informados os arquivos de mapeamentos das classes que o Hibernate deve processar. Se algum arquivo de mapeamento não for definido neste local, a classe a 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
  • 71. _____________________Curso Struts & Hibernate______________ 9. Manipulando Objetos Persistentes O Hibernate utiliza objetos Session para persistir e recuperar objetos. Um objeto Session pode ser considerado 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ência 1. try{ 2. //SessionFactory deve ser criado uma única vez durante a execução 3. //da aplicação 4. SessionFactory sf = new Configuration().configure("/hibernate.cfg.xml").buildSessionFactory(); 5. Session session = sf.openSession(); //Abre sessão 6. Transaction tx = session.beginTransaction(); //Cria transação 7. 8. //Cria objeto Aluno 9. 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 e 14. //recuperado para ser atribuído neste momento. 15. aluno.setCurso(curso); 16. 17. session.save(aluno); //Realiza persistência 18. tx.commit(); //Fecha transação 19. session.close(); //Fecha sessão 20. } 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. O objeto SessionFactory armazena os mapeamentos e configurações do Hibernate. É um objeto pesado e lento de se criar. Pode-se pensar em colocar estas instruções em um Bloco Estático para minimizar o desperdício de tempo. 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
  • 72. _____________________Curso Struts & Hibernate______________ Em relação ao método saveOrUpdate, uma questão que se pode formular é “Como o Hibernate sabe se o objeto em questão já existe ou não no banco de dados, ou seja, se ele deve ser criado ou atualizado?”. A resposta é 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 chave primá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 do objeto 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
  • 73. _____________________Curso Struts & Hibernate______________ 10. Associações O 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. Todos os exemplos apresentados nesta seção baseiam-se no diagrama de classes mostrado na Figura 6. 10.1 Associações 1-n (one-to-many) Para exemplificar o relacionamento 1-n, considere o relacionamento entre a entidade Centro e a entidade Universidade da Figura 7. O relacionamento diz que "uma universidade possui um conjunto de n centros" e "um centro está associado a apenas uma única universidade". Considere as classes de domínio Java de 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
  • 74. _____________________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 ser visto 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. O atributo key representa a coluna da tabela relacionada (Centro) que possui a chave estrangeira para a classe Universidade. 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 o Hibernate saiba como tratar a associação entre duas tabelas. Quando um lado da associação define o atributo inverse 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 da universidade) 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
  • 75. _____________________Curso Struts & Hibernate______________ Dessa forma, a resolução do problema é feita apenas definindo o atributo lazy como sendo true. A coleçã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 da chamada ao método getCentros(). 10.1.1 - O atributo inverse Considerando o relacionamento entre uma universidade e seus centros, no mapeamento do conjunto de centros em universidade, o atributo inverse é igual a true. Dessa forma, a criação ou atualização do relacionamento entre um centro e uma universidade será feita durante a persistência ou atualização de um objeto Centro. A partir do exemplo apresentado na Tabela 18, cria-se uma instância da classe Universidade e define-se um valor para o atributo nome. Em seguida, uma instância da classe Centro também é criada, definindo o atributo nome e o atributo universidade (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 como false. O que acontece é que o Hibernate insere uma linha na tabela UNIVERSIDADE e em seguida tenta atualizar o relacionamento entre uma universidade e um centro, no caso a partir de um UPDATE na tabela CENTRO, 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 o relacionamento entre uma universidade e um centro logo após a inserção da universidade. Neste caso, como o relacionamento 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 tabela CENTRO 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
  • 76. _____________________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 o có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 da inserção de uma universidade o Hibernate não atualiza o relacionamento entre ela e seus centros, pois espera que ele seja feito no momento da inserção/atualização de um objeto Centro. Tabela 21 - SQL gerado pelo Hibernate com atributo inverse=true Hibernate: 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 dos dois lados foi atualizado, ou seja, vai sempre atualizar os dois lados de uma vez, uma atualização para cada classe da relação, o que seria desnecessário. Caso contrário, o Hibernate passa, a saber, de qual lado fazer a atualizaçã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 programador 10.2 Associações n-1 (many-to-one) O relacionamento n-1 será apresentado a partir do relacionamento <manyto-one> existente entre a tabela Centro e a tabela Universidade. Neste caso, o relacionamento está presente no mapeamento da classe Centro, 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
  • 77. _____________________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 apresentados na 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 retirado da 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
  • 78. _____________________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 Curso mostrado 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 de dados. 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 de departamentos. 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 de determinado curso, mas se for realmente necessário, o Hibernate apresenta outros mecanismos para a obtençã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
  • 79. _____________________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 mapeamento da 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
  • 80. _____________________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ção departamentos 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 chave estrangeira 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 mapeamento da entidade Departamento o atributo inverse é igual a true, significando que na tabela DEPARTAMENTO_CURSO só será inserido o relacionamento entre as duas entidades, quando um curso for inserido no banco de dados associado a um departamento. Neste caso, não seria necessário mapear a coleção de cursos em Departamento, pois não está sendo utilizada para popular a tabela de relacionamento. Como já citado, para recuperar a coleção de cursos de um departamento, o Hibernate apresenta outros mecanismos. Em outros relacionamentos n-n, pode ser que seja necessário inserir/atualizar o relacionamento na tabela 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 recupera um objeto persistente da classe Curso com identificador igual a 1, adiciona esse objeto Curso na coleção de cursos 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 da coleçã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
  • 81. _____________________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 persistente Departamento de identificador 1 na base de dados, adiciona o departamento à coleção de departamentos do objeto Curso e realiza a sua persistência. O SQL presente na Tabela 31 mostra que um SELECT foi feito na tabela DEPARTAMENTO, um INSERT na tabela CURSO e um outro INSERT na tabela DEPARTAMENTO_CURSO. Nesse caso, o relacionamento foi persistido, pois no mapeamento da coleção departamentos da classe Curso, como o atributo inverse nã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_ where departamen0_.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 curso e 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 de departamento, mas sim também pela data. Para essa situação, os mapeamentos dos relacionamentos <many-to-many> nas tabelas Curso e Departamento 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ária dupla. 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
  • 82. _____________________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 atributo DepartamentoCursoID 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 name informa 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 da chave composta dentro da classe DepartamentoCursoID. Para exemplificar o relacionamento n-n com atributos, observe o exemplo da Tabela 35. Primeiro um departamento 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 a chave composta. Os valores que compõem a chave, curso e departamento, são atribuídos. Finalmente, cria-se um 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
  • 83. _____________________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_ where curso1x0_.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, uma universidade 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 apresenta nenhuma 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
  • 84. _____________________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 ser inserido ou atualizado automaticamente quando o objeto Universidade for inserido ou atualizado. Nesse mapeamento aparece o atributo unique, que quando assume valor true implica em ter apenas uma universidade por endereço. A outra abordagem é ao invés de inserir o código da Tabela 39 no mapeamento de Universidade.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, o mapeamento do endereço em Endereco.hbm.xml deve ser feito como mostrado na Tabela 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
  • 85. _____________________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 da tag generator agora é foreign. A tag param de name igual a property permite a associação 1-1 da classe Endereco com a classe Universidade, o que acontece é que um parâmetro é passado para a classe geradora do identificador, 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 de Endereco (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ção entre a chave primária de Endereco e de Universidade, informando ao Hibernate que um endereço não pode existir 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 é feito através da tag set e possui o conjunto de atributos mostrado na Tabela 42. Esses atributos são semelhantes para 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
  • 86. _____________________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 o mapeamento de um Set de tipos primitivos considere o mapeamento de uma coleção de String’s para armazenar 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 esta tabela é separada da tabela ALUNO, mas para o Hibernate, ele cria a ilusão de uma única entidade. A tag key indica a chave estrangeira da entidade pai (ID_ALUNO). A tag element indica o tipo da coleção (String) e a coluna 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_TELEFONE consiste 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 inserido em sua coleção de String’s. Por fim, o objeto Aluno é persistido. O resultado é mostrado na Tabela 45, onde primeiro é inserida uma 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
  • 87. _____________________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 lista requer 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 da coleçã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 de dados 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 as colunas 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
  • 88. _____________________Curso Struts & Hibernate______________ 11.3 Map Maps associam chaves aos valores e não podem conter chaves duplicadas. Eles diferem de Sets no fato de 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 chave primária da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e CHAVE, também permitindo a presenç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 de dados; 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 Professor herdam 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
  • 89. _____________________Curso Struts & Hibernate______________ Figura 15 – Herança As Figuras Figura 16, Figura 17 e Figura 18 mostram as tabelas que devem ser criadas para as estratégias de mapeamento 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
  • 90. _____________________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 os conhecimentos 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. Neste caso, as sub-classes são mapeadas em tabelas diferentes, portanto uma associação polimórfica para a classe mãe não seria possível através de chave estrangeira. Outro problema conceitual é que várias colunas diferentes de tabelas distintas compartilham da mesma semântica, podendo tornar a evolução do esquema mais complexo, por exemplo, a mudança de um tipo de uma 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. O mapeamento 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
  • 91. _____________________Curso Struts & Hibernate______________ Essa coluna não é uma propriedade da classe persistente, mas apenas usada internamente pelo Hibernate. No caso, 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 na representação do polimorfismo. É importante saber que restrições ,"não nulas", não são permitidas para o mapeamento 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 o exemplo citado, essa estratégia de mapeamento pode ser vista na Tabela 50. Nessa estratégia as tabelas filhas contêm apenas colunas que não são herdadas e suas chaves primárias são também chaves estrangeiras para a tabela 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
  • 92. _____________________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 da classe mãe são persistidos em uma linha da tabela PESSOA e apenas os valores correspondentes à classe Aluno são persistidos em uma linha da tabela ALUNO. Em momentos posteriores essa instância de aluno persistida pode ser recuperada de um join entre a tabela 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 por sub-classe. A tag key declara as chaves primárias das sub-classes que são também chaves estrangeiras para a chave 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
  • 93. _____________________Curso Struts & Hibernate______________ 13. Transações Uma transação é uma unidade de execução indivisível (ou atômica). Isso significa dizer que todas as etapas pertencentes 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 entre contas 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 A 2º) 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ção 13.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, onde aparecem 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ções realizadas por algum container. Exemplos de ambientes gerenciados são componentes EJB (Enteprise JavaBeans) executando em servidores 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 por exemplo: 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
  • 94. _____________________Curso Struts & Hibernate______________ 13.2 Transações JDBC Uma transação JDBC é controlada pelo gerenciador de transações SGBD e geralmente é utilizada por ambientes não gerenciados. Utilizando um driver JDBC, o início de uma transação é feito implicitamente pelo mesmo. 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 o mé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. Se este atributo for definido como true, ou seja, se na conexão JDBC for invocado setAutoCommit(true), ativa-se o modo 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 a necessidade 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 de dados. Nessas situações, o uso apenas do JDBC pode não garantir a atomicidade. Dessa maneira, é necessário um 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 (Container Managed Transactions). Neste tipo de transação não há a necessidade de programação explícita das delimitaçõ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 ele deve 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 51 apresenta 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ão JDBC é iniciada. Já no caso de um ambiente gerenciado, uma nova transação JTA é criada, caso não exista nenhuma 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 base de dados. O Hibernate só realiza efetivamente o commit se o comando beginTransaction() iniciar uma nova transaçã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 a conexã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
  • 95. _____________________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. As mudanças nos objetos de domínio em memória feitas dentro do escopo de uma sessão (Session) não são imediatamente 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ções com 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, algumas vezes 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 todas as 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 a base 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étodo flush(). 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 que estejam 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 de uma transação. Eles impactam diretamente no nível de acesso concorrente a um mesmo alvo no banco de dados por transações diferentes. Geralmente, o isolamento de transações é feito usando locking, que significa que uma transação pode bloquear 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 de controle 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
  • 96. _____________________Curso Struts & Hibernate______________ Dentre alguns fenômenos que podem ocorrer devido à quebra de isolamento de uma transação estão três: Dirty Read (Leitura Suja): uma transação tem acesso a dados modificados por uma outra transação ainda não finalizada que ocorre concorrentemente. Isso pode causar problema, pois pode ocorrer um erro dentro da transaçã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 dados incorretos. Nonrepeatable Read (Leitura que não pode ser repetida): uma transação lê mais de uma vez um mesmo dado e constata que há valores distintos em cada leitura. Por exemplo, uma transação A lê uma linha do banco; uma transação B modifica essa mesma linha e é finalizada (commit) antes que a transação A; a transaçã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 de uma vez e retornar resultados diferentes. Isso pode ocorrer devido a uma outra transação realizar mudanças que afetem os dados consultados. Por exemplo, uma transação A lê todas as linhas que satisfazem uma condição WHERE; uma transação B insere uma nova linha que satisfaz a mesma condição antes da transação A ter sido finalizada; a transação A reavalia a condição WHERE e encontra uma linha “fantasma” na mesma consulta feita anteriormente. Existem quatro níveis de isolamento da transação em SQL. Eles se diferenciam de acordo com a ocorrência ou não dos fenômenos anteriormente descritos, como mostrado na Tabela 52. Tabela 52 - Níveis de Isolamento da Transação em SQL Obs. 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 dados relacionais, já que permite ler inconsistências e informações parciais (mudanças realizadas por uma transação ainda não finalizada podem ser lidas por outra transação). Se a primeira transação não for concluída, mudanças na 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ções quando 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 que a 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 que iniciou primeiro ser efetivada ou desfeita. Se as atualizações da primeira transação forem desfeitas, seus efeitos serão desconsiderados e a segunda 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 ou aplicará 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 uma transaçã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
  • 97. _____________________Curso Struts & Hibernate______________ Uma transação pode obter uma imagem completa da base de dados quando iniciada. Este nível é ideal para a geração de relatórios, pois em uma mesma transação, um registro é lido diversas vezes e seu valor se manté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. Ele permite uma execução serial das transações, como se todas as transações fossem executadas uma atrás da outra. Dessa forma, pode-se perder muita performance da aplicação, principalmente em ambientes multiusuários. 13.9 Configurando o nível de isolamento No 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 = 4 14. Concorrência Em algumas situações pode acontecer que duas ou mais transações que ocorrem paralelamente leiam e atualizem 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 de dados. Para exemplificar, a Tabela 54 apresenta um exemplo de duas transações concorrentes manipulando o mesmo dado x. No primeiro passo, ambas as transações lêem o dado x com o mesmo valor (2). Em seguida, T1 soma o valor 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 passa a 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, o valor calculado por T2, significando que as alterações feitas por T1 foram descartadas. Tabela 54 – Exemplo de Transação Concorrente 1) Transação 1 (T1) lê x = 2 2) Transação 2 (T2) lê x = 2 3) T1 faz x = x + 1 4) T2 faz x = x + 3 5) T1 armazena o valor de x na base de dados 6) 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
  • 98. _____________________Curso Struts & Hibernate______________ Pessimista: utilizar o controle pessimista significa que se uma transação T1 lê um dado e tem a intenção de atualizá-lo, esse dado será bloqueado (nenhuma outra transação poderá lê-lo) até que T1 o libere, ormalmente após a sua atualização. Otimista: utilizar o controle otimista significa que se T1 lê e altera um dado ele não será bloqueado durante o intervalo entre a leitura e atualização. Caso uma outra transação T2 tenha lido esse mesmo dado antes de T1 o atualizá-lo tente alterá-lo em seguida na base de dados, um erro de violação de concorrência deve ser gerado. 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, a primeira transação (Thread 1) atualiza este dado na base de dados e depois quem também o atualiza é a segunda transação (Thread 2). Nesta abordagem otimista, acontece que a atualização do dado feita pela segunda transação sobrescreve 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 conceito de Version Number, que é um padrão utilizado para versionar numericamente os dados de uma linha de uma tabela 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 de dados, 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 na base 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 a Versão 2. Por fim, a primeira transação vai também atualizar este mesmo dado. Dessa forma, também é feita uma 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
  • 99. _____________________Curso Struts & Hibernate______________ Assim, um erro é disparado e a atualização desejada pela primeira transação não é concretizada, evitando que a 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 no mapeamento das tabelas. Para exemplificar o seu uso, considera-se a classe ContaCorrente na Tabela 55 que será mapeada para a tabela CONTA_CORRENTE na base de dados. Dentre os diversos atributos da classe, está o atributo denominado versao que irá justamente guardar a versão atual das linhas da tabela. A tabela CONTA_CORRENTE também deve ter uma coluna para onde esse atributo 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), o atributo 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
  • 100. _____________________Curso Struts & Hibernate______________ tabela CONTA_CORRENTE. Com esse mapeamento, toda vez que uma determinada linha for atualizada na base de 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 da tabela. Neste caso, a classe ContaCorrente do exemplo anterior ao invés de ter um atributo inteiro para guardar a versão do dado, teria uma atributo do tipo java.util.Date para guardar o instante no tempo da última atualização. Neste caso, a classe de domínio seria equivalente à mostrada na Tabela 57 e seu mapeamento ao exibido na Tabela 58. Neste exemplo, a tabela CONTA_CORRENTE deve conter uma coluna do tipo timestamp denominada 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
  • 101. _____________________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 ser utilizada 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 se os 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 o atributo 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 a atualização seria o exibido na Tabela 60. Neste exemplo, considera-se a atualização do saldo para R$ 1.500,00 de uma determinada conta 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
  • 102. _____________________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 UPDATE para bloquear o dado até que o mesmo seja atualizado. O Hibernate fornece um conjunto de modos de lock (constantes disponíveis na classe LockMode) que podem ser utilizados para implementar o lock pessimista. Considerando o exemplo da Tabela 61, onde um determinado aluno é consultado na base de dados e tem seu nome atualizado. Neste caso, não há um bloqueio ao dado, então qualquer outra transação pode acessar este mesmo dado concorrentemente 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 passar a constante LockMode.UPGRADE como terceiro argumento do método get do objeto Session. Tabela 61 – Transação sem Lock Transaction 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.UPGRADE Transaction 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 lock pessimista 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 em memó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 lock pessimista do banco (se suportado). Lock.UPDGRADE_NOWAIT: Mesmo que UPGRADE, mas desabilita a espera por liberação de locks, e dispara 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 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 102 de 140
  • 103. _____________________Curso Struts & Hibernate______________ 15. Busca de Dados A busca de dados utilizando Hibernate pode se dar através do uso de HQL (Hibernate Query Languange), 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 consulta desejada, como, por exemplo, uma consulta hierárquica, pois Hibernate não suporta. Quando isto acontecer, a API JDBC pode ser utilizada diretamente. 15.2 Hibernate Query Language - HQL HQL é uma linguagem de consulta semelhante à OQL (Object Query Language), no entanto voltada para bancos de dados relacionais. Pertence a família do SQL, podendo ser facilmente compreendida através de algum conhecimento em SQL. HQL suporta polimorfismo, herança e associações, pode incluir na consulta, restrições nas propriedades da classe e associações, suporta ainda agregação, ordenação, paginação, subconsultas, outer joins, chamadas de funções SQL e projeção, que permite buscar apenas os dados necessários, não sendo necessário carregar todo 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 de manipulação de dados (DML). Uma simples consulta usando HQL pode ser realizada através da cláusula from, mostrada na Tabela 63, onde temos a consulta à lista de todos os alunos, se desejar usar Aluno em outra parte da consulta basta criar 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 para agrupar 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 HQL na Tabela 64. Tabela 64 - Expressões HQL from Aluno aluno where aluno.matricula >= 35 from 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 por exemplo as tabelas Curso e Aluno. Para exemplificar os casos de joins, serão utilizados os dados abaixo das tabelas 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
  • 104. _____________________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 Join from Curso c inner join Aluno a on c.id = a.curso.id Ou: from Curso c join Aluno a on c.id = a.curso.id Resultado (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 join from Curso c left outer join Aluno a on c.id = a.curso.id Ou: from Curso c left join Aluno a on c.id = a.curso.id Resultado (omitido matricula 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 3 CURSO 3 As consultas HQL normalmente não explicitam os joins. As associações já são informadas no mapeamento das classes Java, o Hibernate com a informação no documento do mapeamento deduz os joins necessários nas tabelas. Isto facilita as escritas das consultas. Existem quatro maneiras de realizar os joins, são: Join ordinários (no from), Fetch Joins (usado para coleções), Estilos Theta (entre classes não associadas) e Joins implí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
  • 105. _____________________Curso Struts & Hibernate______________ Para enviar uma consulta HQL para o banco de dados, uma interface chamada Query é utilizada para representar a consulta. A Tabela 69 apresenta um objeto Query sendo instanciado para fazer consultas da tabela ALUNO. O comando q.list() faz com que todos os alunos cadastrados sejam retornados, já que a HQL utilizada foi “from Aluno”. Tabela 69 - Obtendo o resultado de uma consulta ao banco usando Query Query q = session.createQuery("from Aluno"); q.list(); A Tabela 70 apresenta em exemplo de consulta que retorna todos os cursos que possuem nomes começados pela letra A. Já a consulta da Tabela 71 retorna todos os cursos que possui departamento com identificador igual a 2. Tabela 70 - Exemplo com Query String hql = "from Curso c where c.nome like ‘A%’"; Query q = session.createQuery(hql); q.list(); Tabela 71 - Exemplo com Query String 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 apenas alguns dados da classe mapeada. A Tabela 73 apresenta um exemplo dessa consulta. Tabela 73 - Exemplo Consulta de Projeção String 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
  • 106. _____________________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 mesmo por 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 By select count(*) from Aluno select min(a.matricula), max(a.matricula) from Aluno a select 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 que esses parâmetros recebam nomes. Por exemplo, no exemplo da Tabela 75, deseja-se saber todos os alunos que possuem determinado nome. 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 seu valor. Tabela 75 - Exemplo Query: Nomeação de Parâmetros Query 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 de execução. Esta abordagem permite definir restrições dinamicamente sem que haja manipulação de Strings, a sua flexibilidade 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ção de 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
  • 107. _____________________Curso Struts & Hibernate______________ Tabela 76 - Obtendo um Criteria Criteria 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ções Criteria 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 Like Criteria 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ários níveis de subcriterias. Veja um exemplo na Tabela 79. Tabela 79 – Sub-Criteria Criteria 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 com alguns valores das propriedades setados, retornando todos os objetos persistentes que possuam os valores das propriedades. Veja exemplo na Tabela 80. Tabela 80 – Query By Example Aluno 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 ser realizada 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 Query Query 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
  • 108. _____________________Curso Struts & Hibernate______________ q.setMaxResults(30); q.list(); Tabela 82 - Paginação Criteria Criteria 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
  • 109. _____________________Curso Struts & Hibernate______________ 16. Hibernate com Anotações e JPA 16.1 Introdução Recentemente, o mapeamento objeto relacional utilizando Hibernate passou a ser feito também a partir de anotações, de forma que se tornou mais simples, possibilitando uma maior produtividade no desenvolvimento de aplicações. Sobre a JPA Posteriormente devido ao grande sucesso obtido pelo Hibernate, o mesmo foi adotado como base para a especificação JPA (Java Persistence API, vide http://www.jcp.org/en/jsr/detail?id=317), especificação esta que se 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 qual será 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 pelo compilador. Qualquer símbolo em um código Java que comece com uma @ (arroba) é uma anotação. Este recurso foi introduzido na linguagem Java a partir da versão Java SE 5.0. Em outras palavras, as anotações marcam 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 em um método qualquer (metodoTeste), respectivamente. O exemplo é meramente ilustrativo, de forma que o tipo de anotação definido não agrega nenhum significado especial ao código fonte. @TesteAnotacao public void metodoTeste{ ... } Listagem 1 – Exemplo ilustrativo para o uso de um tipo de anotação Inicialmente, o mapeamento objeto relacional com Hibernate era feito a partir de um conjunto de configurações em arquivos XMLs. Com o surgimento das anotações no Java SE 5.0, o framework Hibernate anexou este recurso, permitindo que as classes Java fossem mapeadas a partir de anotações, simplificando o seu uso. A próxima seção apresentará um exemplo simples do uso da persistência de uma classe com Hibernate Annotations. Ativando o JPA no seu projeto Hibernate Para que o Hibernate com anotações e JPA seja ativado, devem ser copiados as seguintes bibliotecas para o seu classpath: ejb3-persistence.jar hibernate-annotations.jar lucene-core-2.0.0.jar Para que tudo funcione será necessário instanciar um objeto do tipo org.hibernate.cfg.AnnotationConfiguration ao invés de um org.hibernate.cfg.Configuration, ou utilizar as API´s específicas da JPA: javax.persistence.PersistenceManager e javax.persistence.EntityManagerFactory, que substituem respecitivamente as classes Session e SessionFactory. 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
  • 110. _____________________Curso Struts & Hibernate______________ 16.2 Exemplo Simples com Anotações Inicialmente, para que o Hibernate soubesse como carregar e armazenar objetos de classes persistentes, eram utilizados apenas arquivos de mapeamento XML. Dessa forma, era possível informar que tabela do banco de dados se refere uma dada classe persistente e quais colunas na tabela são referentes a quais atributos da classe. Com o surgimento das anotações no Java 5.0, tornou-se possível substituir os arquivos XML para o mapeamento objeto relacional. Através do uso de um conjunto de anotações no código fonte das classes mapeadas. 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 banco de dados a representa e quais atributos correspondem as quais colunas desta tabela. Figura 1 - Classe Aluno A 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: Aluno Todas 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 na anotaçã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 a tabela 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
  • 111. _____________________Curso Struts & Hibernate______________ @Table. No caso, a linha do código fonte @Table(name="aluno", schema="anotacoes") está informando o 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ária pode ser dado tanto pela aplicação quanto por um mecanismo do Hibernate que o gere automaticamente. A anotação @GeneratedValue permite a definição automática para o valor do identificador, utilizando um dos mecanismos de geração apresentados anteriormente. Neste caso, utilizou-se a estratégia a partir de uma seqüê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 chave primária o próximo valor disponível por uma seqüência padrão chamada hibernate_sequence. Deve-se salientar que o programador deverá criar uma seqüência com este nome na base de dados. Ainda em relação ao identificador, como o nome da coluna mapeada é diferente do nome do atributo, é necessário utilizar a anotação @Column informando o nome da coluna, através do atributo name. Neste exemplo, o nome da coluna 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 feito quando o nome do atributo é igual ao nome da coluna da tabela mapeada, de forma que não há a necessidade de 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
  • 112. _____________________Curso Struts & Hibernate______________ Depois de criar todas as classes persistentes com seus respectivos mapeamentos com anotacoes, deve-se realizar 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.xml 16.3 Outro Exemplo com Anotações JPA A classe Cliente, ilustrada pela Listagem 2, possui exemplos de mapeamentos de atributos a partir das anotações: @Column, @Transient, @Temporal. As anotações @Id e @GeneratedValue também são utilizadas 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
  • 113. _____________________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ções A 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
  • 114. _____________________Curso Struts & Hibernate______________ 16.4 Definição de Chave Primária Utilizando uma Seqüência Pró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
  • 115. _____________________Curso Struts & Hibernate______________ 16.4 Mapeando relacionamento entre classes O 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 entidade Universidade da Figura 1. O relacionamento diz que uma universidade possui um conjunto de n centros e um centro está associado a apenas uma única universidade. Considere as classes de domínio Java de uma universidade 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 Universidade package 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
  • 116. _____________________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: Centro A classe de domínio Universidade é a que possui um mapeamento do tipo 1-n através do atributo coleção de centros. O seu mapeamento foi feito na Listagem 1 a partir da anotação @OneToMany. Como a coleção conterá objetos do tipo Centro, então está classe também deverá ser uma classe persistente da aplicação. Na anotação @OneToMany, existe um atributo denominado mappedBy que deverá receber como valor o nome do 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 tabela universidade, 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 ao atributo 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ção em cascata o relacionamento será tratado, ou seja, especifica quais operações deverão ser em cascata do objeto 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
  • 117. _____________________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 e Universidade, mostrado também na Figura 1. Neste caso, o relacionamento está presente no mapeamento da classe Centro, como mostrado na Listagem 2, a través da anotação @ManyToOne. Para facilitar o entendimento, o trecho de mapeamento many-to-one do atributo universidade da classe Centro pode ser visto 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 ManyToOne A anotação @ManyToOne também possui o atributo fetch, que possui o mesmo comportamento apresentado anteriormente. 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ão aceitá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 é inserido ou atualizado, respectivamente. O atributo do relacionamento não será inserido se insertable = false e não será atualizado se updatable = false. 16.4.3 Demais Associações As 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 detalhes sobre anotações JPA veja: http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html Anotaçõ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 @DiscriminatorValue Tabela 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
  • 118. _____________________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
  • 119. _____________________Curso Struts & Hibernate______________ Exercício 1 – Welcome 1- 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
  • 120. _____________________Curso Struts & Hibernate______________ Exercício 2 - Registro de usuários 1- 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 arquivo register.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: registerForm type: app.RegisterForm 8- Abrir o struts-config.xml, criar um Action Mapping; Path: /register Type: app.RegisterAction Form Bean: registerForm input: /register.jsp forwards: Name:success Path: /success.html Name: failure Path: /failure.html 9- 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, chamada registerForm; 12- Utilizando a variável registerForm criada, testar (if) se o atributo password1 igual a password2 , se sim , 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
  • 121. _____________________Curso Struts & Hibernate______________ 13 – Criar um Global Forward: Name: index Path: /register.jsp 14- Na página /index.jsp , redirecionar para o forward index 15- 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
  • 122. _____________________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
  • 123. _____________________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
  • 124. _____________________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
  • 125. _____________________Curso Struts & Hibernate______________ Exercício 4 – Criação da tela de dados pessoais 1- 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
  • 126. _____________________Curso Struts & Hibernate______________ 2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace do Eclipse; 3- No Windows, menu iniciar, opção Configurações/Painel de Controle/Ferramentas Administrativas/Fontes de Dados ODBC/Fontes de dados do sistema, cadastrar uma fonte de dados Access, com o nome “cadastro”, apontando para o arquivo cadastro.mdb contido no diretório data do seu projeto cadastro; 4- Modificar o Action Mapping /cadastro: type: app.CadastroAction forward name: sucesso path: /pages/pessoa.jsp 5- 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.CadastroForm 8 – 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.do 9- 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.jsp 11 – 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
  • 127. _____________________Curso Struts & Hibernate______________ 13- Teste o botão continuar no formulário de cadastro, e verifique se a tabela pessoa do arquivo cadastro.mdb recebeu um novo registro com os dados digitados anteriormente; 14- Na classe app.CadastroForm, descomente o metodo public ActionErrors validate, e complete os TODO; 15 – De volta ao formulário de cadastro, entre com valores inválidos e verifique se o Struts irá validar a sua 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
  • 128. _____________________Curso Struts & Hibernate______________ Exercício 5 – Criação da tela de formação 1- 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; 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
  • 129. _____________________Curso Struts & Hibernate______________ 3- Modificar o Action Mapping /formacao: type: app.FormacaoAction forward: sucesso path: /pages/formacao.jsp 4- Completar os TODO da classe app.FormacaoAction 5- Cadastrar um Action Form: name: formacaoform type: DynaActionForm id Long idPessoa Long idNivelEscolaridade Integer instituicao String anoInicio Integer anoConclusao Integer method String 6- 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.do 7- Criar um atributo chamado formacoes, do tipo java.util.Collections na clase app.CadastroForm. Gerar gettter e setter, 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.SubmitFormacaoAction 10- 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
  • 130. _____________________Curso Struts & Hibernate______________ 11- Completar os TODO na página /pages/erro.jsp 12- Teste as funcionalidades da tela de formação, e verifique se as informações constam na tabela formação no banco de dados. Exercício 6 – Criação da tela de experiências 1- 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
  • 131. _____________________Curso Struts & Hibernate______________ 2- Copiar o novo diretório “cadastro” fornecido pelo professor, para o seu diretório de workspace do Eclipse; 3- Modificar no Action Mapping /submitformacao: name: continuar path: /experiencia.do 4- Criar um Action Mapping name: /experiencia type: app.ExperienciaAction forward: name: sucesso path: /pages/experiencia.jsp 5- Criar um Form name: experienciaform type: DynaActionForm atributos: id Long empresa String dataInicioDisplay String dataTerminoDisplay String atribuicoes String idPessoa Long method String 6- 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 ExperienciaAction 8- 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
  • 132. _____________________Curso Struts & Hibernate______________ name: adicionar path: /experiencia.do name: voltar path: /formacao.do 9- Completar os TODO da pagina /pages/experiencia.jsp. Após concluir este passo, teste o botão de continuar no /formacao.do no browser. Deverá aparecer a tela de entrada de dados de experiência profissional. 10- Completar os TODO da classe app.SubmitExperienciaAction 12- Testar as funcionalidades da tela de experiência profissional, e verifique se as informações constam na 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
  • 133. _____________________Curso Struts & Hibernate______________ Exercício 7 – Listagem de Currículos Cadastrados 1- 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. 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
  • 134. _____________________Curso Struts & Hibernate______________ 3- Abrir o arquivo para_inserir_em_struts-config.xml.txt, e inserir o conteúdo do mesmo no arquivo 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 globalizada 1- 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 String 4- Completar os TODO em app.LocaleAction 5- Completar os TODO em menu.jsp 6- 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
  • 135. _____________________Curso Struts & Hibernate______________ validate: false scope: request forward: 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
  • 136. _____________________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
  • 137. _____________________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 complexo devido 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: 2015 2- 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 arquivo formacao.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
  • 138. _____________________Curso Struts & Hibernate______________ 2.3 – Para dar um “bypass” na validação de um formulário vazio, modifique nos atributos onclick a bCancel 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 para DynaValidatorForm. 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 no método SubmitFormacaoAction.adicionar, com o método form.validate(mapping,request). Testar os botõ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: 1000 8- 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
  • 139. _____________________Curso Struts & Hibernate______________ 8.2 - Declare uma tag <html:javascript formName=”experienciaform” /> no final do arquivo experiencia.jsp 8.3 – Para dar um “bypass” na validação de um formulário vazio, modifique nos atributos onclick a bCancel 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 no método SubmitExperienciaAction.adicionar, com o método form.validate(mapping,request). Testar os botõ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 Tiles 1- 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 definir o raiz de sua aplicacao web como /web 3- Resolver os TODOS contidos no arquivo tiles-defs.xml 4- 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
  • 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 "*" , exemplo onde 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