• Nenhum resultado encontrado

Analisando a performance das Estratégias que realizam o Mapeamento Objeto Relacional no JPA

N/A
N/A
Protected

Academic year: 2021

Share "Analisando a performance das Estratégias que realizam o Mapeamento Objeto Relacional no JPA"

Copied!
12
0
0

Texto

(1)

Douglas Rocha Mendes

concluiu o curso de Bacharelado em Informática pela Universidade Positivo em 1996. Concluiu o mestrado em Telemática na Universidade Federal Tecnológica do Paraná em 2002. No mesmo ano, publicou o artigo Bandwidth Fairness of a Single Rate Three Color Marker Algorithm Implementation no congresso internacional – 8th IEEE International Conference on Communication Systems (ICCS 2002). Em julho de 2007, publicou o livro Redes de Computadores – Teoria e Prática pela Editora Novatec. Em fevereiro de 2009 publicou o livro Programação Java com Ênfase em Orientação a Objetos. Trabalha com programação Java desde 2000. Atualmente está trabalhando na COPEL como analista de sistemas, desenvolvendo sistemas Java na plataforma J2EE, como também ministra aulas nas faculdades SPEI e Expoente. É professor da pós-graduação em Engenharia de Software da UFPR e de cursos de extensão da Universidade Positivo. Pode ser contatado pelo e-mail: (douglas.mendes@copel.com).

O artigo proposto descreve sobre a performance das três estratégias para mapear uma hierarquia de classes do modelo orientado a objetos para o modelo relacional. Será dado ênfase aos pontos positivos e negativos de cada uma das estratégias de mapeamento como também será apresentada uma análise de performance de cada uma das estratégias de mapeamento. Iremos dar ênfase nas operações de inserção, seleção e remoção de dados. Os testes de performance foram executados com o auxílio do framework JUnit e ainda foram utilizados os bancos de dados HSQLDB v. 1.69, FireBird v. 2.0 e MySQL v. 5.1. Estes testes podem ser baixados do site da revista e ser novamente executados em qualquer outro banco de dados. A ideia é apresentar inicialmente um estudo realizado, porém novos testes poderão ser executados a fim de ajudar no dia-a-dia de administradores de banco de dados como também de desenvolvedores e analistas da plataforma Java.

Analisando a performance das Estratégias que

realizam o Mapeamento Objeto Relacional no JPA

Analisando a performance das estratégias do

mapeamento objeto relacional na prática

(2)

Q

uando desenvolvemos sistemas orientados a objetos e usamos o JDBC para a persistência dos dados, utilizamos consultas no formato da linguagem SQL, que são executadas diretamente no banco de dados. Apesar de a linguagem SQL já ter sido exaustivamente explorada, esta possui algumas particularidades que muitas vezes impac-tam na produtividade do desenvolvimento de um software, principalmen-te quando a equipe de desenvolvimento está iniciando nesta principalmen-tecnologia. Durante um projeto orientado a objetos é muito comum usarmos a lingua-gem SQL e realizarmos o mapeamento objeto relacional manualmente, ou seja, o analista e o programador juntos definem os modelos de classes e dados e ainda juntos formalizam como o acesso a estes dados deve ocorrer. Desta forma, não existe garantia que o acesso definido irá usufruir dos melhores métodos, causando muitas vezes a perda de performance e qualidade no acesso aos dados.

Com o advento dos frameworks, algumas novidades foram disponibili-zadas em relação ao mapeamento objeto relacional, sendo a principal delas que o mapeamento objeto relacional ocorre de forma automática. Os frameworks oferecem uma maior facilidade ao programador no momen-to de gravar, recuperar, remover ou atualizar dados no banco de dados. Desta forma, o programador consegue gravar ou acessar um objeto Java sem a necessidade de montar complexos comandos SQL, ou seja, todo mapeamento objeto relacional ocorre de forma automática. Um simples comando emitido pelo framework permite que todo o conteúdo de um conjunto de tabelas seja associado a um objeto Java, sendo que toda a complexidade gerada para este acesso fique abstraída pelo framework. É importante observar que as consultas continuam sendo executadas pela API JDBC através da linguagem SQL, porém o framework abstrai toda esta complexidade do programador. Esta abstração é que agrega produtivida-de no produtivida-desenvolvimento produtivida-de um software.

Neste artigo iremos abordar sobre uma importante característica oferecida pelos frameworks de mapeamento objeto-relacional, mais especificamen-te, iremos apresentar detalhadamente todos os elementos envolvidos e necessários para o mapeamento de uma hierarquia de classes dispostas em uma herança para uma ou mais tabelas. No exemplo apresentado, iremos considerar todas as estratégias possíveis de herança presentes no framework JPA. O JPA (Java Persistence API) representa uma especificação padrão para o gerenciamento de persistência e mapeamento objeto rela-cional (ORM).

Ainda neste artigo iremos apresentar a performance de cada uma das estratégias de herança, levando em consideração as operações de inser-ção, seleção e remoção de dados. Estes testes irão ocorrer nos bancos de dados HSQLDB, FireBird e MySQL. A ideia será permitir ao leitor escolher qual a melhor estratégia, levando em consideração a sua performance e o banco de dados utilizado. Todos os testes executados neste artigo podem ser estendidos a outros bancos de dados, bastando apenas que o leitor configure alguns arquivos XML. Será disponibilizado neste artigo como proceder os testes em outros banco de dados.

Assim, para introduzir este importante assunto, iremos comentar sobre alguns conceitos presentes neste contexto, tais como: conceito de heran-ça, conceito de polimorfismo, consultas polimórficas, as estratégias de herança SINGLE_TABLE, TABLE_PER_CLASS e JOINED. Desta forma, iremos buscar oferecer ao leitor informações para que este possa tomar a melhor decisão em relação a qual das estratégias de herança usar no seu projeto.

Herança

O conceito de herança está fundamentado na definição de uma classe com base em outra. A classe usada como referencial pode ser chamada de super-classe, classe mãe, classe-base ou generalização. A nova classe criada a partir de outra passa a ser uma subclasse, classe-filha, classe derivada ou especiali-zação. Podemos redefinir métodos e criar novos atributos na subclasse. A im-plementação de herança em Java é realizada inserindo-se a palavra extends seguida do nome da superclasse após a definição da subclasse.

Neste artigo, iremos utilizar como exemplo três hierarquias de classes, sendo uma para cada estratégia de mapeamento, ou seja, teremos uma hierarquia de classes para as estratégias SINGLE_TABLE, TABLE_PER_CLASS e JOINED. A figura 1 apresenta o diagrama de classes utilizado para o artigo. Para mais detalhes sobre o conceito de herança como também outros conceitos de orientação a objetos, buscar no livro Programação Java com Ênfase em Orientação a Objetos. Neste livro, são apresentadas todas as particularidades do conceito de herança como também inúmeros exemplos práticos. A seguir, iremos descrever sobre o conceito de polimorfismo e consultas polimórficas. Estes dois conceitos são extensivamente utilizados na manipulação de obje-tos como também estão presente nas consultas ao banco de dados.

'JHVSB&YFNQMP)JFSBSRVJBEFDMBTTFTEPFYFNQMPVUJMJ[BEP

Polimorfismo

O termo polimorfismo é originário do grego e significa “muitas formas”: poli significa muitas e morphos significa formas. Este representa um dos mais importantes conceitos da orientação a objetos e pode ser utilizado junto com outros conceitos conhecidos, tais como: herança, classes abstratas e interfaces. O seu uso ocorre de forma frequente em programas Java, como também na recuperação de dados através das consultas polimórficas no JPA.

Consulta polimórfica

Uma consulta polimórfica permite a extração de dados de tabelas que foram definidas em uma hierarquia de herança, ou seja, ao selecionar um objeto da tabela PessoaFisicaJoined, por exemplo, todas as outras tabelas da hierarquia conectadas a esta (PessoaJoined e AutorJoined) serão envolvidas na consulta,

(3)

Single_Table

O objetivo desta consulta SQL foi mostrar o uso do join entre as tabelas da hierarquia. Ou seja, apesar de a consulta formalizar que os dados devem ser obtidos da tabela PessoaFisicaJoined, as outras tabelas conectadas

Nesta estratégia, todas as entidades em uma hierarquia de classes são mapeadas para uma única tabela. A figura 2 apresenta o modelo de enti-dade e relacionamento utilizado pela estratégia SINGLE_TABLE.

'JHVSB&YFNQMPNPEFMPFOUJEBEFSFMBDJPOBNFOUPEBFTUSBUÏHJB4*/(-&@5"#-&

Para formalizar o uso desta estratégia, anotamos a classe com a annotation @ Inheritance e informamos que o tipo da herança é SINGLE_TABLE. Vejamos um exemplo: @Inheritance (strategy = InheritanceType.SINGLE_TABLE). A annota-tion @Inheritance e o atributo InheritanceType.SINGLE_TABLE são utilizados para definir a estratégia do relacionamento de herança.

Nesta estratégia, devemos também informar uma coluna discriminadora que será utilizada para diferenciar os objetos que são mapeados para as linhas nessa tabela. Na superclasse, devemos anotar a classe com a annotation @ DiscriminatorColumn. Esta annotation define o nome e o tipo da coluna que será criada na tabela. Vejamos um exemplo: @DiscriminatorColumn (name = "DISCRIMINATOR" , discriminatorType = DiscriminatorType.STRING).

Neste exemplo, formalizamos que o tipo da coluna discriminadora será string e o nome dela será DISCRIMINATOR (poderia ter qualquer outro nome). Para completar a formalização do uso desta estratégia, devemos informar qual o conteúdo da coluna discriminadora. Para isso, usamos a annotation @DiscriminatorValue. Esta annotation define o conteúdo a ser inserido na coluna DISCRIMINATOR criada, ou seja, dentro dos parênteses informamos o conteúdo desta coluna. Vejamos um exemplo: @DiscriminatorValue("PessoaF isica"). É importante observar que todas as classes que compõem a hierarquia deverão também ser anotadas com a annotation @DiscriminatorValue e um valor diferente deve ser informado entre as aspas duplas.

Toda esta formalidade nas classes serve para que as linhas gravadas na tabela sejam posteriormente identificadas, ou seja, se a linha gravada for do tipo da classe PessoaFisica, a coluna DISCRIMINATOR terá este conteúdo. Vejamos na figura 3 um exemplo dos dados gravados na tabela PessoaST. Na coluna DISCRIMINATOR, temos o nome de cada objeto gravado.

afim de retornar o objeto requisitado. Quando informamos um identificador para recuperar um objeto este poderá ser de qualquer um dos tipos da hierar-quia, logo o JPA irá realizar uma busca em todas as tabelas da hierarhierar-quia, seja uma superclasse ou subclasse. Vejamos um exemplo com a consulta: select pessoa from PessoaFisicaJoined pessoa where pessoa.cpf=:cpf.

Esta consulta, após ser convertida para o formato do JPA, irá formalizar que existe um inner join com a tabela PessoaJoined e um left outer join com a tabela AutorJoined. Isto ocorre devido a estas duas tabelas estarem associa-das à tabela PessoaFisicaJoined através da hierarquia de herança. As tabelas PessoaJuridicaJoined e EditoraJoined não serão envolvidas na cláusula SQL por pertencerem a uma segunda parte da hierarquia. A figura 1 esclarece a hierarquia de classes e a figura 5 apresenta o modelo de entidade e relaciona-mento. Ou seja, independentemente do objeto a ser recuperado, uma conexão (join) entre as tabelas sempre vai ocorrer. Esta conexão será um inner join caso a classe seja uma superclasse da tabela requisitada ou um left outer join caso a classe seja uma subclasse da tabela requisitada. A seguir, apresentamos a cláusula SQL original gerada pelo JPA:

através de herança também serão envolvidas. Porém esta consulta SQL varia entre as estratégias disponíveis. A seguir, iremos apresentar deta-lhadamente cada uma das estratégias, como também a performance de cada uma delas.

SELECT pessoafisi0_.id as id38_, pessoafisi0_1_.dataCadastro as dataCada2_38_, pessoafisi0_1_.matricula as matricula38_, pessoafisi0_1_.dataBloqueio as dataBloq4_38_, pessoafisi0_1_.contaAcesso as contaAce5_38_, pessoafisi0_1_.senha as senha38_, pessoafisi0_1_.id_endereco as id8_38_, pessoafisi0_1_.nome as nome38_, pessoafisi0_.rg as rg39_, pessoafisi0_.cpf as cpf39_, pessoafisi0_.especialidade as especial4_39_, pessoafisi0_.dtNasc as dtNasc39_, pessoafisi0_2_.qdadeLivrosPublicados as qdadeLiv2_40_, pessoafisi0_2_.descUltimoLivro as descUlti3_40_, pessoafisi0_2_.qdadePaginasUltLivro as qdadePag4_40_, case

when pessoafisi0_2_.id is not null then 2

when pessoafisi0_.id is not null then 1 end as clazz_ FROM

PessoaFisicaJoined pessoafisi0_

inner join PessoaJoined pessoafisi0_1_ on pessoafisi0_.id=pessoafisi0_1_.id

left outer join AutorJoined pessoafisi0_2_ on pessoafisi0_.id=pessoafisi0_2_.id

(4)

'JHVSB&YFNQMPGSBHNFOUPEBUBCFMBTFHVJOEPBFTUSBUÏHJB4*/(-&@5"#-&

Nesta estratégia, temos uma única tabela para acomodar todos os atri-butos de todas as classes envolvidas na hierarquia. Isto implica em ter colunas não sendo utilizadas, dependendo do objeto gravado.

As listagens de programa 1, 2, 3, 4 e 5 apresentam os programas utiliza-dos neste artigo para a estratégia SINGLE_TABLE. Iremos apresentar um fragmento do código sendo que o código completo poderá ser baixado do site da revista.

Esta estratégia traz facilidades como também dificuldades. A seguir, iremos apresentar os pontos positivos e negativos da estratégia SIN-GLE_TABLE.

Pontos positivos

Pontos negativos

Como pontos positivos, podemos citar:

t PNBQFBNFOUPVTBOEPBFTUSBUÏHJBEF4*/(-&@5"#-&ÏBFTUSBUÏ-gia mais simples para implementar;

t UFNPTBQFOBTVNBÞOJDBUBCFMBQBSBBENJOJTUSBS

t P+1"OÍPQSFDJTBGB[FSDPNQMFYPTKPJOT PVUFSKPJO VOJPOTPVTVC-selects para carregar os dados da tabela ou dados que tenham uma associação através de polimorfismo. Isto ocorre devido aos dados serem gravados na mesma tabela;

t DPNVNÞOJDPTFMFDU SFUPSOBNPTUPEPTPTEBEPT t TVQPSUFBQPMJNPSmTNP

Como pontos negativos, podemos citar:

t BTUBCFMBTJSÍPDPOUFSVNOÞNFSPHSBOEFEFDPMVOBT*NBHJOFNRVF todos os atributos das classes Usuario, PessoaST, PessoaFisicaST, Pessoa-JuridicaST, AutorST e EditoraST serão gravados em uma única tabela. Isto pode causar um problema de gestão na tabela ou ainda muita confusão; t BMHVNBTDPMVOBTOÍPTÍPQSFFODIJEBT"TTJNBPJOTFSJSEBEPTBMHVNBT

colunas ficam com valor null, causando desperdício de espaço em disco; t BUBCFMBQPEFUPSOBSTFJNFOTB FTQFDJBMNFOUFRVBOEPBIJFSBSRVJBGPS

profunda;

t OÍPÏQPTTÓWFMEFmOJSVNBDPMVOBDPNPOPUOVMM"TTJNUPEBTBTDPMVOBT devem ser criadas como nullable;

t FTUB FTUSBUÏHJB HFSB VNB UBCFMB OÍP OPSNBMJ[BEB " OPSNBMJ[BÎÍP GPJ totalmente sacrificada nesta estratégia. Manutenções em sistemas que usam esta estratégia tornam-se bem mais complexas.

@Entity

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name = “DISCRIMINATOR”, discriminatorType = DiscriminatorType.STRING)

@DiscriminatorValue(“Pessoa”)

publicabstractclass PessoaST extends Usuario implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privateint id; private String nome; private Endereco endereco; //getters e setters omitidos

}

Listagem 1. Classe PessoaST. Implementando a estratégia SINGLE_TABLE

@Entity

@DiscriminatorValue(“PessoaFisica”)

publicclass PessoaFisicaST extends PessoaST implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privatelong rg; privatelong cpf;

private String especialidade; private Date dtNasc; //getters e setters omitidos

}

Listagem 2. Classe PessoaFisicaST. Implementando a estratégia SINGLE_TABLE.

@Entity

@DiscriminatorValue(“PessoaJuridica”)

publicclass PessoaJuridicaST extends PessoaST implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privatelong cnpj;

private String nomeFantasia; private String razaoSocial; private Date dtFundacao; //getters e setters omitidos

}

Listagem 3. Classe PessoaJuridicaST. Implementando a estratégia SINGLE_TABLE.

@Entity

@DiscriminatorValue(“Autor”)

publicclass AutorST extends PessoaFisicaST implements Serializable { privateint qdadeLivrosPublicados;

private String descUltimoLivro; privateint qdadePaginasUltLivro; //getters e setters omitidos

}

Listagem 4. Classe AutorST. Implementando a estratégia SINGLE_TABLE.

@Entity

@DiscriminatorValue(“Editora”)

publicclass EditoraST extends PessoaJuridicaST implements Serializable { privateint qdadeFuncionarios;

private String areaEspecializacao; privateint qdadeLivrosEstoque; //getters e setters omitidos

}

(5)

Consulta gerada para select na estratégia

SINGLE_TABLE

Cláusula SQL gerada para insert na

estratégia SINGLE_TABLE

TABLE_PER_CLASS

Quando dizemos que o acesso aos dados na estratégia SINGLE_TABLE é simples é devido à cláusula SQL utilizada não necessitar de join, union ou subselects para este acesso. Quando selecionamos dados por padrão, usamos o comando select, sendo que no JPA não é diferente. Porém o comando select utilizado é remontado internamente e o resultado analisado difere um pouco do que estamos acostumados em utilizar. Vejamos o comando select gerado pelo JPA no seu formato original:

Conforme podemos observar, o comando select sempre irá considerar na cláusula where o nome do objeto e a chave para o acesso. Neste exem-plo, formalizamos que recuperamos um objeto do tipo Editora. No caso da tabela Endereco, como esta não implementa nenhuma estratégia o acesso a suas colunas segue um filtro tradicional, ou seja, apenas usamos a chave primária para recuperar o registro. A tabela Endereco possui um relacionamento @OneToOne com a tabela PessoaST.

O comando insert nesta estratégia é formalizado pelo uso do nome do obje-to na coluna DICRIMINATOR. Vejamos o comando gerado para inserir dados:

Conforme podemos observar, a tabela que concentra todos os atributos é a tabela PessoaST. Neste exemplo, inserimos um objeto do tipo da classe EditoraST. Onde aparece o símbolo de ?, indica que um parâmetro com valor dinâmico será utilizado.

Com essa estratégia, todas as subclasses são mapeadas para uma tabela no banco de dados. Neste exemplo, teremos uma tabela para cada classe exceto para a classe PessoaTPC que representa a superclasse. Cada ta-bela irá possuir os seus atributos e uma cópia de todos os atributos da sua superclasse. Para verificar esta situação, basta acessar as tabelas e conferir as suas colunas. A figura 4 apresenta o modelo de entidade e relacionamento da estratégia TABLE_PER_CLASS.

Figura 4. Exemplo: modelo entidade relacionamento da estratégia.

TABLE_Para formalizarmos o uso desta estratégia, devemos anotar a classe com a annotation @Inheritance e no atributo strategy informar TABLE_PER_CLASS. Vejamos um exemplo: @Inheritance(strategy=Inher itanceType.TABLE_PER_CLASS).

É importante observar que esta estratégia redefine os atributos da su-perclasse nas tabelas que representam as subclasses. Como diferença entre as estratégias SINGLE_TABLE e TABLE_PER_CLASS temos que na estratégia TABLE_PER_CLASS não precisamos definir uma coluna para representar o discriminator. Nesta estratégia, cada nova tabela terá uma chave (id) e os atributos da superclasse. As listagens de programa 6, 7, 8, 9 e 10 apresentam os programas utilizados neste artigo para a estratégia TABLE_PER_CLASS. Iremos apresentar um fragmento do código sendo que o código completo poderá ser baixado do site da revista.

select

editorast0_.id as id43_, editorast0_.dataCadastro as dataCada3_43_, editorast0_.matricula as matricula43_, editorast0_.dataBlo-queio as dataBloq5_43_, editorast0_.contaAcesso as contaAce6_43_, editorast0_.senha as senha43_, editorast0_.id_endereco as id23_43_, editorast0_.nome as nome43_, editorast0_.razaoSocial as razaoSo16_43_, editorast0_.cnpj as cnpj43_,

editorast0_.nomeFan-tasia as nomeFan18_43_, editorast0_.dtFundacao as

dtFundacao43_, editorast0_.qdadeFuncionarios as qdadeFu20_43_, editorast0_.areaEspecializacao as areaEsp21_43_, editorast0_.qdadeLi-vrosEstoque as qdadeLi22_43_

from PessoaST editorast0_

where editorast0_.DISCRIMINATOR='Editora' and editorast0_.cnpj=?

select

endereco0_.idEndereco as idEndereco37_0_, endereco0_.rua as rua37_0_, endereco0_.cidade as cidade37_0_, endereco0_.estado as estado37_0_, endereco0_.complemento as compleme5_37_0_ from Endereco endereco0_

where endereco0_.idEndereco=?

insert into PessoaST

(dataCadastro, matricula, dataBloqueio, contaAcesso, senha, id_endere-co, nome, razaoSocial, cnpj, nomeFantasia, dtFundacao, qdadeFuncionarios, areaEspecializacao, qdadeLivrosEstoque, DISCRI-MINATOR, id)

values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'Editora', ?).

@Entity

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

publicabstractclass PessoaTPC extends Usuario implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privateint id; private String nome; private Endereco endereco; //getters e setters omitidos

}

(6)

Esta estratégia traz facilidades como também dificuldades. A seguir iremos apresentar os pontos positivos e negativos da estratégia TA-BLE_PER_CLASS.

Pontos positivos

Pontos negativos

Como pontos positivos, podemos citar: t UFSDPMVOBTOPUOVMM

t PGFSFDFS VN NFMIPS TVQPSUF BP NBQFBNFOUP EF UBCFMBT QFSUFO-centes ao legado. Pois como as tabelas são independentes umas das outras, o relacionamento com o legado pode ser realizado.

Como pontos negativos, podemos citar:

t QBSBSFDVQFSBSEBEPTEBTUBCFMBTRVFSFQSFTFOUBNBTVQFSDMBTTF ou subclasse, é necessário utilizar subselects e/ou unions; t FTUBFTUSBUÏHJBUBNCÏNHFSBUBCFMBTOÍPOPSNBMJ[BEBT EFWJEPËT

colunas da superclasse serem redundantes nas tabelas que repre-sentam as subclasses;

t QPSFYJHJSPVTPEFVOJPOFTVCTFMFDUTOBTDPOTVMUBT PUFNQPQBSBB recuperação de um grande volume de dados pode ficar impraticá-vel dependendo do banco de dados e também da posição da classe dentro da hierarquia. Neste artigo, iremos apresentar a performan-ce desta estratégia em três diferentes bancos de dados.

Consulta SQL gerada para select na

estratégia TABLE_PER_CLASS

Quando selecionamos dados na estratégia TABLE_PER_CLASS, rea-lizamos a pesquisa diretamente na tabela a ser analisada. Conforme podemos notar neste exemplo fizemos um select na tabela AutorTPC, levando em consideração que todas as colunas da tabela AutorTPC, PessoaFisicaTPC, PessoaTPC e Usuário serão recuperadas.

No caso da tabela AutorTPC, o select ficou simples, pois é a última classe da hierarquia, porém com a classe PessoFisicaTPC algumas novidades serão apresentadas. A tabela PessoFisicaTPC está situada no meio da hierarquia das classes. Por isso, o select ficará mais complexo. Vejamos um exemplo:

Conforme podemos observar, esta cláusula SQL é bem mais complexa que as consultas utilizadas pela estratégia SINGLE_TABLE. Nesta consul-ta, temos o uso de subselect e union. Devido à inserção destes coman-dos, a performance desta estratégia tende a ficar pior dependendo da operação (inserção, seleção ou remoção) e do banco de dados utilizado. Para mais detalhes sobre a performance desta estratégia, analisar os quadros comparativos a seguir.

select

pessoafisi0_.id as id44_, pessoafisi0_.dataCadastro as dataCada2_44_, pessoafisi0_.matricula as matricula44_, pessoafisi0_.dataBloqueio as dataBloq4_44_, pessoafisi0_.contaAcesso as contaAce5_44_, pesso-afisi0_.senha as senha44_, pessoafisi0_.id_endereco as id8_44_, pes-soafisi0_.nome as nome44_, pessoafisi0_.rg as rg45_, pessoafisi0_.cpf @Entity

publicclass PessoaFisicaTPC extends PessoaTPC implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privatelong rg; privatelong cpf;

private String especialidade; private Date dtNasc; //getters e setters omitidos

}

Listagem 7. Classe PessoaFisicaTPC. Implementando a estratégia TABLE_PER_CLASS.

@Entity

publicclass PessoaJuridicaTPC extends PessoaTPC implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privatelong cnpj;

private String nomeFantasia; private String razaoSocial; private Date dtFundacao; //getters e setters omitidos

}

Listagem 8. Classe PessoaJuridicaTPC. Implementando a estratégia TABLE_PER_CLASS.

@Entity

publicclass AutorTPC extends PessoaFisicaTPC implements Serializable { privateint qdadeLivrosPublicados;

private String descUltimoLivro; privateint qdadePaginasUltLivro; //getters e setters omitidos

}

Listagem 9. Classe AutorTPC. Implementando a estratégia TABLE_ PER_CLASS.

@Entity

publicclass EditoraTPC extends PessoaJuridicaTPC implements Serializable { privateint qdadeFuncionarios;

private String areaEspecializacao; privateint qdadeLivrosEstoque; //getters e setters omitidos

}

Listagem 10. Classe EditoraTPC. Implementando a estratégia TABLE_ PER_CLASS.

select

autortpc0_.id as id44_, autortpc0_.dataCadastro as dataCada2_44_, autortpc0_.matricula as matricula44_, autortpc0_.dataBloqueio as da-taBloq4_44_, autortpc0_.contaAcesso as contaAce5_44_, autortpc0_. senha as senha44_, autortpc0_.id_endereco as id8_44_, autortpc0_. nome as nome44_, autortpc0_.rg as rg45_, autortpc0_.cpf as cpf45_, autortpc0_.especialidade as especial3_45_, autortpc0_.dtNasc as dtNasc45_, autortpc0_.qdadeLivrosPublicados as qdadeLiv1_46_, autortpc0_.descUltimoLivro as descUlti2_46_, autortpc0_.qdadePagina-sUltLivro as qdadePag3_46_

from AutorTPC autortpc0_ where autortpc0_.cpf=?

(7)

Cláusula SQL gerada para insert na

estratégia TABLE_PER_CLASS

JOINED

Na estratégia TABLE_PER_CLASS, o comando insert é simples não sendo necessário inserir nenhum campo para a identificação do objeto. Cada objeto é identificado apenas pela chave primária. Vejamos um exemplo:

Neste exemplo, inserimos um objeto do tipo da classe EditoraTPC. Onde aparece o símbolo de ?, indica que um parâmetro com valor dinâmico será utilizado.

Figura 5. Exemplo: modelo entidade relacionamento da estratégia.

Na estratégia JOINED será criada uma tabela para cada classe presente no modelo de classes. Assim, não teremos a redefinição de atributos da superclasse em subclasses. A figura 5 apresenta o modelo de entidades e relacionamento da estratégia JOINED.

Para formalizarmos o uso desta estratégia, devemos anotar a classe com a annotation @Inheritance e no atributo strategy informar JOINED.

as cpf45_, pessoafisi0_.especialidade as especial3_45_, pessoafisi0_. dtNasc as dtNasc45_, pessoafisi0_.qdadeLivrosPublicados as qdade-Liv1_46_, pessoafisi0_.descUltimoLivro as descUlti2_46_, pessoafisi0_. qdadePaginasUltLivro as qdadePag3_46_, pessoafisi0_.clazz_ as clazz_ from ( select

rg, id_endereco, senha, null as qdadeLivrosPublicados, matricula, id, null as descUltimoLivro, null

as qdadePaginasUltLivro, dtNasc, contaAcesso, dataCadastro, dataBlo-queio, nome, cpf,

especialidade, 1 as clazz_

from PessoaFisicaTPC union select

rg, id_endereco, senha, qdadeLivrosPublicados, matricula, id, descUltimoLivro,

qdadePaginasUltLivro, dtNasc, contaAcesso, dataCadastro, dataBloqueio, nome, cpf,

especialidade, 2 as clazz_ from AutorTPC ) pessoafisi0_ where pessoafisi0_.cpf=?

Vejamos um exemplo: @Inheritance(strategy=InheritanceType.JOINED). É importante observar que esta estratégia não redefine os atributos da superclasse nas tabelas que representam as subclasses. Outro ponto im-portante desta estratégia é a necessidade de definir explicitamente nas subclasses qual é o atributo da superclasse que representa a chave pri-mária. Para isso, usamos a annotation @PrimaryKeyJoinColumn. Vejamos um exemplo @PrimaryKeyJoinColumn(referencedColumnName = "id"). No atributo referencedColumnName, informamos o nome da coluna do banco de dados que representa a chave primária. No nosso exemplo, esta é a coluna id da classe PessoaJoined.

As listagens de programa 11, 12, 13, 14 e 15 apresentam os programas utilizados neste artigo para a estratégia JOINED. Iremos apresentar um fragmento do código sendo que o código completo poderá ser baixado do site da revista.

insert into EditoraTPC

(dataCadastro, matricula, dataBloqueio, contaAcesso, senha, id_endere-co, nome, razaoSocial, cnpj, nomeFantasia, dtFundacao, qdadeFuncionarios, areaEspecializacao, qdadeLivrosEstoque, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).

@Entity

@Inheritance(strategy = InheritanceType.JOINED)

@AttributeOverride(name=”senha”, column=@

Column(name=”password”))

publicabstractclass PessoaJoined extends Usuario implements Serializable { privatestaticfinallong serialVersionUID = 1L;

privateint id; private String nome; private Endereco endereco; //getters e setters omitidos

}

Listagem 11. Classe PessoaJoined. Implementando a estratégia JOINED.

@Entity

@PrimaryKeyJoinColumn (referencedColumnName=”id”)

publicclass PessoaFisicaJoined extends PessoaJoined implements Serializable {

privatestaticfinallong serialVersionUID = 1L; privatelong rg;

privatelong cpf;

private String especialidade; private Date dtNasc; //getters e setters omitidos

}

(8)

Esta estratégia traz facilidades como também dificuldades. A seguir, iremos apresentar os pontos positivos e negativos da estratégia JOINED.

Pontos positivos

Pontos negativos

Como pontos positivos, podemos citar:

t PCBODPEFEBEPTQFSNBOFDFOPSNBMJ[BEP ØUJNP t QPTTVJQFSGPSNBODFTJNJMBSBTPVUSBTFTUSBUÏHJBT

t DPNPCBODPEFEBEPT)42-%#QPTTVJFYDFMFOUFQFSGPSNBODF

Como pontos negativos, podemos citar: t OÍPFODPOUSBNPT

Consulta gerada para select na estratégia

JOINED

Análise de performance

Conforme podemos observar, na estratégia JOINED a JPA opta pelo uso de join e left join, enquanto na estratégia TABLE_PER_CLASS é utilizado union e subselects. A seguir, iremos abordar em mais detalhes a perfor-mance de cada uma das estratégias.

Para a identificação dos tempos das estratégias SINGLE_TABLE, TABLE_PER_ CLASS e JOINED, usamos o framework JUnit e utilizamos as operações de inserção, seleção e deleção dos registros. Os testes ocorreram com 8 mil regis-tros. O equipamento utilizado foi um Notebook Accer Core 2 Duo com 2G de memória RAM. Os testes foram realizados em três diferentes bancos de dados: HSQLDB 1.69, FireBird 2.0 e MySQL 5.1, porém estes testes podem também ser estendidos a outros banco de dados.

Para a implementação dos testes foram desenvolvidas nove classes, sendo três para inserção em cada uma das estratégias, três para seleção em cada uma das estratégias e três para remoção dos dados. Todos os testes manipulam os mesmos dados, a fim de manter o mesmo critério para avaliação dos tempos. É importante observar que dentre os testes aqui apresentados a remoção ocor-reu através da chave primária, porém a pesquisa ocorocor-reu pelas colunas CPF e CNPJ, que não representam a chave primária das tabelas PessoaFisicaJoined e PessoaJuridicaJoined, respectivamente. Esta foi uma forma de realizar os tes-tes, porém caso seja necessária a alteração para utilizar a chave torna-se bem simples e possível de ser feita.

@Entity

@PrimaryKeyJoinColumn (referencedColumnName=”id”)

publicclass PessoaJuridicaJoined extends PessoaJoined implements

Serializable {

privatestaticfinallong serialVersionUID = 1L; privatelong cnpj;

private String nomeFantasia; private String razaoSocial; private Date dtFundacao; //getters e setters omitidos

}

Listagem 13. Classe PessoaJuridicaJoined. Implementando a estraté-gia JOINED.

@Entity

@PrimaryKeyJoinColumn (referencedColumnName=”id”)

publicclass AutorJoined extends PessoaFisicaJoined implements Serializable { privateint qdadeLivrosPublicados;

private String descUltimoLivro; privateint qdadePaginasUltLivro; //getters e setters omitidos

}

@Entity

@PrimaryKeyJoinColumn (referencedColumnName=”id”)

publicclass EditoraJoined extends PessoaJuridicaJoined implements

Serializable {

privateint qdadeFuncionarios; private String areaEspecializacao; privateint qdadeLivrosEstoque; //getters e setters omitidos

}

Listagem 14. Classe AutorJoined. Implementando a estratégia JOINED.

Listagem 15. Classe EditoraJoined. Implementando a estratégia JOINED.

select

pessoafisi0_.id as id38_, pessoafisi0_1_.dataCadastro as dataCa-da2_38_, pessoafisi0_1_.matricula as

matricula38_, pessoafisi0_1_.dataBloqueio as dataBloq4_38_, pessoa-fisi0_1_.contaAcesso as

contaAce5_38_, pessoafisi0_1_.senha as senha38_, pessoafisi0_1_. id_endereco as id8_38_,

pessoafisi0_1_.nome as nome38_, pessoafisi0_.rg as rg39_, pessoafi-si0_.cpf as cpf39_,

pessoafisi0_.especialidade as especial4_39_, pessoafisi0_.dtNasc as dtNasc39_, pessoafisi0_2_.qdadeLivrosPublicados as qdadeLiv2_40_, pessoafisi0_2_.descUltimoLivro as descUlti3_40_, pessoafisi0_2_.qdadePaginasUltLivro as qdadePag4_40_, case

when pessoafisi0_2_.id is not null then 2 when pessoafisi0_.id is not null then 1 end as clazz_ from PessoaFisicaJoined pessoafisi0_

inner join PessoaJoined pessoafisi0_1_ on pessoafisi0_.id=pessoafisi0_1_.id left outer join AutorJoined pessoafisi0_2_ on pessoafisi0_.id=pessoafisi0_2_.id where pessoafisi0_.cpf=?

(9)

Análise dos tempos de inserção de 8 mil registros:

"OÈMJTFEF1FSGPSNBODFOPCBODPEFEBEPT.Z42-

7JTÍP HSÈmDB EPT UFNQPT EF TFMFÎÍP EF 

mil registros:

Visão gráfica dos tempos de inserção de

SFHJTUSPT

"OÈMJTFEPTUFNQPTEFTFMFÎÍPEFNJMSFHJTUSPT

8000 Registros

MySQL

FireBird

HSQLDB

JOINED

TPC

ST

JOINED TPC

ST

JOINED TPC

ST

273,188

276,297 265,562 116,516 111,328 114,359 31,563

57,172 61,047

290,000

278,156 269,641 111,391 108,110 113,266 28,562

46,859 74,453

317,968

279,094 269,844 150,000 118,312 127,391 37,172

64,922 55,297

309,688

276,156 271,516 146,671 121,875 118,703 40,328

59,094 64,859

Total

1.190,844 1.109,703 1076,563 524,578 459,625 473,719 137,625 228,047 255,656

inserirPessoaFisica

inserirPessoaJuridica

inserirAutor

inserirEditora

Tabela 1. Exemplo: Tabela com dados da operação de inserção

Figura 6. Exemplo: visão gráfica da operação de inserção.

Como podemos observar na figura 6, o banco de dados HSQLDB é de longe o mais rápido em todas as estratégias para a operação de inserção. Em segundo lugar, fica o banco de dados FireBird e em terceiro o MySQL. Outros dados importantes a serem analisados tratam-se dos tempos da tabela 1 para a estratégia JOINED com as tabelas AutorJoined e Editora-Joined. Como estas tabelas ficam em uma maior profundidade na hierar-quia, o tempo para incluir os dados ficou maior. Este evento se estendeu em quase todas as estratégias e em quase todos os bancos de dados.

8000 Registros

MySQL

FireBird

HSQLDB

JOINED

TPC

ST

JOINED

TPC

ST

JOINED TPC

ST

149,187 27.097,46 9 699,688

231,234 268,344

608,219 77,657

687,391 121,609

167,141 27.192,89 9 713,531

232,125 271,187

602,672 94,125

875,875 124,594

208,047

178,546

692,266

390,609 195,766

576,047 182,484

60,484 139,016

199,296

187,016

716,390

391,172 186,234

562,437 176,484

68,844 135,937

Total

723,671 54.655,930 2.821,875 1.245,140 921,531 2.349,375 530,750 1.692,594 521,156

obterPessoaFisica

obterPessoaJuridica

obterAutor

obterEditora

Tabela 2. Exemplo: tabela com dados da operação de seleção.

Como podemos observar na figura 7, o banco de dados HSQLDB não foi o mais rápido quando selecionamos dados na estratégia TABLE_PER_ CLASS. Nesta operação, tivemos que a operação de select no banco de dados MySQL para as tabelas posicionadas no meio da hierarquia ficou muito lenta. O tempo para executar cada operação foi de apro-ximadamente 3,2 segundos. Isto gerou um tempo final perto de 7,5 horas. Porém, caso sejam removidos os registros das tabelas AutorTPC e EditoraTPC, os tempos para a seleção como também para a remoção de registros, na estratégia TABLE_PER_CLASS, das tabelas PessoaFisicaTPC e PessoaJuridicaTPC ficam bem menores.

Isto ocorre devido ao comando union gerado pela estratégia TABLE_ PER_CLASS nas consultas ficar sem função. Vejamos um exemplo:

a consulta gerada para a tabela PessoaFisicaTPC cria um subselect com a tabela PessoaFisicaTPC como também um union com a tabela AutorTPC. Como a tabela AutorTPC não possui registros, o union acaba ficando sem função. Assim, a performance melhora e muito. A consulta SQL para a tabela PessoaFisicaTPC apresentada no tópico Consulta SQL gerada para select na estratégia TABLE_PER_CLASS exemplifica a situação comentada.

No caso da remoção de registros, a performance melhora devido ao mesmo caso. Para remover os registros, precisamos executar o método merge(). Este método gera um select no banco de dados, assim, tere-mos o mesmo problema da geração do union. Caso a tabela AutorTPC não tenha registros, este union também não retornará nenhum registro.

(10)

Figura 7. Exemplo: visão gráfica da operação de seleção.

"OÈMJTFEPTUFNQPTEFSFNPÎÍPEFNJMSFHJTUSPT

8000 Registros

MySQL

FireBird

HSQLDB

JOINED

TPC

ST

JOINED

TPC

ST

JOINED TPC

ST

246,250 31.926,000 253,265 120,438 121,328 134,016 31,515

519,672

33,000

286,297 32.321,421 232,063 115,625 113,609 113,766 32,578

658,312

34,954

247,328

242,187 246,906 133,750

98,141 113,562 34,454

29,860 35,468

255,891

258,516 244,812 130,953 101,437 120,359 35,734

31,468 35,641

Total

1.035,766 64.748,124 977,046 500,766 434,515 481,703 134,281 1.239,312 139,063

removerPessoaFisica

removerPessoaJuridica

removerAutor

removerEditora

Tabela 3. Exemplo: tabela com dados da operação de remoção.

Figura 8. Exemplo: visão gráfica da operação de remoção.

7JTÍPHSÈmDBEPTUFNQPTEFSFNPÎÍPEF

mil registros:

Como podemos observar na figura 8 o banco de dados HSQLDB não foi o mais rápido quando removemos dados na estratégia TABLE_PER_CLASS, porém nos outros o tempo quase sempre ficou bem menor. Nesta operação, tivemos também que a operação de delete no banco de dados MySQL para as tabelas posicionadas no meio da hierarquia (PessoaFisicaTPC e PessoaJuridicaTPC) ficou muito lenta. O tempo para executar cada operação foi de aproximadamente 4 segundos. Isto gerou um tempo final perto de 8 horas. Porém, caso sejam removidos os registros das tabelas AutorTPC e EditoraTPC, os tempos para a remoção na estratégia TABLE_PER_CLASS no banco de dados MySQL, das tabelas Pesso-aFisicaTPC e PessoaJuridicaTPC, ficam bem menores. Isto ocorre devido ao banco de dados considerar que as tabelas que estão hierarquicamente abaixo das tabelas em questão não possuem mais nenhum registro.

Como curiosidade, podemos enfatizar que os tempos de remoção de registros no banco de dados HSQLDB na estratégia TABLE_ PER_CLASS ficaram bem menores para as tabelas que estão na extremidade da hierarquia.

Como executar os testes em outros bancos

de dados

Para executar em outros bancos de dados, precisamos configurar apenas dois arquivos XMLs. Primeiramente devemos criar o arquivo de conexão referente ao seu banco de dados. Ver no site do fornecedor ou na Internet

Após a definição do arquivo para a conexão com o banco de dados, de-vemos configurar o arquivo persistence.xml que conecta os programas Java com o banco de dados. Este arquivo deve ficar no diretório META-INF e apontar para o arquivo de DataSource que pretende-se conectar. O nome do arquivo de DataSource deve ficar dentro do arquivo persisten-ce.xml. A Listagem 18 apresenta um exemplo do arquivo persistence.xml apontando para o banco de dados MySQL.

Herança de classes que não representam

entidades

É importante observar que cada banco de dados possui um arquivo com as suas particularidades. Caso precise testar com outro banco de dados, altere o conteúdo deste arquivo.

Até o momento, as estratégias de herança abordadas consideraram que todas as classes envolvidas na hierarquia são classes anotadas com a an-notation @Entity, ou seja, são classes que serão representadas no banco de dados como tabelas. Porém, podemos ter situações nas quais seja ne-cessário herdar de uma classe do legado que não deverá ser considerada como uma tabela. Para isso, usamos a annotation @javax.persistence. MappedSuperclass.

como deve ser preparado. Neste artigo, usamos DataSource para o acesso aos bancos de dados. Estes arquivos devem ser gravados no diretório de deploy do servidor JBoss. Ex.: C:\...\server\jboss\server\default\deploy. Vejamos dois exemplos dos arquivos utilizados para os testes no MySQL e FireBird. O arquivo referente ao HSQLDB poderá ser baixado do site da revista. Vejamos na Listagem 16 o conteúdo do arquivo mysql-ds.xml

(11)

Uma vez que a classe não está anotada com a annotation @Entity, esta não terá uma tabela associada. Porém, pode ser necessário renomear um atributo para um novo nome na tabela criada. Para isto, usamos a anno-tation @AttributeOverride. Na classe PessoaJoined, sobrescrevemos um atributo da classe Usuario utilizando a annotation @AttributeOverride. Vejamos o exemplo: @AttributeOverride (name = "senha", column = @ Column (name="password")). Neste exemplo, estamos renomeando a coluna definida como senha para um novo nome chamado de password, ou seja, no banco de dados a coluna será criada como password. As lis-tagens de programa 20 e 21 apresentam os programas utilizados neste artigo com este fim.

<connection-factories>

<local-tx-datasource>

<jndi-name>mysql-ds</jndi-name>

<connection-url>

jdbc:mysql://localhost:3306/curso?createDatabaseIfNotExist=true </connection-url>

<driver-class>com.mysql.jdbc.Driver</driver-class>

<transaction-isolation>TRANSACTION_REPEATABLE_READ </transaction-isolation>

<connection-propertyname=”lc_ctype”type=”java.lang.String”> UNICODE_FSS</connection-property>

<connection-propertyname=”maxStatements”>10</connection-property>

<user-name>root</user-name>

<password>12345</password>

<min-pool-size>0</min-pool-size>

<max-pool-size>200</max-pool-size>

<blocking-timeout-millis>5000</blocking-timeout-millis>

<idle-timeout-minutes>15</idle-timeout-minutes>

<track-statements>false</track-statements>

<prepared-statement-cache-size>0</prepared-statement-cache-size>

<metadata>

<type-mapping>MySQL</type-mapping>

</metadata>

</local-tx-datasource> </connection-factories>

<connection-factories>

<local-tx-datasource>

<jndi-name>mfirebird-ds</jndi-name>

<connection-url>jdbc:firebirdsql:localhost/3050:/exemplo.fdb </connection-url> <driver-class>org.firebirdsql.jdbc.FBDriver </driver-class> <transaction-isolation>TRANSACTION_REPEATABLE_READ </transaction-isolation>

<connection-propertyname=”lc_ctype”type=”java.lang.String”>

UNICODE_FSS</connection-property>

<connection-propertyname=”maxStatements”>10 </connection-property>

<user-name>sysdba</user-name>

<password>masterkey</password>

<min-pool-size>0</min-pool-size>

<max-pool-size>200</max-pool-size>

<blocking-timeout-millis>5000</blocking-timeout-millis>

<idle-timeout-minutes>15</idle-timeout-minutes>

<check-valid-connection-sql>SELECT CAST(1 as INTEGER) FROM rdb$database</check-valid-connection-sql>

<track-statements>false</track-statements>

<prepared-statement-cache-size>0</prepared-statement-cache-size>

<metadata>

<type-mapping>Firebird</type-mapping>

</metadata> </local-tx-datasource> </connection-factories> <?xmlversion=”1.0” encoding=”windows-1252” ?> <persistenceversion=”1.0” 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”> <persistence-unitname=”titan”>

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<jta-data-source>java:/mysql-ds</jta-data-source>

<properties>

<propertyname=”hibernate.hbm2ddl.auto”value=”create”/>

<propertyname=”hibernate.show.sql”value=”false”/>

<propertyname=”hibernate.dialect” value=”org.hibernate.dialect.MySQLDialect”/> </properties> </persistence-unit> </persistence> <?xmlversion=”1.0” encoding=”windows-1252” ?> <persistenceversion=”1.0” 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”> <persistence-unitname=”titan”>

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<jta-data-source>java:/mfirebird-ds</jta-data-source>

<properties>

<propertyname=”hibernate.hbm2ddl.auto”value=”update”/>

<propertyname=”hibernate.show.sql”value=”false”/>

<propertyname=”hibernate.dialect”

value=”org.hibernate.dialect.FirebirdDialect”/>

</properties>

</persistence-unit>

</persistence>

Listagem 16. Arquivo XML utilizado como DataSource para acesso ao banco de dados MySQL.

Listagem 17. Arquivo XML utilizado como DataSource para acesso ao banco de dados FireBird.

Listagem 18. Arquivo XML utilizado para a comunicação do JPA com o banco de dados MySQL.

Listagem 19. Arquivo XML utilizado para a comunicação do JPA com o banco de dados FireBird.

(12)

Considerações finais

Conforme podemos observar, cada estratégia possui uma particula-ridade, as quais destacamos:

t B FTUSBUÏHJB 4*/(-&@5"#-& QPTTVJ B DBSBDUFSÓTUJDB EF FYJHJS uma coluna adicional;

t BQFTBS EF TFS BQSFTFOUBEP FN JOÞNFSPT TJUFT RVF B FTUSBUÏ-gia SINGLE_TABLE possui melhor performance, vemos que isto ocorre em alguns casos, conforme podemos observar nos tes-tes realizados. Esta estratégia joga no lixo o conceito de nor-malização e por isto deve-se sempre justificar a sua utilização; t OBTPQFSBÎÜFTEFTFMFÎÍP BFTUSBUÏHJB4*/(-&@5"#-&GPJNBJT

lenta que a estratégia JOINED em quase todos os testes realiza-dos. Isto ocorre devido a esta estratégia utilizar uma string no filtro da cláusula SQL. No caso da estratégia JOINED, os filtros são feitos usando-se as chaves primárias;

t BFTUSBUÏHJB5"#-&@1&3@$-"44VUJMJ[BVOJPOFTVCTFMFDUTQBSB a recuperação de dados dentro de uma hierarquia de classe. Conforme podemos observar, esta estratégia tem grande difi-culdade em funcionar no banco de dados MySQL;

t BFTUSBUÏHJB+0*/&%VUJMJ[BKPJOQBSBFTUFGJN&TUBFTUSBUÏHJBTF mostrou a melhor das estratégias;

t BQFSGPSNBODFEFDBEBFTUSBUÏHJBWBSJBEFBDPSEPDPNBPQF-ração que está sendo executada. Como podemos observar na operação de inserção, a estratégia JOINED foi a mais lenta,

po-rém não o suficiente para torná-la inviável. Quando utilizamos a estratégia JOINED na seleção, esta teve um resultado bastan-te positivo em relação às outras estratégias, ou seja, apesar de usar join o JPA esta bem ajustado a estas necessidades. Assim, esta estratégia deve ser sempre analisada com carinho, pois, além de ter boa performance, mantém o banco de dados nor-malizado;

t PTWBMPSFTBRVJBQSFTFOUBEPTSFGMFUFNBSFBMJEBEFEPTCBODPT de dados avaliados. É extremamente recomendado que, caso o leitor utilize outro banco de dados, os testes sejam realizados para ter outra avaliação. Os testes podem com certeza auxiliar tanto o analista de sistemas como também administradores de banco de dados no momento da definição da melhor estraté-gia a ser adotada.

Os testes aqui apresentados podem ser novamente executados em outros bancos de dados, porém recomendamos que seja utilizado o framework JUnit, por ter integrado o tempo que cada caso de teste executa. Isto ajuda a ter qualidade nos tempos levantados. Todos os testes foram executados mais de três vezes e em todos os casos os tempos ficaram próximos. Caso alguém tenha alguma dúvida ou TVHFTUÍP GJRVFËWPOUBEFQBSBFOUSBSFNDPOUBUPt Referências .&/%&4 %31SPHSBNBÎÍP+BWBDPNÐOGBTFFN0SJFOUBÎÍPB0CKFUPTFE4ÍP1BVMP Novatec, 2009. v.1. 456 p. #*--#63,& 3*$)"3%.0/40/)"&'&-&OUFSQSJTF+BWB#FBOT 0}3FJMMZ ... @MappedSuperclass

public class Usuario implements Serializable {

private static final long serialVersionUID = 1L; private int matricula;

private Date dataCadastro; private Date dataBloqueio; private String contaAcesso; private String senha; ... ... @Entity @Inheritance(strategy = InheritanceType.JOINED) @AttributeOverride(name="senha", column=@ Column(name="password"))

public abstract class PessoaJoined extends Usuario implements Serializable { private static final long serialVersionUID = 1L;

private int id; private String nome; private Endereco endereco; ...

Referências

Documentos relacionados

Dessa forma, os grupos armados teriam como alvos locais em que o MDC conquistou o apoio da população, de forma a ameaçar a hegemonia do partido de Robert Mugabe.. Ademais,

Resumo: Considerando a influência que as novas mídias da comunicação e da informação exercem sobre nossas vidas, o trabalho proposto visa apresentar a análise da

Por isso, o mesmo mostrou-se completamente disposto para realização das extrações dentárias superiores e instalação de implantes osseointegrados na maxila com prótese de arco

Embora esteja cada vez mais bem documentada a magnitude da dispersão no meio ambiente de poluentes tóxicos produzidos pelo homem, poucas pessoas sabem que esses mesmos compostos

Atendimento em locais indicados pela operadora, após liberação da guia TISS, de acordo com a legislação vigente. Guia de encaminhamento autorizado pelo guichê

Já agora não se me dá de confessar que sentia umas tais ou quais cócegas de curiosidade, por saber onde ficava a origem dos séculos, se era tão misteriosa como a origem do Nilo, e

Luminárias da linha Essential LED Highbay com facho fechado (NB) são ideais para aplicações com altura de montagem entre 8-10 metros.*. Em muitos galpões de estoque, posições

No entanto, é preciso considerar também a possível variabilidade climática natural (por exemplo, a PDO citada anteriormente), uma vez que registros climáticos existentes não