At line 178 changed 2 lines. |
<div class="note" style="font-size: 12px"> |
<a name="appgen"></a>__A Ferramenta AppGen__ |
%%note <a name="appgen"></a>__NOTE:__ AppFuse versions 1.6.1+ contain include an [AppGen] tool that can be used to generate all the classes for the rest of these tutorials. However, it's best that you go through these tutorials before using this tool - then you'll know what code it's generating.%% |
At line 181 removed 17 lines. |
Como parte da 1.6.1, eu criei uma ferramenta __AppGen__ que pode ser usada para gerar todas as classes para o restante destes tutoriais. Esta ferramenta foi baseada em contribuições de [Lance Lavandowska|https://appfuse.dev.java.net/issues/show_bug.cgi?id=60] e [Ben Gill|https://appfuse.dev.java.net/issues/show_bug.cgi?id=78]. No início, eu não quis adicionar uma característica de geração de código como essa porque você terminaria com um 1-para-1 relacionamento entre tabelas/pojos, DAOs e Managers. Em muito de meu projetos, eu tenho de longe menos DAOs e Managers do que POJOs. |
|
Por padrão, AppGen irá gerar somente Actions/Controllers, Action/Controller Tests, test data, i18n keys e JSPs. Irá também configurar Actions/Controllers para você. Ele usa as classes genéricas BaseManager e BaseDaoHibernate (configurada como "manager" e "dao") reduzindo o número de arquivos que são gerados. Porém, eu percebi que algumas vezes você irá querer gerar todas as classes DAO e Manager (e também seus tests), assim eu adicionei esta opção também. |
|
Para usar a ferramenta AppGen (depois de instalar sua framework web), execute os seguintes passos: |
|
# Crie seu POJO (no diretório model) e <a href="#ref-CreateDAO-5">configure o arquivo de mapeamento</a> in applicationContext-hibernate.xml. |
# cd dentro do ''extras/appgen'' diretório e execute "ant -Dobject.name=Person -Dappgen.type=pojo". Neste exemplo, uma classe __Person__ deve existir em seu pacote "model". Isto gera todos os arquivos que você criou no tutoriais neste site (para sua framework web de escolha). |
# Para instalar os arquivos gerados, execute "ant install". Você pode executar "ant install -Dmodel.name=Person -Dmodel.name.lowercase=person" se você desejar fazer tudo de uma única vez. __ATENÇÃO:__ Você deveria fazer backup de seu projeto antes de executar esta opção - ou pelo menos ter certeza que ele foi gravado no seu repositório de código fonte. Eu testei este código, e penso que funciona bem - mas ele ''está'' modificando a árvore de código-fonte para você. |
|
A razão para o "lowercase" parâmetro é renomear as JSPs para começar com uma letra minúscula. Se eu tentasse renomá-los e alterado o nome do arquivo programaticamente, levaria à 1MB a importância da BSF e Rhino JARs (+5 linhas de código) e desta forma me pareceu mais fácil. Falando de JSPs - depende de você modificar o *Form.jsp e fazê-lo paracer melhor. Isto é abrangido no passo 5 de cada respectiva framework web "Create Action/Controller" tutorial: <a href="http://raibledesigns.com/wiki/Wiki.jsp?page=CreateActions#ref-CreateAction-5">Struts</a>, <a href="http://raibledesigns.com/wiki/Wiki.jsp?page=SpringControllers#ref-SpringControllers-5">Spring</a> and <a href="http://raibledesigns.com/wiki/Wiki.jsp?page=WebWorkActions#ref-WebWorkActions-5">WebWork</a>. |
|
__NOTA:__ Se você quizer gerar tudo DAOs/Managers/Tests, execute "ant install-detailed" no lugar de "ant install". Antes de você instalar tudo, os arquivos serão criados no extras/appgen/build/gen diretório (caso você queira dar uma olhada antes de instalar). Se você somente quizer testar a ferramenta, você pode cd para este diretório e executar "ant test" para vê o conteúdo destes tutoriais criados. |
|
Eu o encorago a ler estes tutorias mesmo se você decidir gerar todo seu código. Desta forma você irá entender o que está sendo gerado para você e somente precisará das lista de usuários para [perguntando questões inteligentes|http://www.catb.org/~esr/faqs/smart-questions.html]. ;-) Espero que esta ferramenta irá remover o sofrimento de escrever simples código CRUD e deixar você concentrar no desenvolvimento de suas regras/lógica de negócio e UIs especiais!</div> |
|
|
At line 200 changed 1 line. |
Para começar, crie uma classe PessoaDaoTest.java no diretório test/dao/**/dao. Esta classe deve estender [BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDAOTestCase.java.html], que já existe neste pacote. Esta classe pai é usada para carregar ApplicationContext do [Spring's|http://www.springframework.org] (Spring une todas as camadas), e para automaticamente carregar um arquivo .properties (ResourceBundle) que tem o mesmo nome que sua classe *Test.class. Neste exemplo, se você colocar um arquivo PessoaDAOTest.properties no mesmo diretório que PessoaDAOTest.java, este arquivo de propriedades estará disponível via uma variável rb. |
Para começar, crie uma classe PessoaDaoTest.java no diretório test/dao/**/dao. Esta classe deve estender [BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDAOTestCase.java.html], sub-classe da classe [AbstractDependencyInjectionSpringContextTests|http://www.springframework.org/docs/api/org/springframework/test/AbstractDependencyInjectionSpringContextTests.html] do Spring que já existe neste pacote. Esta classe pai é usada para carregar ApplicationContext do [Spring's|http://www.springframework.org] (Spring une todas as camadas), e para (opcionalmente) carregar um arquivo .properties (ResourceBundle) que tem o mesmo nome que sua classe *Test.class. Neste exemplo, se você colocar um arquivo PessoaDAOTest.properties no mesmo diretório que PessoaDAOTest.java, este arquivo de propriedades estará disponível via uma variável rb. |
At line 208 removed 2 lines. |
import org.apache.commons.logging.Log; |
import org.apache.commons.logging.LogFactory; |
At line 191 added 1 line. |
import org.springframework.dao.DataAccessException; |
At line 212 removed 1 line. |
|
At line 215 removed 3 lines. |
|
//~ Instance fields ======================================================== |
|
At line 221 changed 4 lines. |
//~ Methods ================================================================ |
protected void setUp() { |
log = LogFactory.getLog(PersonDaoTest.class); |
dao = (PersonDao) ctx.getBean("personDao"); |
public void setPersonDao(PersonDao dao) { |
this.dao = dao; |
At line 226 removed 8 lines. |
|
protected void tearDown() { |
dao = null; |
} |
|
public static void main(String[] args) { |
junit.textui.TestRunner.run(PersonDaoTest.class); |
} |
At line 237 changed 1 line. |
O código que você vê acima é o que precisamos para um teste JUnit básico, que inicializa e destrói nosso PessoaDAO. O objeto ctx é uma referência ao ApplicationContext do Spring, o qual é inicializado em um bloco estático da classe [BaseDaoTestCase's|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDaoTestCase.java.html] class. |
O código que você vê acima é o que precisamos para um teste de integração Spring básico que inicializa e destrói nosso PessoaDAO. Spring irá usar autowiring (auto-ligamento) por tipo para chamar o método ''setPersonDao()'' e atribuir o bean "personDao" como uma dependência desta classe. |
At line 225 added 1 line. |
|
At line 266 changed 1 line. |
assertTrue(person.getLastName().equals("Last Name Updated")); |
assertEquals(person.getLastName(), "Last Name Updated"); |
At line 249 added 1 line. |
|
At line 284 changed 1 line. |
assertNull(dao.getPerson(person.getId())); |
|
try { |
person = dao.getPerson(person.getId()); |
fail("Person found in database"); |
} catch (DataAccessException dae) { |
log.debug("Expected exception: " + dae.getMessage()); |
assertNotNull(dae); |
} |
At line 325 changed 1 line. |
Primeiro, crie a interface PessoaDAO.java no diretório src/dao/**/dao e especifique os métodos CRUD básicos para qualquer classe de implementação. Eliminei as partes JavaDocs na classe abaixo apenas por propósito de visualização.'' |
Primeiro, crie a interface PessoaDAO.java no diretório src/dao/**/dao e especifique os métodos CRUD básicos para qualquer classe de implementação. Eliminei as partes JavaDocs na classe abaixo apenas por propósito de visualização. |
At line 333 removed 2 lines. |
import java.util.List; |
|
At line 336 removed 3 lines. |
|
public List getPeople(Person person); |
|
At line 340 changed 3 lines. |
|
public void savePerson(Object person); |
|
public void savePerson(Person person); |
At line 357 removed 3 lines. |
import org.apache.commons.logging.Log; |
import org.apache.commons.logging.LogFactory; |
|
At line 328 added 1 line. |
import org.springframework.orm.ObjectRetrievalFailureException; |
At line 363 removed 3 lines. |
import java.util.List; |
|
|
At line 368 changed 1 line. |
private Log log = LogFactory.getLog(PersonDaoHibernate.class); |
public Person getPerson(Long id) { |
Person person = (Person) getHibernateTemplate().get(Person.class, id); |
At line 370 changed 3 lines. |
public List getPeople(Person person) { |
return getHibernateTemplate().find("from Person"); |
} |
if (person == null) { |
throw new ObjectRetrievalFailureException(Person.class, id); |
} |
At line 374 changed 2 lines. |
public Person getPerson(Long id) { |
return (Person) getHibernateTemplate().get(Person.class, id); |
return person; |
At line 378 changed 1 line. |
public void savePerson(Object person) { |
public void savePerson(Person person) { |
At line 383 changed 2 lines. |
Object person = getHibernateTemplate().load(Person.class, id); |
getHibernateTemplate().delete(person); |
// object must be loaded before it can be deleted |
getHibernateTemplate().delete(getPerson(id)); |
At line 389 removed 21 lines. |
|
Você notará aqui que não estamos fazendo nada com o parâmetro pessoa. Isto é somente um place holder por enquanto no futuro você pode filtrar suas propriedades usando [Hibernate's Query Language|http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html] (HQL) ou usando [Criteria Queries|http://www.hibernate.org/hib_docs/reference/en/html/querycriteria.html]. |
|
''Um exemplo usando Criteria Query:'' |
|
[{Java2HtmlPlugin |
|
Example example = Example.create(person) |
.excludeZeroes() //exclude zero valued properties |
.ignoreCase(); //perform case insensitive string comparisons |
try { |
return getSession().createCriteria(Person.class) |
.add(example) |
.list(); |
} catch (Exception e) { |
throw new DAOException(e); |
} |
return new ArrayList(); |
|
}] |
|
At line 423 removed 2 lines. |
<value>org/appfuse/model/UserCookie.hbm.xml</value> |
<value>org/appfuse/model/UserRole.hbm.xml</value> |
At line 453 changed 1 line. |
''Next Up:'' __Part II:__ [Creating new Managers|CreateManager] - A HowTo for creating [Business Delegates|http://java.sun.com/blueprints/corej2eepatterns/Patterns/BusinessDelegate.html] that talk to the database tier (DAOs) and the web tier (Struts Actions). |
''Próxima:'' __Parte II:__ [Criando novos Managers|CreateManager_pt] - Um "HowTo" para criar [Business Delegates|http://java.sun.com/blueprints/corej2eepatterns/Patterns/BusinessDelegate.html] que comunicam-se com a camada de banco de dados (DAOs) e web (Spring Controllers). |