quarta-feira, 4 de setembro de 2013

Struts

  7.3 Struts  

   

 Front Controller: A classe ActionServlet atua como o Front Controller do Struts. Ele deve ser configurado no arquivo web.xml.  

 Web.xml  

 <servlet>  

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

   <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>  

 </servlet>  

 <init-param>  

    <param-name>config</param-name>  

    <param-value>/WEB-INF/struts-config.xml</param-value>  

 </init-param>  

 <servlet-mapping>  

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

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

 </servlet-mapping>  

 <taglib>  

   <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>  

   <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>  

 </taglib>  

   

 Action Form: Logo após o recebimento da requisição o ActionServlet delega ao RequestProcessor a responsabilidade de extrair os parâmetros da requisição e popular um ActionForm.  

 •    Os ActionForms são responsáveis por validar se os atributos da requisição são sintaticamente corretos e eventualmente disparar exceções avisando o usuário final.  

 •    O desenvolvedor deve especializar um ActionForm e sobrescrever os métodos reset e validade.  

 •    Além disso, a sua classe de ActionForm deve conter os atributos que correspondem aos campos do form html.  

   

 package br.com.softech;  

 import org.apache.struts.action.*;  

 public class FuncionarioForm extends ActionForm {  

     private String nome;  

     private Integer idade;  

     //Setters and getters;  

     public void reset( ActionMapping mapping, HttpServletRequest req ) {  

         this.nome = null;  

         this.idade = null;  

     }  

     public ActionErrors validate( ActionMapping mapping, HttpServletRequest req ) {  

         ActionErrors errors = new ActionErrors( );  

         if( nome == null || idade == null ) {  

             errors.add( “errNomeIdade”, new ActionError(“nomeIdade.required”) );  

         }  

         return errors;  

 }}  

 No struct-config  

     <struts-config>  

     <form-beans>  

         <form-bean name="funcionarioForm" type="br.com.softech.FuncionarioForm“ />  

     </form-beans>  

     </struts-config>  

   

 Action: Após criar e validar os parâmetros via ActionForm o RequestProcessor acessa o método execute do objeto  

 Action relacionado a requisição (Command Pattern).  

 •    As Actions são responsáveis por ativar os objetos de negócio, tratar eventuais exceções e redirecionar dados e  

 conteúdo para a próxima página.  

 •    O desenvolvedor deve especializar a classe Action e sobrescrever o método execute.  

 •    As classes Action são reutilizadas por todas as requisições, deste modo tais classes devem ser threadsafe.  

   

     public class NovoFuncAction extends Action {  

         public ActionForward execute(ActionMapping mapping, ActionForm form,  

             HttpServletRequest request,    HttpServletResponse response)  

         throws IOException, ServletException {  

             //Acessando ActionForm  

             FuncionarioForm funcForm = (FuncionarioForm) form;  

             String nome = funcForm.getNome( );  

             Integer idade = funcForm.getIdade( );  

             //Lógica do Negócio para cadastrar um novo funcionário  

             //....  

             //Redirecionamento  

             return mapping.findForward("sucesso");  

         }}  

   

 O mapeamento entre as requisições e as ações (Action) é feito de forma declarativa no arquivo struts-config.xml.  

 <action-mappings>  

     <action path="/listaFunc" type=“br.com.softech.ListaFuncAction“ input="/listaFunc.jsp“ />  

     <action path="/novoFunc" type=“br.com.softech.NovoFuncAction"  

         name=“funcionarioForm" scope="request" input="/novoFunc.jsp">  

         <forward name="sucesso" path="/listaFunc.do" redirect="true“ />  

     </action>  

 </action-mappings>  

   

 ActionForward: A classe ActionFoward é responsável pelo mapeamento lógico das páginas do sistemas, evitando assim, o uso do nome físico (URI) dento do código.  

 •    O uso eficiente do ActionFoward facilita a manutenção do sistema.  

 •    ActionFowards são declaradas dentro do strutsconfig.xml em dois níveis (Global e Action), sendo que as  

 declaradas dentro das ações tem maior precedência.  

     <global-forwards>  

         <forward name="error" path="/error.jsp"/>  

     </global-forwards>  

     <action-mappings>  

         <action path="/login" type=“acme.actions.LoginCheckAciton"  

             name="LoginForm" scope="request" input="/login.jsp">  

             <forward name="success" path="/main.jsp" redirect="true"/>  

         </action>  

     </action-mappings>  

   

 ActionError e ActionMessages: Responsáveis pelo armazenamento de informações sobre mensagens de erro, anomalias do sistema (ActionError) e avisos (ActionMessage).  

 •    Geralmente é utilizada dentro de ActionForm’s (erros de sintaxe) e Action’s (erros de sistema).  

 •    Possuem grande integração com os serviços de internacionalização e tag libraries  

   

     public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {  

         ActionErrors errors = new ActionErrors();  

         if ((this.nome == null) || (this.nome.lenght()<1)) {  

             errors.add(“nome”, new ActionError(“nome.required”));  

         }  

         return errors;  

     }  

   

   

 Internacionalização:  

 •    O Struts oferece suporte a internacionalização através da classe MessageResources.  

 •    A classe MessageResources é populada em tempo de execução pelo RequestProcessor de acordo com as informações registradas no struts-config e a língua/região utilizada pelo usuário final.  

 •    Largamente utilizadas pelos ActionErrors e tag libraries do Struts.  

 •    A implementação padrão usa arquivos .properties, mas especializações podem ser adicionadas para atender outros cenários.  

 •    Configurando a I18N no arquivo struts-config.xml:  

         <message-resources parameter=“ApplicationResources"/>  

 •    Configuração do arquivo ApplicationResources.properties:  

         nomeIdade.required=Nome e Idade são requeridos.  

         label.nome=Nome  

         label.idade=Idade  

 •    Acessando as mensagens do JSP:  

         <bean:message key=“label.nome” />  

 •    Acessando as mensagens do Action:  

         msg = getResources( request ).getMessage( "nomeIdade.requerido“ );  

 Exceptions Handling:  

 •    Mecanismo adicionado na versão 1.1.  

 •    Tem por finalidade implementar o tratamento de exceções de forma declarativa.  

 •    Utiliza a classe ExceptionHandler para interceptar as exceções e redirecioná-las para as suas páginas de erro ou respectivas ações de controle.  

 •    Impedem que o usuário veja exceções de sistema não tratadas:  

 ◦     NullPointerException, Internal Error  

 •    Podem ser globais ou relativas a uma ação (Action).  

 •    Configuração no struts-config.xml  

     <global-exceptions>  

     <exception type=“br.com.softech.MinhaException"    path="/error.jsp“ key=“exception.minha.exception" scope="request"/>  

     </global-exceptions>  

   

 Passos:  

     1 – HTTP request  

     2 – acesso ao struts-config.xml. Lido pelo ActionServlet na inicializaão da aplicação. Nesse arquivo são definidos os Actions.  

     3 – Lê as informações do ActionForm. Passa os filtos  

     4 – Retorna as informações do ActionForm para o ActinServlet.  

     5 – O ActionServlet poassa as informações para o Action, implementado pelo desenvolvedor.  

     6-7- Regras de negócio.  

     8 – Volta ao ActionServlet.  

     9 – Faz o foward para o JSP ou HTML através do ActionForward.  

     10 – HTTP response  

 Os detalhes são definidos no ActionMapping  

   

   

   

 @Action(value="adicionaTarefa", results = {  

 @Result(name="ok", location="/tarefa-adicionada.jsp")  

 @Result(name="ok", type="redirectAction", params= {"actionName", "listaTarefas"})  

   

 <interceptors>  

 <interceptor name="autorizador"  

 class="br.com.caelum.tarefas.interceptor.AutorizadorInterceptor"></interceptor>  

 </interceptors>  

   

   

 Struts-config.xlm  

 <struts-config>  

 <form-beans>  

 <form-bean name="userFormBean" type="coreservlets.UserFormBean"/>  

 </form-beans>  

 <action-mappings>  

 <action path="/actions/register4" type="coreservlets.RegisterAction3"  

 name="userFormBean" scope="request">  

 <forward name="bad-address" path="/WEB-INF/results/bad-address4.jsp"/>  

 <forward name="bad-password" path="/WEB-INF/results/bad-password4.jsp"/>  

 <forward name="success" path="/WEB-INF/results/result4.jsp"/>  

 </action>  

 </action-mappings>  

 <message-resources parameter="resources.application" null="false"/>  

 </struts-config>  

 ´  

  7.3.1 DispatchAction functionality  

 package vaannila;  

 import com.opensymphony.xwork2.ActionSupport;  

 public class UserAction extends ActionSupport{  

   private String message;  

   public String execute()  {  

     message = "Inside execute method";    return SUCCESS;  }  

   public String add()  {  

     message = "Inside add method";    return SUCCESS;  }  

   public String getMessage() {   return message;  }  

   public void setMessage(String message) { this.message = message;  }  

 }  

   

 <struts>  

   <package name="default" extends="struts-default">  

     <action name="User" class="vaannila.UserAction">  

       <result name="success">/success.jsp</result>  

     </action>  

     <action name="addUser" method="add" class="vaannila.UserAction">  

       <result name="success">/success.jsp</result>  

     </action>  

   </package>  

 </struts>  

   

 <%@taglib uri="/struts-tags" prefix="s" %>  

 <html><head>  

 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  

 <title>Insert title here</title>  

 </head>  

 <body>  

 <s:form action="User" >  

   <s:submit />  

   <s:submit action="addUser" value="Add" />  

 </s:form>  

 </body></html>  

   

 Se o “User” for clicado no request, o método execute() na classe UserAction é chamado. Se o requet for “addUser”, o método add() será chamado .  

   

  7.3.2 Validação  

 http://viralpatel.net/blogs/2009/12/struts2-validation-framework-tutorial-example.html  

   

 Validator.xml: Quais rotinas de validação são incluídas e como elas devem ser aplicadas.  

 Validator-rules.xml. Validações no lado do cliente, podem enviar JavaScript.  

 Tipos:  

 Field Validators: Age sobre campos simples acessível pela action.  

 <validators>  

  <field name="bar">  

    <field-validator type="required">  

      <message>You must enter a value for bar.</message>  

    </field-validator>  

  </field>  

 </validators>  

   

 Non-field validators: Específico para o domínio. Um exemplo é o ExpressionValidator.  

 <validators>  

    <validator type="expression">  

       <param name="expression">foo lt bar</param>  

    </validator>  

 </validators>  

   

 Criar a Action  

 public class CustomerAction extends ActionSupport{  

   private String name;  

   public String addCustomer() {    return SUCCESS;    }  

   public String getName() {        return name;    }      

 }  

 No struts.xml:  

 <action name="customer"    ---- Associa essa action ao nome “customer”  

   class="net.viralpatel.struts2.CustomerAction">  

   <result name="success">SuccessCustomer.jsp</result>  

   <result name="input">Customer.jsp</result>  

 </action>  

 No Customer.jsp:  

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <html>    <head>        <title>Customer Form - Struts2 Demo | ViralPatel.net</title>    </head>  

 <body>        <h2>Customer Form</h2>  

     <s:form action="customer.action" method="post">  

       <s:textfield name="name" key="name" size="20" />  

       <s:submit method="addCustomer" key="label.add.customer" align="center" />  

     </s:form>  

 </body>    </html>  

 No SuccessCustomer.jsp  

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <html>        <head>        <title>Customer Page - Struts2 Demo | ViralPatel.net</title>    </head>  

 <body>  <h2>Customer Added Successfully.</h2>    </body>    </html>  

 No /resources/ApplicationResources.properties   

 name= Name  

 label.add.customer=Add Customer  

 errors.invalid=${getText(fieldName)} is invalid.  

 errors.required=${getText(fieldName)} is required.  

 errors.number=${getText(fieldName)} must be a number.  

 errors.range=${getText(fieldName)} is not in the range ${min} and ${max}.  

 CustomerAction-validation.xml - CustomerAction = nome da Action. Deve estar no mesmo pacote da Action.  

 <validators>  

   <field name="name">  

     <field-validator type="requiredstring">  

       <param name="trim">true</param>  

       <message key="errors.required" />  

     </field-validator>  

   </field>  

   <field name="age">  

     <field-validator type="int">  

       <param name="min">1</param>  

       <param name="max">100</param>  

       <message key="errors.range"/>  

     </field-validator>  

   </field>  

 </validators>  

 Client Side Validator  

 No jsp, apenas coloca o parâmtro validate = true  

 <s:form action="customer.action" method="post" validate="true">  

   …  

 </s:form>  

  7.3.3 Interceptors  

 Eles interceptão ou agente sobre o request dos usuários. Três usos principais: Antes da action, entre a action e a view ou depois da view.  

   

   

   

 public class AuthorizationInterceptor extends AbstractInterceptor {  

     private static final String USER_KEY = "user";  

     public String intercept(ActionInvocation invocation) throws Exception {  

         Map session = invocation.getInvocationContext().getSession();  

         if(session.get(USER_KEY) == null) {  

             addActionError(invocation, "You must be authenticated ");  

             return Action.ERROR;     }  

   

         return invocation.invoke();        }  

   

     public String intercept(ActionInvocation invocation) throws Exception {  

       //Pre processing  

       logMessage(invocation, START_MESSAGE);  

       String result = invocation.invoke();  

       //Post processing  

       logMessage(invocation, FINISH_MESSAGE);  

       return result;  

     }  

     private void addActionError(ActionInvocation invocation, String message) {  

         Object action = invocation.getAction();  

         if(action instanceof ValidationAware) {  

             ((ValidationAware) action).addActionError(message);  

         }    }    }  

   

 Adding an Interceptor to your struts.xml:  

 <package name="example" extends="struts-default">  

  <interceptors>  

   <!--  

    One possible use of an interceptor is to send the user to special version of the .jsp  

      view if they are using a Blackberry as shown above.  

   -->  

   <interceptor name="wireless" class="com.lumidant.tutorial.struts2.interceptor.WirelessInterceptor">  

   

   <interceptor-stack name="wirelessStack">  

    <interceptor-ref name="exception" />  

    <interceptor-ref name="servlet-config" />  

    <interceptor-ref name="i18n" />  

    <interceptor-ref name="chain" />  

    <interceptor-ref name="params" />  

    <interceptor-ref name="wireless" />  

   </interceptor-stack>  

  </interceptors>  

   

  <default-interceptor-ref name="wirelessStack" />  

 </package>  

   

 Na configuração do Action  

 <action name="*Sample" method="{1}" class="vaannila.SampleAction">  

    <interceptor-ref name="exampleStack" />  

    <result name="populate">/first.jsp</result>  

    <result name="success">/success.jsp</result>  

 </action>  

  7.3.4 Tiles  

 http://javafree.uol.com.br/artigo/2157/Tiles-com-Struts.html  

   

 Solução para Templates de Layout, por exemplo, Foot e Header. Evita a repetição de código e controle do layout.  

 Solução 1: Inconveniente: Ao mudar o layout da aplicação, tem que modificar todas as páginas.   

     <html>   

      <body>   

        <jsp:include page="/header.jsp" />   

            a's body...   

       <p>   

        <jsp:include page="/footer.jsp" />   

       </body>   

     </html>   

   

 Solução 2: Com tile, mas parecido com a solução 1.  

 No web.xml  

     <taglib>  

        <taglib-uri>/tags/struts-tiles</taglib-uri>  

        <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>  

     </taglib>   

 Página.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <html>   

         <body>   

             <tiles:insert page="/header.jsp" flush="true"/>   

             <tiles:insert page="bBody.jsp" flush="true"/>   

             <tiles:insert page="/footer.jsp" flush="true"/>   

         </body>   

     </html>   

 Solução 3: Solução com Templates para a definição de layouts. Insere-se marcadores ao invés de dar includes.  

 Layout.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <html>   

      <body>   

       <tiles:insert attribute="header"/>   

       <tiles:insert attribute="body"/>   

       <tiles:insert attribute="footer"/>   

      </body>   

     </html>   

 Página.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <tiles:insert page="/layout.jsp" flush="true">   

       <tiles:put name="header" value="/header.jsp"/>   

       <tiles:put name="body" value="/aBody.jsp"/>   

       <tiles:put name="footer" value="/footer.jsp"/>   

     </tiles:insert>    

 Solução 4: Configurar o Struts e Tiles em um arquivo XML. Ex: tileDefinitions.xml  Nesse caso, nem tem um aquivo principal com o jsp, só fragmentos.  

   

     <?xml version="1.0" encoding="ISO-8859-1"?>   

     <component-definitions>   

       <definition name="aDef" path="/layout.jsp">   

         <put name="header" value="/header.jsp"/>   

         <put name="footer" value="/footer.jsp"/>   

         <put name="body" value="/aBody.jsp"/>   

       </definition>   

     </component-definitions>   

   

     <?xml version="1.0" encoding="ISO-8859-1"?>   

     <component-definitions>   

       <definition name="baseDef" path="/layout.jsp">   

         <put name="header" value="/header.jsp"/>   

         <put name="footer" value="/footer.jsp"/>   

         <put name="body" value=""/>   

       </definition>   

    

       <definition name="aDef" extends="baseDef">   

         <put name="body" value="/aBody.jsp"/>   

       </definition>   

      </component-definitions>   

 No web.xml  

       <init-param>   

         <param-name>definitions-config</param-name>   

         <param-value> /WEB-INF/tileDefinitions.xml </param-value>   

       </init-param>   

   

 No action:  

 public class DoFirst extends Action {   

    

   public ActionForward perform( ActionMapping aMapping, ActionForm aForm,   

     HttpServletRequest aRequest, HttpServletResponse aResponse ) {   

     return aMapping.findForward("success"); } }   

   

 No struts-config:  

     <action path="/a" type="com.malani.struts.action.DoFirst">   

       <forward name="success" path="aDef"/>   

     </action>    

   

  7.3.5 Struts com AJAX  

 http://viralpatel.net/blogs/2010/01/struts-2-ajax-tutorial-example-drop-down.html  

 O Struts 2 usa o AJAX using Dojo Toolkit: http://viralpatel.net/blogs/2009/02/introduction-to-dojo-toolkit-javascript-framework.html  

 1.    Incluir no classpath: struts2-dojo-plugin.jar. Jogar no WEB-INF/lib   

 2.    Criar a classe AJAX action:  

     import com.opensymphony.xwork2.  

     public class AjaxAutocomplete extends ActionSupport {  

       private String data = "Afghanistan, Zimbabwe, India, United States, Germany, China";  

       private List<String> countries;  

       private String country;  

       public String execute() {  

         countries = new ArrayList<String>();  

         StringTokenizer st = new StringTokenizer(data, ",");  

         while (st.hasMoreTokens()) {          countries.add(st.nextToken().trim());    }  

         return SUCCESS;  

       }  

       public String getCountry() {    return this.country;          }  

       public void setCountries(List<String> countries) {    this.countries = countries;  }  

       public void setCountries(List<String> countries) {    this.country = country;    }  

     }  

 3.    Criar a Jsp. Com a inclusão da taglib e o taglib <sx:head/> que será usada na para habilitar as tags AJAX. Colocar entre <head> … </head>   

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <%@ taglib prefix="sx" uri="/struts-dojo-tags"%>  

 <html><head>  <title>Welcome</title>  

   <sx:head />  

 </head>  

 <body>  

   <h2>Struts 2 Autocomplete (Drop down) Example!</h2>  

   Country:  

   <sx:autocompleter size="1" list="countries" name="country"></sx:autocompleter> Tag que renderiza o auto complete drop down  

   </action>  

 </body>    </html>  

 4.    struts.xml  

 <action name="ajaxdemo" class="net.viralpatel.struts2.AjaxAutocomplete">  

   <interceptor-ref name="loggingStack"></interceptor-ref>  

   <result name="success" type="tiles">/ajaxdemo.tiles</result>  //está usando tiles. Maspoderia apontar diretamente para o jsp.  

   <result type="tiles">/ajaxdemo.tiles</result>        com <result name="success">/ajaxDemo.jsp</result>  

 </action>   

   

domingo, 1 de setembro de 2013

JPA - Hibernate

JPA (Java Persistence API)

 http://www.marcomendes.com/ArquivosBlog/AloMundoJPA.pdf
 http://www.devmedia.com.br/articles/viewcomp.asp?comp=4590
 http://evandropaes.wordpress.com/2007/06/22/introducao-a-java-persistence-api-%E2%80%93-jpa/
 http://www.slideshare.net/caroljmcdonald/td09jpabestpractices2
 http://www.slideshare.net/guestf54162/jpa-java-persistence-api
 http://www.slideshare.net/rodrigocasca/jpa
 https://www.redhat.com/docs/manuals/jboss/jboss-eap-4.2/doc/Server_Configuration_Guide/Java_EE_5_Application_Configuration.html
 http://www.slideshare.net/junyuo/java-persistence-api-jpa-step-by-step-presentation
 
 JPA é um framework utilizado na camada de persistência para obter maior produtividade. Modo padrão de mapeamento Objeto/Relacional.
 O JPA define um caminho para mapear os POJOs para um BD (Java Persistence Metadata). Os pojos são vistos como beans de entidade(Entity Beans).
 Utiliza-se o ORM(Mapeamento Objeto/Relacional) para os entity Beans possam ser portados facilmente de um fabricante para outro.
 
 
 
  Entity: POJO, suporta herança e polimorfismo
 EntityManager: Responsável pelas operações de persistência de objetos.
 PersistenceContext: Área de memória que mantém os objetos que estão sendo manipulados pelos EntityManager
 Provedores: Especificação para framework de persistência.
 Persistence Unit: Configuração do provedor JPA para localizar o banco de dados e estabelecer conexões JDBC.
 
 Exemplo simples:
 package addressbook;
 import javax.persistence.*;
 
 @Entity
 public class Person {
   @Id @GeneratedValue
   public Long id;
   public String first;
   public String middle;
   public String last;
 }
 
 package addressbook;
 import javax.persistence.*;
 
 public class Main {
   EntityManagerFactory factory; //Um factory por aplicação, pois é thread-safe. Mas só é importante para aplicações Web. App desktop só tem 1 usuário mesmo.
   EntityManager manager;       //Um manager por usuário.    
   
   public void init() {
     factory = Persistence.createEntityManagerFactory("sample");//Persistence unit no persistence.xml.
     manager = factory.createEntityManager();
   }
 
   private void shutdown() {
     manager.close();
     factory.close();
   }
   
   public static void main(String[] args) {
     // TODO code application logic here
     Main main = new Main();
     main.init();
     try {
       // do some persistence stuff
     } catch (RuntimeException ex) {
       ex.printStackTrace();
     } finally {
       main.shutdown();
     }
   }
 //Para fazer uma persistência, é só criar uma transação, criar os objetos e salvá-los
   private void create() {
     System.out.println("creating two people");
     EntityTransaction tx = manager.getTransaction(); //Criou a Transação.
     tx.begin();
     try {
       Person person = new Person();
       person.first = "Joshua";
       person.middle = "Michael";
       person.last = "Marinacci";
       manager.persist(person);
 
       tx.commit();
     } catch (Exception ex) {
       tx.rollback();
     }
     System.out.println("created one person");
   }
 }
 
 Chaves compostas usando @EmbeddedId
 @Embeddable
 public class ContactPK implements Serializable {
 
   @Column(name = "FIRSTNAME", nullable = false)
   private String firstname;
 
   @Column(name = "LASTNAME", nullable = false)
   private String lastname;
 }
 A chave primária da classe da Entidade é anotada com a anotação @EmbeddedId.
 @Entity
 public class Contact implements Serializable {
 
   /**
    * EmbeddedId primary key field
    */
   @EmbeddedId
   protected ContactPK contactPK;
 
   public void hashcode(){} // tem que incluir esses dois métodos para garantir que terá só uma chave.
   public void equals() {}
 ...
 }
 
 
 Persistence.xml
 •     Lista as classes a serem persistidas
 •     A conexão do Banco de Dados
 •     E propriedades específicas para a implementação de persistência (ex:Hibernate, Hypersonic)
 •     Deve ficar dentro do META-INF
 
 <?xml version="1.0" encoding="UTF-8"?>
 <persistence xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation=
   "http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
   version="1.0">
   <persistence-unit name="sample" transaction-type="RESOURCE_LOCAL"> //Tem o nome da unidade, que tem que ser o mesmo recebido em Persistence.createEntityManagerFactory()
    <class>addressbook.Person</class>
    <properties>
      <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
      <property name="hibernate.connection.username" value="sa"/>
      <property name="hibernate.connection.password" value=""/>
      <property name="hibernate.connection.url"  value="jdbc:hsqldb:hsql://test"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/> //Controla como o hibernate cria e gerencia as suas tabelas
 o     Validate:
 o     Update: Cria as tabelas se elas não existirem, se adicionar novos campos, altera a tabela, deixando os dados intactos.
 o     Create: Cria a tabela na primeira conexão, destruindo todos os dados anteriores. Bom para teste.
 o     Create-drop: como o Create, mas destroy a tabela quando a conexão é fechada. Bom pra teste de unidade.
    </properties>
   </persistence-unit>
 </persistence>
 
 Rodar
 java -classpath lib/hsqldb.jar org.hsqldb.Server //Para rodar o hypersonic
 
 public static void main(String[] args) throws Exception {
    // start hypersonic
    Class.forName("org.hsqldb.jdbcDriver").newInstance();
    Connection c = DriverManager.getConnection(
         "jdbc:hsqldb:file:test", "sa", "");
    // start persistence
    Main main = new Main();
    main.init();
 
    // rest of the program....
 
   // shutdown hypersonic
   Statement stmt = c.createStatement();
   stmt.execute("SHUTDOWN");
   c.close();
 }
 
 Outros exemplos de Persistence.xml
 http://download.oracle.com/docs/cd/B31017_01/web.1013/b28221/cfgdepds005.htm
      Usado para o servidor saber qual DabaBase será usado. Nele é configurado qual engine de mapeamento Objeto/Relacional, cache para melhor performance. Ele dá a flexibilidade completa para configurar o EntityManager.
 
      Colocar em: META-INF dentro do diretorio WEB-INF/classes ou do Jar.
 OpenJPA
 <?xml version="1.0"?>
 <persistence>
   <persistence-unit name="testjpa" transaction-type="RESOURCE_LOCAL">
     <provider>
       org.apache.openjpa.persistence.PersistenceProviderImpl
     </provider>
     <class>entidades.Cliente</class>
     <properties>
       <property name="openjpa.ConnectionURL" value="jdbc:postgresql://localhost:5432/jpateste"/>
       <property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver"/>
       <property name="openjpa.ConnectionUserName" value="postgres"/>
       <property name="openjpa.ConnectionPassword" value="123456"/>
       <property name="openjpa.Log" value="SQL=TRACE"/>
     </properties>
   </persistence-unit>
 </persistence>
 
 Hibernate
 <persistence>
  <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
 
   <provider>org.hibernate.ejb.HibernatePersistence</provider>
   <jta-data-source>java:/DefaultDS</jta-data-source>
   <properties>
    <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>
    <property name="hibernate.connection.url" value="jdbc:derby:db; create=true"/>
    <property name="hibernate.connection.autocommit" value="true"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" ou “DerbyDialect”/>
    <property name="hibernate.connection.username" value="APP" />
    <property name="hibernate.connection.password" value="APP" />
 
   </properties>
  </persistence-unit>
  OU
 <persistence>
  <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
   <properties>
      <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />
      <property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true" />
      <property name="hibernate.connection.username" value="APP" />
      <property name="hibernate.connection.password" value="APP" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
 </properties>
  </persistence-unit>
 </persistence>
 
 TopLink
 <persistence>
 <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
  <properties>
      <property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
      <property name="toplink.jdbc.user" value="APP"/>
      <property name="toplink.jdbc.password" value="APP"/>
  </properties>
 </persistence-unit>
 </persistence>
 
 
 
 Tabela:
 create table bug (
 id_bug int(11) not null auto_increment,
 titulo varchar(60) not null,
 data date default null,
 texto text not null,
 primary key (id_bug)
 );
 
 Classe POJO
 @entity
 @table(name=”bug”)
 public class bug implements java.io.serializable {
      private integer id_bug;
      private string titulo;
      private java.util.date data;
      private string texto;
      @Enumerated(EnumType.STRING) → Define que um tipo vem de um enum
      @Conumn(name=”TIPO_MOEDA”, nullable=false, columnDefinition=”CHAR(1)”))
      private TipoMoeda tipoMoeda;
      @Transient → Valor não será gravado.
      private Integer valor = new Integer();
      /** creates a new instance of bug */
      public bug() {}
      /*a notação @generatedvalue(strategy=generationtype.sequence) informa que o id será gerado automaticamente pelo db.*/
      @id
      @generatedvalue(strategy=generationtype.sequence)
      @column(name=”id_bug”)
      public integer getid_bug() {     return id_bug;     }
      public void setid_bug(integer id_bug) {     this.id_bug = id_bug;     }
 
      @column(name=”titulo”, lenght=255, nullable=true)
      public string gettitulo() {     return titulo;     }
      public void settitulo(string titulo) {          this.titulo = titulo;     }
 
      @temporal(temporaltype.date)
      @column(name=”data”)
      public java.util.date getdata() {     return data;     }
      public void setdata(java.util.date data) {     this.data = data;     }
 
      @column(name=”texto”)
      @Lob → Define que o campo armazenará dados do tipo Long Object Binary(texto)
      public string gettexto() {     return texto;     }
      public void settexto(string texto) {     this.texto = texto;     }
      @override
      public string tostring(){     return “id: “+this.id_bug;     }
 }
 
 Query
 •     NamedQuery
 o     Query predefinidaes executadas por nome.
 @NamedQuery cria consulta predefinida (estática) associado com o @Entity
 
 @Entity
 @NamedQuery(name = “ConsultaPorId”, query = “SELECT f FROM Funcionarios f WHERE f.id = :id”)
 public class Funcionario implements Serializable {
 ...
 }
 
 •     Criteria
 o     So do Hibernate, baseado na API Criteria
 •     By Example
 •     JPAQL/ HQL / EJB3-QL
 o     Parecidas com SQL, mas mais objec-centric
 o     Suporta (Seleção de instancias, propriedades, polimorfismo), joining automático para propriedades nested.
 o     Confortável para quem é familiar ao SQL
 o     JPAQL é um subconjunto do HQL (Hibernate suporta ambos)
 o     Para rodar:
      EntityManager.createQuery(String jpaql)
      Session.createQuery(String hql)
 Ex: “from Item i where i.name = “aaa”
   private void search() {
     EntityTransaction tx = manager.getTransaction();
     tx.begin();
     System.out.println("searching for people");
     Query query = manager.createQuery("select p from Person p");
     List<Person> results = (List<Person>)query.getResultList();
     for(Person p : results) {
       System.out.println("got a person: " + p.first + " " + p.last);
     }
     System.out.println("done searching for people");
     tx.commit();
   }
 
 
 •     Native SQL
 o     Session.createSQLQuery(SQL)
 o     EntityManager.createNativeQuery(sql)
 
 
 
 Relacionamento
 •     Um para Um (@OneToOne)
 @OneToOne (mapedBy = “pessoa”)
 private Ramal ramal;
 
 @OneToOne
 @JoinColumn( name = “id_pessoa”)
 private Pessoa pessoa;
 Tabelas.
 ramal                    pessoa
  - numero:Integer                - id:Integer
  - pessoa_id: Integer (FK)           - nome: VARCHAR(50)
 
 
 •     Um para Muitos(@OneToMany)´
 Uma entidade possui uma coleção de outras entidades.
 @OneToMany(mappedBy=”pessoa”, cascade = CascadeType.ALL)
 private List<Ramal> ramais = new ArrayLIst<Ramal>();
 •     Muitos para um (@ManyToOne)
 A entidade faz parte de uma coleção de entidades de outra entidade.
 @ManyToOne(cascade=CascadeType.PERSIST)
 @JoinColumn(name=”id_pessoa”)
 private Pessoa pessoa;
 
 •     Muitos para muitos(@ManyToMany)
 @ManyToMany
 @JoinTable(name=”ramal_pessoa”,
 joinColumns=(@JoinColumn(name = “id_pessoa”)),
 inverseJoinColumns = (@JoinColumn(name = “id_ramal”))
 )
 @Column (name = “id_ramal”);
 private List<Ramal> ramais = new ArrayList<Ramal>();
       
 @ManyToMany
 @JoinTable(name=”ramal_pessoa”,
 joinColumns=(@JoinColumn(name = “id_ramal”)),
 inverseJoinColumns = (@JoinColumn(name = “id_pessoa”))
 )
 @Column(name = “id_pessoa”)
 private List<Ramal> pessoas= new ArrayList<Ramal>();
 
 Tabelas:
 Ramal               pessoa_has_ramal                    pessoa
  - numero:INTEGER     - pessoa_id: INTEGER (FK)                - id:INTEGER
                - ramal_numero: INTEGER                - nome: VARCHAR(50)
 
 Características dos Relacionamentos:
 •     Lazy loading
 o     Otimização de Performance
 o     Itens relacionados não são carregados até que eles sejam acessados pela primeira vez. (acesso a nível de Campo)
 o     Limitado para trabalhar somente com a Sessão ou EntityManager que carregou o objeto pai.
      Pode causar problemas em aplicações web.
 •     Fetch
 o     Fetch Mode
      Lazy
      Eager – desabilita o lazy loading
 o     Modo pode ser configurado em cada relacionamento.
 o     Considerar a performance e usar quando estiver configurando o fetch.
 @Basic(fetch = FetchType.LAZY) //Só vai carregar o objeto quando o método for acessado.
 @Lob      //Permite um BLOB ou CLOB (Bit or Char Large Object transforma valores para charS ou biteS
 public BufferedImage getPhoto() {
   return photo;
 }
 
 
 •     Cascading
 o     Fala do Hibernate o que fazer com o relacionamento nos casos de Insert, Update, Delete, All
 o     Cascade=PERSIST, REMOVE, MERGE, REFRESH, ALL.
 •     Polimorphic
 o     Três abordagens:
      Tabela por hierarquia de classe
 •     Todo dado de todas as propriedades das classes na herança são guardadas na tabela.
 •     Requer que as colunas que representam campos na subclasses permitam NULL.
 •     Usa uma coluna discriminadora para determinar o tipo de objeto representado em uma tupla.
 @Entity
 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
 @DiscriminatorColumn(name=”person_type”)
 public class Person {
      @Id     @GeneratedValue(strategy=GenerationType.AUTO)
      private int id = 0;
      private String name;
 }
 @Entity @DiscriminatorValue(value=”p”
 public class Patient extends Person {
      private boolean insured = false;
 }
 @Entity @DiscriminatorValue(value=”d”)
 public class Physician extends Person {
      private boolean accredited;
 }
 
 create table person {
      patient_id INTEGER,
      person_type varchar(255) not null,
      name varchar(255) not null,
      insured bit
      accredited bit
      primary key (patient_id));
 
      Tabela por sub-classe.
 •     Cada sub-classe tem a sua própria tabela.
 •     Campos da classe Pai estão em outra tabela.
 •     PK na tabela da sub-classe referem à tabela da classe pai.
 •     Usar configuração joined-subclass
 •     Também suporta o uso de discriminator
 @Entity     @Inheritance(strategy=InheritanceType.JOINED)
 public abstract class Payment
      @Id     @Column(name=”payment_id”)
      @GeneratedValue(strategy=GenerationType.AUTO)
      private int id = 0;
 }
 @Entity @Table(name=”check_payment”)
 @PrimaryKeyJoinColumn(name=”payment_id”)
 public class CheckPayment extends Payment{    
      private int check;
 }
 @Entity @Table(name=”credit_card_payment”)
 @PrimaryKeyJoinColumn(name=”payment_id”)
 public class CreditCardPayment extends Payment{    
      @Column(nullable=false)
      private String account;
 }
 create table payment { payment_id INTEGER, amount INTEGER, primary key(payment_id));
 create table check_payment { payment_id INTEGER, check-numer INTEGER, primary key(payment_id));
 create table credit_card_payment { payment_id INTEGER, account INTEGER, primary key(payment_id));
 
      Table por classe concreta
 •     Cada classe na hierarquia tem a sua própria tabela.
 •     O campos da classe pai são duplicadas em cada tabela.
 •     Duas abordagens:
 o     Subclass Union.
      Mapeia a classe pai normalmente, sem discriminador.
      @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
      Papeia cada uma das subclasses
 •     Especifica o nome da tabela
 •     Especifica as propriedades das subclasses
 o     Polimorfismo Implícito
      Class pai não é mapeada usando hibernate (@MappedSuperclass)
      Cada subclasse é mapeada como uma clase normal.
 •     Mapeia todas as propriedades, inclusive as propriedades do pai.
 @MappedSuperclass
 public class Vehicle{               //Class não é mapeada, mas as propriedades são.
      @Id      @Column(name=”vehicle_id”)
      @GeneratedValue(strategy=GenerationType.AUTO)
      private int id;
 }
 @Entity
 public class Car extends Vehicle{
      boolean coupe;
 }
 @Entity
 public class Truck extends Vehicle {
      @Column (name=”Max_weight”)
      private int maxWeight;
 }
 public SUV extends Truck {
      @Column (name=”spinner_wheels”)
      private boolean spinnerWheels;
 }
 create table vehicle ( vehicle_id INTEGER, coupe_ind bit, primary key(vehicle_id));
 create table truck ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
 create table suv ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
 
 
 Sem EJB
 EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
 EntityManager em = emf.createEntityManager();
 EntityTransaction et = em.getTransaction();
 et.begin();
      Insert: em.persist(carro);
      Update: em.merge(carro);
      Remove: em.remove(carro);
      Busca: Carro carro = em.find(Carro.class, id);
 et.commit() ou et.roolback();
 
 Com EJB
 EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
 @PersistenceContext
 EntityManager em = emf.createEntityManager();
 EntityTransaction et = em.getTransaction();
 et.begin();
      Insert: em.persist(carro);
      Update: em.merge(carro);
      Remove: em.remove(carro);
      Busca: Carro carro = em.find(Carro.class, id);
 et.commit() ou et.roolback();
 
  6.4.9.1 Entity Manager
 
 •     No Hibernate
 o     Configuration -> SessionFactoryy -> Session
 o     Session é o gateway para as funções de persistência.
 •     JPA
 o     Persistence -> EntityManagerFactory -> EntityManager
 o     EntityManager é o gateway para as funções de persistência.
 
 Ciclo de Vida de um Objeto
 Um objeto(Entity) pode ter 4 estados que indicam como eles estão conectados ao BD.
 •     New(transient): Objeto foi criado, mas ainda não foi persistido ou associado ao BD. Ao ser salvo com o EntityManager.persist() ele passa ao estado Managed.
 •     Managed(Persistent): O objeto já está associado ao BD. Mudanças no objeto vão, potencialmente gerar mudança no BD. Se necessário pode-se chamar EntityManager.flush() para sincronizar as mudanças, senão somente no commit da transação.
 •     Detached: O objeto já foi associado ao BD, mas não está mais. Um objeto Detached pode ser reatached usando o EntityManager.merge().
 •     Removed: Objeto que recebeu a operação de remoção. EntityManager.remove();
 
 Similar ao Hibernate Session, controla o ciclo de vida das entidades.
 •     new() → Cria uma nova entidade
 •     persist() → Salva ou faz um update em uma entidade
      public Order createNewOrder(Customer customer){
           Order order = new Order(customer);
           entityManager.persist(order);
           return order;          }
 •     refresh() → Atualiza o estado da entidade
 •     remove() → Marca uma entidade para remoção
      public void removeOrder(Long orderId){
           Order order = entityManager.find(Order.class, orderId);
           entityManager.remove(order);      }
 •     merge() → Sincroniza o estado de entidades desacopladas.
      public void updateOrder(Order order){
           entityManager.merge(order);      }
 •     find(Class type, Serializeble id) – Obtém o item de um tipo pelo id
 •     getTransaction
 ◦     Prove um objeto de transação para fazer o commit e rollback.