Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ligação de dados com o Castor, Parte 4: Ligue seus objetos Java com bancos de dados SQL

Use o Castor para ligar objetos Java com bancos de dados SQL

Brett D. McLaughlin, Sr., Author and Editor, O'Reilly Media, Inc.
Photo of Brett McLaughlin
Brett McLaughlin é um autor de não ficção premiado e campeão de vendas. Seus livros sobre programação de computadores, home theater e análise e design já venderam mais de 100.000 cópias. Há quase 10 anos, ele escreve, edita e produz livros técnicos, e sente-se confortável tanto na frente de um processador de texto quanto tocando violão, correndo pela casa atrás dos seus dois filhos ou assistindo reprises de Arrested Development (Caindo na Real, no Brasil) com sua esposa. Seu último livro, Head First Object Oriented Analysis and Design, ganhou o prêmio Jolt Technical Book 2007. Além disso, seu clássico Java and XML continua sendo um dos trabalhos definitivos sobre o uso de tecnologias XML em linguagem Java.

Resumo:  Você já conhece a flexibilidade do Castor para converter objetos Java™ em XML e vice-versa. Porém, o Castor pode fazer muito mais que isto, incluindo transformar esses objetos Java em linhas no seu banco de dados SQL. Aprenda qual sintaxe é a mesma, qual é diferente, e como é possível adicionar SQL ao seu arsenal de ligações de dados.

Visualizar mais conteúdo nesta série

Data:  15/Abr/2010 (Publicado em: 15/Abr/2010)
Nível:  Avançado
Atividade:  3231 visualizações
Comentários:  


30 de março de 2010 Respondendo aos comentários dos leitores, o autor atualizou a Listagem 9 e a seção terceiro código curto após a Listagem 9. Alterou-se "author.getFirstName() + " " + author.getLastName());" para "lookup.getFirstName() + " " + lookup.getLastName());".

Para a maioria dos desenvolvedores—especialmente os de Java—o termo ligação de dados tornou-se parte comum do vocabulário, junto com encerramentos, singletons e Ajax. Assim como esses outros termos, a ligação de dados é frequentemente definida de maneira incorreta.

Especificamente, quando a maioria dos programadores escuta o termo ligação de dados, na verdade pensam em ligação de dados XML. A adição dessa pequena palavra—XML—faz com que a maioria dos programadores percam um mundo de funcionalidades e flexibilidade adicionais, especialmente quando a API Castor está sendo usada. Isto acontece, pois quando se trata do Castor, a ligação de dados XML é somente uma parte de todo o quebra-cabeça. Além de ligar dados Java em documentos XML, o Castor também oferece a possibilidade de ligar estes dados em bancos de dados SQL. E é nesse ponto que a ligação de dados SQL entra em jogo.

Definindo a ligação de dados SQL.

Acrônimos usados frequentemente

  • Ajax: Asynchronous JavaScript + XML
  • API: Application programming interface
  • IDE: Integrated Development Environment
  • XML: Extensible Markup Language

Ligação de dados SQL pode ser um novo termo, porém trata-se de um conceito bem simples. De fato, é possível entender melhor o termo à luz do que significa um termo mais familiar, ligação de dados XML. A ligação de dados XML é o processo de criação de um mapeamento entre os dados em um documento XML—normalmente armazenados em elementos e atributos—e as propriedades de um modelo de objeto Java. É possível executar um organizador e um desorganizador para mover-se entre os dois. Um organizador armazena os dados de um modelo de objeto Java em um documento XML; um desorganizador carrega os dados de um documento XML nas propriedades de um modelo de objeto Java.

Com base nisso, não deve ser difícil entender que a ligação de dados SQL é o processo de criação de um mapeamento entre os dados em um banco de dados SQL—armazenados em esquemas, tabelas, colunas, etc.—e objetos Java. O mesmo processo de execução de organizar e desorganizar é aplicado, mas a conversão ocorre entre objetos Java e SQL, em vez de objetos Java e XML. De fato, se você trocar XML por SQL e dados de elementos por entradas de tabela na maioria dos artigos sobre ligação de dados, já entenderá do que se trata a ligação de dados SQL.


O valor da ligação de dados SQL

Quando a tecnologia Java apareceu pela primeira vez, era praticamente uma linguagem de brinquedo, pois contava com uma API muito simples e focava em gráficos (você se lembra do AWT?). Um dos marcos do amadurecimento da tecnologia Java foi a adição da Java database connectivity (JDBC), permitindo persistência aos bancos de dados SQL. O único problema foi, e ainda é, que o uso da JDBC é um pouco complicado. Embora não seja algo complexo, seu uso introduz uma quantidade de trabalho adicional significativa para a maioria dos programas.

Com o Castor e a ligação de dados SQL, é possível evitar a maior parte desta complexidade. Além disso, você passa a usar uma API que funciona praticamente da mesma forma em contextos XML e SQL. Por fim, como na ligação de dados, há menos detalhes com os quais se preocupar no seu aplicativo. Lidar com contagens de linhas e ResultSets JDBC não é mais uma preocupação no seu código; em vez disso, algumas simples chamadas de organizar e desorganizar tratam da conversão entre objetos Java e o seu banco de dados SQL.

O mais interessante sobre a ligação de dados SQL é que ela não recebeu mais atenção e consideração. Isso é principalmente verdade considerando que grande parte dos programadores não se importam com XML, ou porque é muito detalhado e de difícil manejo, ou porque preferem a serialização binária. Entretanto, este mesmo grupo adota a SQL sem problema algum. De fato, é difícil achar até mesmo um grupo de programadores amadores que não pensem que a SQL é uma tecnologia legítima de persistência e armazenamento de dados. (Veja, por exemplo, quantos dos nossos parceiros pensam que os bancos de dados relacionais são excessivamente valorizados, ineficientes e irrelevantes.)

Sendo assim, a ligação de dados SQL é comprovadamente uma ferramenta ainda mais útil do que seu primo XML. Sempre é necessário persistir (ou armazenar) dados em um aplicativo corporativo, e a composição de códigos de acesso e recuperação de dados é realmente complicada. A ligação de dados SQL usa uma API familiar (assumindo aqui que você leu os artigos anteriores desta série) e a aplica completamente para o armazenamento de dados SQL. É possível escrever em uma tabela (ou várias tabelas) com poucos comandos, e extrair dados do mesmo modo.

O mapeamento ainda é aplicado

A capacidade de fazer o mapeamento a partir de objetos Java para um esquema de dados SQL sem estar preso a nomes SQL ou Java é particularmente importante na ligação de dados SQL. Mais ainda que em XML, a estrutura de um banco de dados relacional é normalmente muito diferente da estrutura dos seus objetos Java. Tabelas geralmente são coleções de dados, enquanto objetos costumam representar uma única porção (possivelmente uma linha) de dados. Os relacionamentos entre os objetos devem ser traçados com relação a outros objetos, do mesmo modo que os relacionamentos entre as tabelas devem ser feitos com relação a outras tabelas. Porém, não há uma tabela de junção de uma para muitos no seu modelo de objeto Java, e certamente nenhuma junção de muitos para muitos.

Ao começar a se envolver com as partes de complexidade intermediária do seu banco de dados relacional, você passará a projetar as coisas de forma diferente do que faria com um modelo de objeto. Grande parte do trabalho de mapeamento de SQL para objetos Java e vice-versa é definir o mapeamento entre os objetos e as tabelas. Embora o mapeamento possa ser algo bem avançado, neste artigo eu usarei mapeamentos simples para lhe oferecer um entendimento básico sobre como funciona o mapeamento no mundo das ligações de dados SQL.


Isso se trata simplesmente de JDO, certo?

Sim. Bem, não. Mais ou menos. Este ponto é um pouco confuso.

Padrões são realmente importantes?

Alguns desenvolvedores—ou seus chefes—creem que o uso de APIs padrão é o fator mais importante na escolha de tecnologias. Outros não se importam nem um pouco com isso. Em geral, sua melhor opção é usar a API que seja mais produtiva para o seu trabalho, sendo ou não uma API "padrão". O aumento na produtividade compensa sem dúvida nenhuma os ditos aspectos negativos do uso de APIs não padrão.

Ainda assim, recomenda-se verificar o histórico de uma API não padrão. Por exemplo, se você encontrar uma ótima ferramenta, que existe há apenas três meses e foi desenvolvida por um sujeito em sua garagem, provavelmente terá problemas mais adiante com atualizações e suporte (embora ainda haja a possibilidade de que ele seja o próximo Bill Gates ou Steve Jobs). Se escolher uma API um pouco fora do comum, ao menos certifique-se de que há certo histórico (um versão 2.0 ou superior é um bom sinal) e de preferência alguma documentação ou suporte on-line.

A Sun tem uma especificação chamada de Java Data Objects (JDO). O Java Specification Request (JSR) 12 para JDO 1.0 e o JSR 243 para JDO 2.0 definem uma abordagem específica para a ligação de dados SQL (embora não seja explicitamente chamada "ligação de dados SQL") Se você ler sobre JDO e então reler os parágrafos introdutórios deste artigo, pensará que está lendo a mesma coisa. Porém, a versão da especificação JDO do Castor (sim, o Castor também usa o nome JDO, o que torna as coisas ainda mais confusas) não é a mesma da Sun, ou mesmo tem relação com a Sun, com a única exceção que ambas têm o mesmo objetivo.

Isso pode causar muita confusão, assim, é preciso dizer novamente: se você usa a JDO do Castor, você não está usando a API padrão da SUN. Porém, isto não é tão ruim, ou tão claro, quanto parece. O pessoal no Castor está tentando implementar muitos dos recursos que trabalharam em sua própria API nas ligações de dados da Sun e em APIs JDO. Assim, embora a Castor não seja uma API padrão, muitos dos recursos—e a própria API—podem levá-la a se tornar uma API JDO padronizada.

Configurando um ambiente de exemplo

No caso de ligações de dados XML, seus dois terminais são um modelo de objeto Java e um documento XML (um esquema XML que restrinja documentos). No mundo das ligações de dados SQL, você ainda usaa um modelo de objeto Java, mas o outro terminal é um esquema SQL: uma ou mais tabelas com colunas. Considere um conjunto de terminais relativamente simples para os exemplos deste artigo.

Nesta série, eu usei um modelo de objeto Java para representar livros e autores, assim, vou usar novamente o mesmo modelo de dados neste artigo. A Listagem 1 mostra o código para a classe Book.


Listagem 1. A classe Book
package ibm.xml.castor;

import java.util.LinkedList;
import java.util.List;

public class Book {

  /** The book's ISBN */
  private String isbn;
  /** The book's title */
  private String title;
  /** The authors' names */
  private List<Author> authors;

  public Book() { }

  public Book(String isbn, String title, List<Author> authors) {
    this.isbn = isbn;
    this.title = title;
    this.authors = authors;
  }

  public Book(String isbn, String title, Author author) {
    this.isbn = isbn;
    this.title = title;
    this.authors = new LinkedList<Author>();
    authors.add(author);
  }

  public void setIsbn(String isbn) {
    this.isbn = isbn;
  }

  public String getIsbn() {
    return isbn;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public String getTitle() {
    return title;
  }

  public void setAuthors(List<Author> authors) {
    this.authors = authors;
  }

  public List<Author> getAuthors() {
    return authors;
  }

  public void addAuthor(Author author) {
    authors.add(author);
  }
}

A Listagem 2 mostra o código para a classe Author.


Listagem 2. Uma classe para representar os autores
package ibm.xml.castor;

public class Author {

  private String firstName, lastName;

  public Author() { }

  public Author(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getFirstName() {
    return firstName;
  }
  
  public String getLastName() {
    return lastName;
  }

}

Nos artigos anteriores, você fez a persistência de várias ocorrências destas classes para documentos XML. Nos dois primeiros artigos, você focou na conversão direta do modelo de objeto para documentos XML, usando em ambos os mesmos nomes de propriedades. No terceiro artigo, o foco foi a conversão de objetos Java para XML (e vice-versa), mas com a capacidade de alterar convenções de nomenclatura de um formato para o outro.

Porém, agora, queremos armazenar todos os dados destas classes em um banco de dados SQL. Em vez de elementos e atributos, os dados estão em colunas, linhas e tabelas.

Criando uma amostra do esquema do banco de dados SQL

De certo modo, um esquema do banco de dados SQL normalmente é mapeado de forma parecida a um modelo de objeto Java, principalmente se o modelo não é muito complexo (como no nosso caso). Vamos considerar duas tabelas: dw_books e dw_authors.

É mais fácil criar a tabela dw_authors primeiro, pois a tabela dw_books faz referência a esta. Ela deve ter três colunas: um ID para cada autor, e seus primeiros e últimos nomes. Caso esteja acompanhando, é possível criar esta tabela em MySQL com o código da Listagem 3.


Listagem 3. Uma tabela para os autores
CREATE TABLE 'dw_authors' (
'id' INT NOT NULL ,
'first_name' VARCHAR( 50 ) NOT NULL ,
'last_name' VARCHAR( 50 ) NOT NULL ,
PRIMARY KEY ( 'id' ) ,
INDEX ( 'first_name' , 'last_name' )
);

Observe que eu usei o prefixo dw_ em todas as tabelas deste artigo para distingui-las de outras tabelas que você pode encontrar, principalmente porque authors e books são nomes comuns de tabelas. Embora isto possa ser um pouco confuso, garante que você não terá conflitos de nomenclaturas com outros bancos de dados no seu sistema, caso esteja acompanhando este artigo (e possivelmente você está).

A seguir temos a tabela dw_books. Ela também é muito simples. A data definition language (DDL), que é o idioma usado para criar estruturas em SQL, está na Listagem 4.


Listagem 4. DDL para a tabela dw_books
CREATE TABLE 'dw_books' (
'isbn' VARCHAR( 13 ) NOT NULL ,
'title' VARCHAR( 200 ) NOT NULL ,
PRIMARY KEY ( 'isbn' ) ,
INDEX ( 'title' )
);

Finalmente, é necessário conectar essas duas tabelas. Aqui, já temos um problema. Um livro pode ter vários autores, o que significa que há um relacionamento de muitos para muitos entre as tabelas dw_books e dw_authors. Em outras palavras, um livro pode ter vários autores e um autor pode escrever vários livros. Logo, é necessária uma tabela para conectar um livro a um autor, e estas conexões devem ser de muitas para muitas.

No mundo de SQL, isto é algo muito comum: é necessária uma tabela de junção, onde cada linha contém um ISBN e um ID de autor. A Listagem 5 mostra como a tabela se parece.


Listagem 5. Tabela de junção (de muitos para muitos) para autores e livros
CREATE TABLE 'dw_books_authors' (
'book_isbn' VARCHAR( 13 ) NOT NULL ,
'author_id' INT NOT NULL ,
PRIMARY KEY ( 'book_isbn' , 'author_id' )
);

Entendendo a integridade referencial

Integridade referencial é um termo especial de SQL que diz respeito a manter todos os dados do seu banco de dados limpos, livres de dados incorretos ou fora de uso, e precisos em termos de junções entre as tabelas. Neste contexto, se você excluir um livro, todos os registros na tabela dw_books_authors com o ISBN deste livro serão excluídos. Uma vez que o livro não existe, também não devem existir registros com o ISBN deste livro. O mesmo serve para o autores; quando um autor é excluído, todos os registros com o ID desse autor também devem ser excluídos.

Para fazer isso, usam-se chaves estrangeiras. Logo, na tabela dw_books_authors, book_isbn contém isbn na tabela dw_books como um chave estrangeira; o mesmo relacionamento ocorre entre author_id na tabela dw_books_authors e id em dw_authors. Isso garante a integridade referencial entre as tabelas.

Entretanto, a maioria dos bancos de dados lida com a integridade referencial de forma diferente, e o MySQL não a suporta completamente em muitas versões do software. Assim, para tornar as coisas mais simples neste artigo, nenhuma chave estrangeira foi usada. Se você gosta de criar chaves estrangeiras, o que é uma boa ideia, verifique a documentação do fornecedor para o seu banco de dados ou consulte seu database administrator (DBA).


Preparando-se para a ligação de dados SQL

Mesmo que você já tenha usado o Castor para ligações de dados XML, provavelmente precisará fazer algumas alterações (ou, pelo menos, adições) ao seu ambiente de programação para fazer a ligação de dados SQL funcionar.

Adicionando arquivos JDO do Castor ao seu caminho de classe

Sua primeira necessidade são classes JDO do Castor no seu caminho de classe. Se você acompanhou as etapas de instalação no primeiro artigo desta série (consulte links para o artigo em Recursos), terá todos os arquivos Castor Java ARchive (JAR). Entretanto, é possível que você não tenha adicionado o arquivo específico JDO JAR ao seu caminho de classe. No diretório do Castor, localize e adicione o arquivo castor-1.1.2.1-jdo.jar ao seu caminho de classe (sua versão do arquivo pode ser mais recente, mas o procedimento é o mesmo).

Este arquivo junta-se aos outros arquivos JARs do Castor que você provavelmente já adicionou, como castor-1.1.2.1.jar, castor-1.1.2.1-xml.jar, e os arquivos Xerces e Commons Logging JAR. Se você usa um servidor de aplicativos ou IDE para executar seu código, certifique-se de também alterar esses caminhos de classe.

Adicionando um driver JDBC ao seu ambiente

Uma vez que você irá se conectar a um banco de dados SQL, é necessário um driver JDBC do seu fornecedor. Drivers JDBC para IBM DB2® e Informix®, Oracle, MySQL, PostgreSQL, entre outros, estão disponíveis gratuitamente. Isto já pode estar resolvido caso você tenha aplicativos com acesso a bancos de dados. Se você está começando a conhecer o JDBC, consulte os Recursos para links para drivers JDBC da DataDirect, que funcionam muito bem em DB2 e Informix, assim como em muitos outros servidores de bancos de dados. Caso não esteja usando DB2 ou Informix, encontre o driver JDBC para o seu fornecedor de banco de dados através de um busca rápida no Google, faça o download de um JAR e adicione-o ao seu caminho de classe.

Para este artigo, o banco de dados MySQL é usado na maioria dos exemplos. Caso for usar MySQL, você precisará do arquivo mysql-connector-java-3.0.17-ga-bin.jar, disponível gratuitamente no Web site MySQL (consulte os Recursos para mais informações).


Mapeando uma classe para uma tabela

Considere a mais simples das tarefas de ligação de dados SQL: mapear para uma única tabela um objeto que não faz referência a nenhum outro objeto. Esta é a principal operação que você irá executar na ligação de dados SQL, sendo que todos os recursos mais avançados vêm a ser variações deste tema.

Entendendo um mapeamento

Primeiro, mapeie a classe Author para a tabela dw_authors. O mapeamento desejado é como o exibido na Tabela 1.


Tabela 1. Mapeamento entre o objeto Author e a tabela dw_authors.
Propriedade JavaColuna SQL
firstNamefirst_name
lastNamelast_name

Isto é suficientemente simples, porém há um problema óbvio: a tabela dw_authors também contém uma coluna id. De fato, esta é a chave primária da tabela dw_authors, assim, deve obrigatoriamente existir. Como resultado, é necessário fazer uma adição à classe Author, como exibido na Listagem 6.


Listagem 6. Adicionando suporte a IDs em Author.java
package ibm.xml.castor;

public class Author {

  private String firstName, lastName;
  private int id;

  public Author() { }

  public Author(int id, String firstName, String lastName) {
    this.id = id;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public void setId(int id) {
    this.id = id;
  }

  public int getId() {
    return id;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getFirstName() {
    return firstName;
  }
  
  public String getLastName() {
    return lastName;
  }

}

Agora é possível atualizar a tabela que mostra o mapeamento entre uma ocorrência de Author e uma linha na tabela dw_authors, como exibido na Tabela 2.


Tabela 2. Adicionado um campo ID à tabela de mapeamento
Propriedade JavaColuna SQL
idid
firstNamefirst_name
lastNamelast_name

Criando um mapeamento para o Castor

Agora é necessário indicar ao Castor quais propriedades Java mapeiam para quais colunas SQL. Para isso, usa-se um arquivo de mapeamento similar aos arquivos de mapeamento que você usou para XML no terceiro artigo desta série. A Listagem 7 mostra o mapeamento usado para converter ocorrências de Author para linhas na tabela dw_authors.


Listagem 7. Mapeando objetos Author para a tabela dw_authors
<mapping>
  <class name="ibm.xml.castor.Author" identity="id">
    <map-to table="dw_authors" />
    <field name="id" type="int">
      <sql name="id" type="integer" />
    </field>
    <field name="firstName" type="string">
      <sql name="first_name" type="varchar" />
    </field>
    <field name="lastName" type="string">
      <sql name="last_name" type="varchar" />
    </field>
  </class>
</mapping>

Não há muito o que falar sobre isso, pois é semelhante aos arquivos de mapeamento usados com objetos Java e XML. Salve este arquivo como sql-mapping.xml, e agora é possível indicar para o Castor como mapear as propriedades dos seus objetos Java nas suas tabelas do banco de dados.

O atributo de identidade

Em comparação com o que você viu no mapeamento em Java e XML, a única novidade no arquivo de mapeamento é o uso do atributo identity, que indica o campo de chave primária para a tabela dw_authors. Provavelmente você não tinha usado o atributo identity antes, pois o Castor normalmente infere ou não precisa dele para funcionar. Porém, na ligação de dados SQL, este atributo informa ao Castor o campo que define especificamente um objeto; neste caso, o campo id de um autor.

Configurando o Castor para o acesso SQL

No mundo das ligações de dados XML, é necessário estar preparando para escrever códigos para organizar XML para objetos Java e vice-versa. Porém, no modelo SQL, há outra parte do software a considerar: o banco de dados. É preciso informar ao Castor onde o seu banco de dados está localizado, como efetuar login e qual arquivo de mapeamento deve ser usado. Isto é feito através de um arquivo de configuração, normalmente nomeado como jdo-conf.xml. A Listagem 8 fornece um arquivo de configuração, que você pode usar para MySQL.


Listagem 8. Definindo um esquema de conexão MySQL para o Castor
<?xml version="1.0" ?>
<!DOCTYPE jdo-conf PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN"
                          "http://castor.org/jdo-conf.dtd">
<jdo-conf>
  <database name="YOUR-DATABASE-NAME" engine="mysql">
    <driver class-name="com.mysql.jdbc.Driver"
            url="jdbc:mysql://YOUR-DATABASE-SERVER-HOSTNAME/YOUR-DATABASE-NAME">
      <param name="user" value="YOUR-DATABASE-USERNAME"/>
      <param name="password" value="YOUR-DATABASE-PASSWORD"/>
    </driver>
    <mapping href="sql-mapping.xml"/>
  </database>
  <transaction-demarcation mode="local"/>
</jdo-conf>

Adicionado, procurando e excluindo uma entrada

Após todas estas configurações, você está finalmente pronto para interagir com o banco de dados. Usando estes arquivos de configuração, é necessário carregar a configuração, abrir um banco de dados e interagir com ele. A Listagem 9 faz tudo isso, criando uma nova ocorrência de Author, armazenando-a no banco de dados, procurando e, a seguir, removendo-a.


Listagem 9. Usando a ligação de dados SQL com um autor
import ibm.xml.castor.Author;

import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDOManager;

public class SQLTester {
  public static void main(String args[]) {
    try {
      JDOManager.loadConfiguration("jdo-conf.xml");
      JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

      Database database = jdoManager.getDatabase();
      database.begin();
      Author author = new Author(1001, "Joseph", "Conrad");
      database.create(author);

      Author lookup = (Author)database.load(Author.class,
                                    new Integer(1001));
      System.out.println("Located author is named " +
        lookup.getFirstName() + " " + lookup.getLastName());
      database.remove(lookup);
      database.commit();
      database.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Vamos observar este processo passo a passo.

Primeiro, é necessário um trabalho inicial para carregar suas informações de conexão e conectar-se ao banco de dados. Esta primeira etapa é basicamente a mesma em todo aplicativo onde você usa ligação de dados SQL, assim, recomenda-se memorizar estes comandos (ou adicionar este artigo aos seus favoritos):

 JDOManager.loadConfiguration("jdo-conf.xml"); JDOManager
                jdoManager = JDOManager.createInstance("bmclaugh"); Database database =
                jdoManager.getDatabase(); database.begin();

O objetivo aqui é adquirir uma ocorrência do objeto Database, que lhe permite criar, procurar e excluir entradas. Após adquirir a ocorrência, é possível criar uma nova ocorrência de Author e armazená-la no banco de dados:

 Author author = new Author(1001, "Joseph", "Conrad");
                database.create(author);

Ao chamar create(), o Castor usa o seu arquivo de mapeamento (sql-mapping.xml) para descobrir como armazenar o objeto que você passa para esse método como dados SQL. Os seus dados são colocados no banco de dados e você já está pronto para usá-los.

A seguir, é possível procurar objetos por sua identidade (é aqui que o atributo identity entra em jogo):

 Author lookup = (Author)database.load(Author.class, new
                Integer(1001)); System.out.println("Located author is named " +
                lookup.getFirstName() + " " + lookup.getLastName());

Usa-se o método load() com o tipo de classe que você deseja usar, assim como o valor de identidade para a entrada que deseja. load() retorna uma nova ocorrência, que pode ser usada como qualquer outro objeto Java, novamente usando os mapeamentos definidos em sql-mapping.xml.

Este exemplo exclui a entrada, deixando o banco de dados no mesmo estado em que estava antes da execução do programa:

 database.remove(lookup);

Por fim, mas não menos importante, é necessário executar as alterações e fechar o banco de dados:

 database.commit(); database.close();


Adicionado dados relacionais

Como você pode ver, não é muito difícil trabalhar com um simples mapeamento de classe para tabela. Entretanto, as coisas ficam mais interessantes quando é necessário trabalhar com uma situação mais complicada, como modelo de objeto Java com Books relacionados a ocorrências de Author.

Definindo um mapeamento SQL básico para um livro

Assim como em Author, é necessário definir um mapeamento em sql-mapping.xml para tomar as propriedades da classe Book e persisti-las para um banco de dados relacional. Comece com as adições da Listagem 10; estas tratam das propriedades básicas de um livro.


Listing 10. Adding a book to the mappings file
<mapping>
  <class name="ibm.xml.castor.Book" identity="isbn">
    <map-to table="dw_books"/>
    <field name="isbn" type="string">
      <sql name="isbn" type="varchar" />
    </field>
    <field name="title" type="string">
      <sql name="title" type="varchar" />
    </field>
  </class>

  <class name="ibm.xml.castor.Author" identity="id">
    <map-to table="dw_authors" />
    <field name="id" type="int">
      <sql name="id" type="integer" />
    </field>
    <field name="firstName" type="string">
      <sql name="first_name" type="varchar" />
    </field>
    <field name="lastName" type="string">
      <sql name="last_name" type="varchar" />
    </field>
  </class>
</mapping>

Nada disto é surpresa; o código simplesmente toma a classe Book e identifica a tabela onde este deve ser mapeado (dw_books) e como mapear as propriedades do objeto (isbn e title).

Definindo um relacionamento de muitos para muitos

Agora vem a parte interessante: informar ao Castor como os livros se relacionam com os autores. Lembre-se, o relacionamento funciona da seguinte maneira:

  • Cada livro contém um único ISBN.
  • Cada autor contém um único ID.
  • Quando um livro é escrito por um autor, uma entrada em dw_books_authors contém o ISBN do livro e o ID do autor.
  • Um livro pode ter vários autores (nesse caso, dw_books_authors contém várias entradas com o mesmo ISBN, mas com IDs de autores diferentes).
  • Um autor pode escrever vários livros (nesse caso, dw_books_authors contém várias entradas com o mesmo ID de autor, mas ISBNs diferentes).

Primeiro, examine essa relação a partir do lado da classe Book na equação. Em uma ocorrência de Book, você deseja preencher a propriedade authors com os autores para dito livro. O mesmo serve para o contrário. Se uma ocorrência de Book contém dados em sua propriedade authors, é necessário armazenar estes autores por meio do ID de cada autor. É necessário mapear a propriedade—authors—para entradas em dw_books_authors.

Para fazer isso funcionar, você começa com outro elemento field do Castor, como exibido na Listagem 11.


Listagem 11. Usando um elemento field para mapear autores para um array em Books
<field name="authors" type="ibm.xml.castor.Author"
       collection="arraylist">
</field>

Até aqui não temos nada de novo; você mapeia a propriedade authors, e dessa vez o tipo é uma classe, em vez de string ou int. Você usa collection="arraylist" para informar ao Castor que a propriedade é um conjunto e não um valor único.

Agora, porém, é necessário indicar o campo para armazenar o ID do autor, assim como em qual tabela o campo deve ser armazenado, pois o ID do autor nunca acaba na tabela dw_books. A Listagem 12 mostra como indicar o nome da tabela de muitos para muitos—neste caso, dw_books_authors—assim como a chave para o ISBN do livro nessa mesma tabela.


Listagem 12. O elemento sql define uma tabela de muitos e um relacionamento de muitos para muitos
<field name="authors" type="ibm.xml.castor.Author"
       collection="arraylist">
  <sql name="author_id"
       many-table="dw_books_authors"
       many-key="book_isbn" />
</field>

Trace essa lógica com atenção. Primeiro, lembre-se que este elemento trata de valores na propriedade authors das ocorrências de Book. O campo real sendo mapeado é uma instância de Author, e você deseja mapear a parte identificadora desse objeto—o id— para uma coluna chamada author_id. Entretanto, isso não é feito na tabela dw_books, assim, usa-se many-table para identificar que a tabela para onde o ID é mapeado é dw_books_authors. Por fim, o atributo many-key indica que o ISBN da ocorrência de Book também deve ser armazenado na sua tabela de muitos para muitos.

A Listagem 13 mostra o arquivo sql-mapping.xml com isso integrado no resto do arquivo.


Listagem 13. Adicionando suporte de muitos para muitos para Books
<mapping>
  <class name="ibm.xml.castor.Book" identity="isbn">
    <map-to table="dw_books"/>
    <field name="isbn" type="string">
      <sql name="isbn" type="varchar" />
    </field>
    <field name="title" type="string">
      <sql name="title" type="varchar" />
    </field>
    <field name="authors" type="ibm.xml.castor.Author"
           collection="arraylist">
      <sql name="author_id"
           many-table="dw_books_authors"
           many-key="book_isbn" />
    </field>
  </class>

  <class name="ibm.xml.castor.Author" identity="id">
    <map-to table="dw_authors" />
    <field name="id" type="int">
      <sql name="id" type="integer" />
    </field>
    <field name="firstName" type="string">
      <sql name="first_name" type="varchar" />
    </field>
    <field name="lastName" type="string">
      <sql name="last_name" type="varchar" />
    </field>
  </class>
</mapping>

Testando o mapeamento

A Listagem 14 mostra como revisar o programa SQLTester de modo que este crie um novo Author e, a seguir, um Book relacionado com este autor.


Listagem 14. Criando um novo autor e um novo livro
import java.util.Iterator;

import ibm.xml.castor.Author;
import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDOManager;

public class SQLTester {
  public static void main(String args[]) {
    try {
      JDOManager.loadConfiguration("jdo-conf.xml");
      JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

      Database database = jdoManager.getDatabase();
      database.begin();
      Author author = new Author(1001, "Joseph", "Conrad");
      Book book = new Book("1892295490", "Heart of Darkness", author);
      database.create(author);
      database.create(book);
      database.commit();

      database.begin();
      Book lookup = (Book)database.load(Book.class, "1892295490");
      System.out.println("Located book is named " + lookup.getTitle());
      System.out.println("Authors:");
      for (Iterator i = lookup.getAuthors().iterator(); i.hasNext(); ) {
        Author bookAuthor = (Author)i.next();
        System.out.println("  " + bookAuthor.getFirstName() + " " +
                                  bookAuthor.getLastName());
      }
      database.commit();
      database.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Isto é bem óbvio. Você se conecta ao banco de dados, cria um novo autor e um novo livro, e adiciona ambos ao banco de dados (fechando com commit()):

 Database database = jdoManager.getDatabase(); database.begin();
                Author author = new Author(1001, "Joseph", "Conrad"); Book book = new
                Book("1892295490", "Heart of Darkness", author); database.create(author);
                database.create(book); database.commit();

A seguir, verifica-se se os dados foram inseridos com sucesso.

Para simular melhor a persistência de dados, os dados são comprometidos e uma nova transação é iniciada (com o segundo database.begin(), após os dados de livro e do autor serem comprometidos). Isso garante que a versão local do Castor dos dados não seja usada, mas que o banco de dados seja de fato consultado na segunda metade do programa.

Verificando os dados

Dê uma olhada nos dados em suas tabelas para certificar-se que estes estão de acordo com suas expectativas. Você deverá ter algo semelhante aos dados na Tabela 3 da sua tabela dw_books.


Tabela 3. Dados em dw_books após a execução do SQLTester
isbntítulo
1892295490Heart of Darkness

A Tabela 4 mostra a tabela dw_authors após a inserção.


Tabela 4. Dados em dw_authors após executar o SQLTester
idfirst_namelast_name
1001JosephConrad

Por fim, a Tabela 5 mostra a junção entre um livro e seu autor, que, de várias formas, compreende os dados mais importantes que você já viu. Se autores e livros não podem ser relacionados, então nada disso é útil.


Tabela 5. A tabela de muitos para muitos dw_books_authors com dados a partir do SQLTester
book_isbnauthor_id
18922954901001

Excluindo os dados

A Listagem 15 é um pequeno programa utilitário que exclui os dados inseridos pelo SQLTester. Conforme você experimenta a ligação de dados SQL e adiciona livros e autores (o que deve com certeza fazer), é possível atualizar esta classe para remover essas entradas. Manter as classes separadas lhe dá uma chance de examinar o banco de dados entre inserções e exclusões, que é uma parte importante no aprendizado e depuração de quaisquer problemas que possam ocorrer.


Listagem 15. Excluindo os dados criados pelo SQLTester
import ibm.xml.castor.Author;
import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDOManager;

public class SQLClean {
  public static void main(String args[]) {
    try {
      JDOManager.loadConfiguration("jdo-conf.xml");
      JDOManager jdoManager = JDOManager.createInstance("bmclaugh");
      Database database = jdoManager.getDatabase();
      database.begin();
      try {
        Book book = (Book)database.load(Book.class, "1892295490");
        database.remove(book);
      } catch (org.exolab.castor.jdo.ObjectNotFoundException ignored) { }
      try {
        Author author = (Author)database.load(Author.class, 1001);
        database.remove(author);
      } catch (org.exolab.castor.jdo.ObjectNotFoundException ignored) { }
      database.commit();
      database.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

O programa conta com a manipulação de exceções aninhada para lidar com situações nas quais procura por dados inexistentes para excluir, o que o torna um pouco mais robusto.


O Castor não persiste o seu relacionamento por padrão

Um ponto interessante no SQLTester (na Listagem 14) é que ambas as ocorrências de Author e a ocorrência de Book são persistidas para o banco de dados. De fato, retirando um desses dois, irá obter um livro ou autor, mas não o outro, e não obterá quaisquer dados em dw_books_authors.

Para programadores Java, isto é de fato um pouco estranho. Se uma ocorrência de Book contém um Author, os dois não estão vinculados? É possível persistir um livro sem seu autor? Bem, no Castor sim, sendo este o comportamento padrão. Porém, se você deseja que o Castor siga em frente em todos os relacionamentos como esse, pode emitir o seguinte comando:

 database.setAutoStore(true);

É necessário fazer isso antes que qualquer transação seja criada, assim, a Listagem 16 trata dessa tarefa com uma versão um pouco diferente da Listagem 14.


Listagem 16. Programa de teste para o armazenamento automático de relacionamentos
import java.util.Iterator;

import ibm.xml.castor.Author;
import ibm.xml.castor.Book;

import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDOManager;

public class SQLTester {
  public static void main(String args[]) {
    try {
      JDOManager.loadConfiguration("jdo-conf.xml");
      JDOManager jdoManager = JDOManager.createInstance("bmclaugh");

      Database database = jdoManager.getDatabase();
      database.setAutoStore(true);
      database.begin();
      Author author = new Author(1001, "Joseph", "Conrad");
      Book book = new Book("1892295490", "Heart of Darkness", author);
      // We can persist just the book, and Castor will handle the author, as well
      // database.create(author);
      database.create(book);
      database.commit();

      database.begin();
      Book lookup = (Book)database.load(Book.class, "1892295490");
      System.out.println("Located book is named " + lookup.getTitle());
      System.out.println("Authors:");
      for (Iterator i = lookup.getAuthors().iterator(); i.hasNext(); ) {
        Author bookAuthor = (Author)i.next();
        System.out.println("  " + bookAuthor.getFirstName() + " " +
                                  bookAuthor.getLastName());
      }
      database.commit();
      database.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Experimente com isto (certifique-se de executar o SQLClean primeiro, caso ainda tenha dados no seu banco de dados), e você irá obter os mesmo resultados que antes—com exceção da chamada adicional database.create(). Embora isso seja apenas uma pequena melhora, considera adicionar centenas (ou milhares!) de livros e autores. Salvar o trabalho adicional é realmente importante.


Conclusão

Enquanto a ligação de dados XML está estabelecida e predominantemente está sendo acrescida em vez de alterada, JDO—tanto a versão da Sun quanto da Castor—ainda é uma API volátil. Porém, isto não significa que você deve evitá-la, pois a ligação de dados SQL e o JDO (de qualquer fornecedor) podem facilitar muito sua vida de programador. Use este artigo com um ponto de partida, e não como uma abordagem definitiva, para aprender sobre as tecnologias.

Experimente com a ligação de dados SQL e veja se ela pode ajudar o seu aplicativo (provavelmente irá). Em seguida, confira as versões da Sun e do Castor do JDO e veja o que acha delas. Finalmente, escolha uma delas para trabalhar. Mesmo que a versão do Castor não seja padrão, ela é mais flexível, e com o seu trabalho para se envolver com a Sun, o padrão oficial pode incorporar muitos recursos do Castor no futuro.

E o mais importante, melhore suas habilidades de programação. Aprenda como a ligação de dados SQL pode lhe ajudar, economize esforço e, o principal, aumente a qualidade do seu trabalho e dos aplicativos que desenvolve. Experimente usar as ligações de dados SQL e XML com o mesmo aplicativo para entender como o mesmo tipo de mapeamento é usado nas duas ligações. Você irá se beneficiar com isso, e provavelmente irá se livrar quase completamente do JDBC, e ninguém vai dizer que isso não é bom.



Downloads

DescriçãoNomeTamanhoMétodo de download
Java source codejavaSourceCode.zip3KBHTTP
Castor configuration filescastorConfigurationFiles.zip1KBHTTP

Informações sobre métodos de download


Recursos

Aprender

  • Data binding with Castor, Part 1: Install and set up Castor (Brett McLaughlin, developerWorks, novembro de 2007): No primeiro artigo da série, são abordados os primeiros passos para executar o Castor no seu equipamento, incluindo download, instalação, configuração, problemas de caminhos de classe, entre outros.

  • Data binding with Castor, Part 2: Marshall and unmarshall XML (Brett McLaughlin, developerWorks, dezembro de 2007): Converta suas classes Java para XML e converta este XML de volta em código Java. Além disso, aprenda como o Castor projeta e trabalha com suas classes para que essas funcionem com a API.

  • Data binding with Castor, Part 3: Map between schemas (Brett McLaughlin, developerWorks, janeiro de 2008): Converta dados em um inconveniente documento XML para os seus objetos Java personalizados usando o Castor. Você não terá mais restrições de nomes de elementos no seu documento XML, ou de nomes de variáveis de membros em suas classes Java.

  • O Web site do Castor: Visite o hub on-line para saber tudo sobre o Castor.

  • Classes do Castor: Leia o JavaDoc.

  • Introdução ao JDO do Castor: Uma ótima introdução para este mapeamento relacional de objetos e estrutura de ligação de dados.

  • Página dos Java Data Objects (JDO) da Sun: Visite o local principal para aprender sobre a versão oficial do JDO.

  • JSR 12: Leia a especificação que define o JDO 1.0, os Java Data Objects originais.

  • JSR 243: Aprenda sobre esta especificação para o JDO 2.0 e os esforços para facilitar o uso do JDO, padronizar o suporte ao banco de dados do JDO e expandir seu escopo.

  • Get started with Castor JDO (Bruce Snyder, developerWorks, agosto de 2002): Leia este antigo artigo do developerWorks. Parte da linguagem específica deste artigo está desatualizada, mas os conceitos ainda são válidos.

  • Practical data binding (Brett McLaughlin, developerWorks, maio de 2004): Comece com o artigo introdutório de uma série de várias partes para aprender mais sobre a API de ligação de dados da SUN, a JAXB.

  • Certificação XML da IBM: Descubra como se tornar um Desenvolvedor Certificado pela IBM em XML e tecnologias relacionadas.

  • Biblioteca técnica de XML: Veja na Zona de XML do developerWorks uma grande variedade de artigos técnicos e dicas, tutoriais, padrões e Redbooks da IBM.

  • Zona de XML do developerWorks: Saiba tudo sobre XML.

  • Eventos técnicos e webcasts do developerWorks: Fique atualizado sobre a tecnologia por meio dessas sessões.

  • Podcasts: Sintonize-se e informe-se com os especialistas técnicos da IBM.

Obter produtos e tecnologias

  • Driver JDBC para MySQL: Faça o download e aprenda sobre este driver JDBC Java original em MySQL.com.

  • Java and XML, Third Edition (Brett McLaughlin e Justin Edelson, O'Reilly Media, Inc.): Aprenda tudo sobre XML, do começo ao fim, incluindo informações extensivas sobre ligação de dados e mapeamento.

  • Java and XML Data Binding (Brett McLaughlin, O'Reilly Media, Inc.): Neste antigo livro, encontre detalhes sobre o Castor e os conceitos envolvidos na ligação de dados.

  • Castor Professional Services: Procurando suporte ou ajuda pagos para o Castor? Confira os serviços profissionais do Castor.

  • DB2 Express-C: Faça o download desta versão sem custos do DB2, ótima para experimentar o JDO. O banco de dados IMB DB2 é um banco de dados SQL que funciona muito bem com o JDO do Castor, assim como com o JDO padrão da Sun.

  • IBM Informix: Confira uma linha de produtos que oferece produtos de servidores de banco de dados de força industrial.

  • Drivers JDBC para DB2 e Informix: Experimente este pacote de drivers da DataDirect conveniente e de fácil download.

  • Software de teste IBM Elabore seu próximo projeto de desenvolvimento com o software de teste IBM, disponível para download diretamente no developerWorks.

Discutir

Sobre o autor

Photo of Brett McLaughlin

Brett McLaughlin é um autor de não ficção premiado e campeão de vendas. Seus livros sobre programação de computadores, home theater e análise e design já venderam mais de 100.000 cópias. Há quase 10 anos, ele escreve, edita e produz livros técnicos, e sente-se confortável tanto na frente de um processador de texto quanto tocando violão, correndo pela casa atrás dos seus dois filhos ou assistindo reprises de Arrested Development (Caindo na Real, no Brasil) com sua esposa. Seu último livro, Head First Object Oriented Analysis and Design, ganhou o prêmio Jolt Technical Book 2007. Além disso, seu clássico Java and XML continua sendo um dos trabalhos definitivos sobre o uso de tecnologias XML em linguagem Java.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=WebSphere, Tecnologia Java
ArticleID=483008
ArticleTitle=Ligação de dados com o Castor, Parte 4: Ligue seus objetos Java com bancos de dados SQL
publish-date=04152010
author1-email=brett@newInstance.com
author1-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).