140
Versão 2.0 – Março - 2009 Revisada por Mauro de Souza Guimarães

Curso struts e hibernate

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Curso struts e hibernate

Versão 2.0 – Março - 2009

Revisada por Mauro de Souza Guimarães

Page 2: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 2 de 140

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

Page 3: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 3 de 140

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.

Page 4: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 4 de 140

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.

Page 5: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 5 de 140

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

Page 6: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 6 de 140

4. O mecanismo do M-V-C em uma aplicação Web, com o STRUTS. Veja o diagrama abaixo: Na figura acima, estão representadas as 3 camadas: Model – View – Controller.

3

Jakarta Struts Framework – Modelo MVC

Page 7: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 7 de 140

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:

Page 8: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 8 de 140

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:

Page 9: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 9 de 140

5. Nós iremos utilizar o padrão de diretórios que o Eclipse utiliza, isto é, sugerindo a instalação em “C:\eclipse\workspace”, 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:

Page 10: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 10 de 140

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

"eclipse\plugins" 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.

Page 11: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 11 de 140

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:

Page 12: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 12 de 140

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:

Page 13: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 13 de 140

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:

Page 14: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 14 de 140

Page 15: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 15 de 140

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

Page 16: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 16 de 140

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)

Page 17: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 17 de 140

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:

Se a senha for digitada de forma errada, esta outra mensagem aparece:

� O que ocorreu entre o aparecimento da página do formulário e a página com uma das mensagens?

Struts User Registration

Username:

Password:

Confirm:

ok

Registration Succeeded!

Try Another?

Registration failed!

Try Again?

Page 18: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 18 de 140

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;

}

}

Page 19: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 19 de 140

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");

}

} }

Page 20: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 20 de 140

12. Parte do arquivo struts-config.xml, com as tags <action-mappings> e <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.

<!-- 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>

Page 21: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 21 de 140

<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">

Page 22: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 22 de 140

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

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

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>register.jsp</welcome-file> </welcome-file-list>

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

Page 23: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 23 de 140

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>

Page 24: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 24 de 140

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

<init-param>

<param-name>application</param-name>

<param-value>resources.MessageResources</param-value> </init-param>

Page 25: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 25 de 140

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:

Page 26: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 26 de 140

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

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

Page 27: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 27 de 140

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

Page 28: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 28 de 140

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!

Page 29: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 29 de 140

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

Page 30: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 30 de 140

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:

Page 31: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 31 de 140

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.

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");

}

}

Page 32: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 32 de 140

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 {

Page 33: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 33 de 140

O arquivo de configuração Struts poderia criar uma entrada como esta: <action. path="/registrarDados" type="app.gravacaoDispatchAction" name="dataForm" scope="request" 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:

o parâmetro "parameter" indica qual método será chamado na classe DispatchAction

Page 34: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 34 de 140

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

Page 35: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 35 de 140

• 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

Page 36: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 36 de 140

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

lessEqual Executa o conteúdo da tag se a variável testada for igual ou menor do que o valor especificado.

lessThan Executa o conteúdo da tag se a variável testada for menor do que o valor especificado.

match Executa o conteúdo da tag desde de que a string informada contenha o trecho procurado. (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.

Page 37: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 37 de 140

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.

Page 38: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 38 de 140

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>

Page 39: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 39 de 140

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:

Page 40: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 40 de 140

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

Page 41: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 41 de 140

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>

Page 42: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 42 de 140

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>

Page 43: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 43 de 140

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.

Page 44: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 44 de 140

•Exemplo de validação no validation-rules.xml 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.

O atributo depends determina que o validador somente será executado após todos os outros validadores listados como dependentes.

Define o identificador da mensagem exibida se a validação gerar um erro; a mensagem deve ser especificada em um dos arquivos de recursos do Struts.

No exemplo, "intRange" é definido pelo método validateIntRange da classe org.apache.struts.validator.FieldChecks.

Este elemento <javascript>, dentro do arquivo de configuração do validator, serve para indicar quais validações no lado CLIENTE deverão ser feitas.

Page 45: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 45 de 140

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:

Page 46: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 46 de 140

•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>

37

Jakarta Struts Framework – Fluxo da Solicitação

web browser

Page 47: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 47 de 140

38

Jakarta Struts Framework – Sequência

Page 48: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 48 de 140

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

Page 49: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 49 de 140

Page 50: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 50 de 140

Í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

Page 51: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 51 de 140

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

Page 52: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 52 de 140

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.

Page 53: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 53 de 140

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.

Page 54: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 54 de 140

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.

Page 55: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 55 de 140

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.

Page 56: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 56 de 140

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;

Page 57: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 57 de 140

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.

Page 58: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 58 de 140

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.

Page 59: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 59 de 140

�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).

Page 60: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 60 de 140

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;

}

}

Page 61: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 61 de 140

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.

Page 62: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 62 de 140

Tabela 2 – Mecanismos de Geração de Chaves Primárias

Mecanismo Descrição

identity Mapeado para colunas identity no DB2, MySQL, MSSQL, Sybase, HSQLDM, Informix.

sequence Mapeado em sequências no DB2, PostgreSQL, Oracle, SAP DB, Firebird (ou generator no Interbase).

increment

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

hilo Usa algoritmo high/low para geração de chaves únicas.

uudi.hex Usa uma combinação do IP com um timestamp para gerar u m identificador único na rede.

assigned Utiliza o valor atribuído com set à propriedade do objeto associada ao 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.

Page 63: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 63 de 140

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

Page 64: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 64 de 140

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.

Page 65: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 65 de 140

Page 66: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 66 de 140

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

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;

}

}

Page 67: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 67 de 140

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.

Page 68: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 68 de 140

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;

Page 69: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 69 de 140

� 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:

Page 70: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 70 de 140

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

Page 71: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 71 de 140

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

Page 72: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 72 de 140

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();

...

Page 73: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 73 de 140

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

Page 74: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 74 de 140

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.

Page 75: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 75 de 140

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.

Page 76: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 76 de 140

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.

Page 77: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 77 de 140

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.

Page 78: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 78 de 140

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

}

Page 79: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 79 de 140

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"/>

Page 80: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 80 de 140

</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=?

Page 81: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 81 de 140

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

Page 82: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 82 de 140

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.

Page 83: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 83 de 140

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"/>

Page 84: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 84 de 140

<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"/>

Page 85: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 85 de 140

<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();

Page 86: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 86 de 140

� 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);

Page 87: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 87 de 140

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.

Page 88: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 88 de 140

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.

Page 89: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 89 de 140

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

Page 90: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 90 de 140

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

Page 91: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 91 de 140

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.

Page 92: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 92 de 140

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.

Page 93: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 93 de 140

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

Page 94: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 94 de 140

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 {

Page 95: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 95 de 140

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

Page 96: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 96 de 140

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.

Page 97: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 97 de 140

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:

Page 98: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 98 de 140

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

Page 99: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 99 de 140

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

Page 100: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 100 de 140

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

Page 101: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 101 de 140

<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

Page 102: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 102 de 140

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.

Page 103: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 103 de 140

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.

Page 104: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 104 de 140

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 ‘.’.

Page 105: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 105 de 140

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();

Page 106: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 106 de 140

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.

Page 107: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 107 de 140

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

Page 108: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 108 de 140

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();

Page 109: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 109 de 140

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 Listagem 1 Listagem 1 Listagem 1 –––– Exemplo ilustrativo para o uso de um tipo de anotação Exemplo ilustrativo para o uso de um tipo de anotação Exemplo ilustrativo para o uso de um tipo de anotação 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.

Page 110: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 110 de 140

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

Page 111: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 111 de 140

@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

Page 112: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 112 de 140

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

Page 113: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 113 de 140

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

Page 114: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 114 de 140

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

Page 115: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 115 de 140

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

Page 116: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 116 de 140

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.

Page 117: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 117 de 140

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 @Embeddable

Efetua um mapeamento com chave composta

@Inheritance(strategy=InheritanceType) @DiscriminatorColumn @DiscriminatorValue

Efetua um mapeamento com herança

Tabela 1.6.4.3 – Demais associações utilizadas com anotações JPA.

Page 118: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 118 de 140

APÊNDICE “A” CADERNO DE EXERCÍCIOS

Page 119: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 119 de 140

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;

Page 120: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 120 de 140

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_hibernate\register\web) para a pasta web do projeto; 4- Colocar o arquivo WEB-INF\lib\struts.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").

Page 121: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 121 de 140

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.

Page 122: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 122 de 140

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:

Page 123: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 123 de 140

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

Page 124: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 124 de 140

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

Page 125: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 125 de 140

Exercício 4 – Criação da tela de dados pessoais 1- Analisar o diagrama de comunicação abaixo:

Page 126: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 126 de 140

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;

Page 127: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 127 de 140

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.

Page 128: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 128 de 140

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;

Page 129: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 129 de 140

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

Page 130: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 130 de 140

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:

Page 131: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 131 de 140

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

Page 132: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 132 de 140

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.

Page 133: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 133 de 140

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.

Page 134: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 134 de 140

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

Page 135: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 135 de 140

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!!

Page 136: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 136 de 140

Page 137: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 137 de 140

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

Page 138: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 138 de 140

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.

Page 139: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 139 de 140

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 \web\pages\layout

Page 140: Curso struts e hibernate

_____________________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: [email protected]

site: www.ensina.com.br email: [email protected]

Página 140 de 140

5- Retirar todo o conteudo antes (inclusive) de <jsp:include page="/menuinclude.do" /> e depois (inclusive) de </body> das paginas jsp contidas no diretorio \web\pages, 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