Você está na página 1de 78

Curso Hibernate

Curso Hibernate 1. 2. CONCEITOS GERAIS DE PERSISTNCIA MAPEAMENTO OBJETO RELACIONAL


2.1 MAPEAMENTO OBJETO RELACIONAL 2.1.1 2.1.2

4 4

Mapeamento de um objeto com tipos primitivos Mapeamento de objetos que contm uma coleo de objetos

3. 4.

INTRODUO AO HIBERNATE ARQUITETURA 4.1 SESSION (ORG.HIBERNATE.SESSION) 4.2 SESSIONFACTORY (ORG.HIBERNATE.SESSIONFACTORY) 4.3 CONFIGURATION (ORG..HIBERNATE.CONFIGURATION) 4.4 TRANSACTION (ORG.HIBERNATE.TRANSACTION) 4.5 INTERFACES CRITERIA E QUERY

8 8

5.

CLASSES PERSISTENTES 5.1 IDENTIDADE/IGUALDADE ENTRE OBJETOS 5.2 ESCOLHENDO CHAVES PRIMRIAS

10

6. 7.

OBJETOS PERSISTENTES, TRANSIENTES E DETACHED INTRODUO A ANOTAES (ANNOTATIONS) 7.1 TIPOS DE ANOTAES SUPORTADAS PELO JAVA 5.0

14 15

8. 9.

CONFIGURANDO O HIBERNATE MANIPULANDO OBJETOS PERSISTENTES

19 21 24 27

10. MAPEANDO ATRIBUTOS DA CLASSE 11. ASSOCIAES 11.1 ASSOCIAES 1-N (ONE-TO-MANY) 11.2 ASSOCIAES N-1 (MANY-TO-ONE) 11.3 ASSOCIAES N-N (MANY-TO-MANY)

Curso Hibernate 11.4 ASSOCIAES N-N COM ATRIBUTOS 11.4.1 Composite-id 11.5 ASSOCIAES 1-1 (ONE-TO-ONE) 12. DEFINIO DE CHAVE PRIMRIA 13. COLEES 13.1 SET 13.2 LIST 13.3 MAP 13.4 MAP 14. TRANSAES 14.1 MODELOS DE TRANSAES 14.2 TRANSAES E BANCO DE DADOS 14.3 AMBIENTES GERENCIADOS E NO GERENCIADOS 14.4 TRANSAES JDBC 14.5 TRANSAES JTA 14.6 API PARA TRANSAES DO HIBERNATE 14.7 FLUSHING 14.8 NVEIS DE ISOLAMENTO DE UMA TRANSAO 14.9 CONFIGURANDO O NVEL DE ISOLAMENTO 15. CONCORRNCIA 15.1 LOCK OTIMISTA 15.2 LOCK PESSIMISTA 16. CACHING 16.1 ARQUITETURA DE CACHE COM HIBERNATE 16.2 MAPEANDO CACHE 74 66 56 48 49

Curso Hibernate 1. CONCEITOS GERAIS DE PERSISTNCIA Quando se fala em persistncia de dados logo nos vem a mente modelos complexos e cheios de abreviaes: DAO, ORM, Integridade Relacional. A verdade reside no fato de que esses conceitos so imprescindveis para construo de uma aplicao robusta, mas a interao do desenvolvedor com eles pode ser muito amigvel com a utilizao do framework Hibernate. A codificao de camadas de persistncia so meticulosas e a demanda de tempo e possibilidades de erros so tpicos de teor conclusivo para este trabalho. Contudo, mais do que abordar caractersticas e, principalmente, a simplicidade desse framework, o ponto alto de toda argumentao est no entendimento da mudana de paradigma proporcionada pelo Hibernate no trabalho com banco de dados, ou seja, o trabalho estruturada sobreposto pelo orientada objeto, o que torna essa ferramenta atrativa pela maximizao da produtividade. O uso do Hibernate torna a aplicao malevel a mais de um tipo de banco de dados, isso depende, na maioria das vezes, apenas de poucos minutos de uma reconfigurao bsica do framework. Ele tambm deixa transparente as operaes CRUD de dados. Contudo o principal ponto de destaque est no paradigma de OO para banco de dados, tornando a modelagem e o trabalho de programao muito mais elagante.

2.

MAPEAMENTO OBJETO RELACIONAL Por vrios anos os projetos de aplicaes corporativas tiveram uma forte necessidade de se otimizar a comunicao da lgica de negcio com a base de dados. Essa necessidade ganhou mais intensidade com o crescimento dessas aplicaes, crescimento esse, tanto em requisitos (funcionalidade) quanto em volume de dados armazenados em seu banco de dados.

Curso Hibernate Na dcada de 80, foram criados os bancos de dados relacionais (BDR) que substituram as bases de dados de arquivos. Para esse tipo de base de dados foi criada uma linguagem, a SQL. Essa linguagem foi toda baseada na lgica relacional e por isso contava com diversas otimizaes em suas tarefas se comparadas com as outras tecnologias existentes. A partir de ento foi diminudo o tempo gasto para as operaes de persistncia, mesmo com um grande volume de dados. Entretanto, essa linguagem no propiciava aos desenvolvedores uma facilidade para que a produtividade fosse aumentada. Uma soluo que surgiu no incio da dcada de 90 foi criao de um modelo de banco de dados baseado no conceito de orientao a objetos. Este modelo visava facilitar, para os desenvolvedores, a implementao da camada de persistncia da aplicao, pois eles j estavam familiarizados com o paradigma de orientao a objetos, conseqentemente, a produtividade certamente aumentaria. Na prtica, esse modelo de dados no foi utilizado em grandes aplicaes, isto que elas tinham um volume de dados muito grande e esse modelo era ineficiente em termos de tempo de resposta, pois ao contrrio dos bancos de dados relacionais, eles no tinham um modelo matemtico que facilitasse as suas operaes de persistncias. Ento a soluo foi usar os BDR e desenvolver ferramentas para que o seu uso seja facilitado. Uma dessas ferramentas o framework Hibernate que usa o conceito de mapeamento objeto relacional (MOR). 2.1

M APEAMENTO OBJETO RELACIONAL Como foi descrito anteriormente, mapeamento objeto relacional funciona com a transformao dos dados de um objeto em uma linha de uma tabela de um banco de dados, ou de forma inversa, com a transformao de uma linha da tabela em um objeto da aplicao. Abordando essa idia, alguns problemas podero existir, como, se um objeto tiver uma coleo de outros objetos.

2.1.1 Mapeamento de um objeto com tipos primitivos Esse o mapeamento mais simples, onde um objeto tem apenas tipos de dados bsicos. Vale salientar que entendesse por tipos bsicos aqueles que possuem um correspondente em SQL, ou seja, o tipo String da linguagem Java considerado um tipo bsico, pois ele possui 5

Curso Hibernate um correspondente em SQL. Na Figura 1, observa-se o mapeamento de trs objetos do tipo Veiculo na tabela de um banco de dados. Caso a aplicao deseje saber o veculo da cor vermelha, por exemplo, ento o objeto que tem o Plio como modelo retornado.

Figura 1 - Exemplo de mapeamento de tipos bsicos

2.1.2 Mapeamento de objetos que contm uma coleo de objetos Esse tipo de mapeamento quando um objeto possui um conjunto de outros objetos. Para obter esse conceito necessrio adicionar, ao exemplo da Figura 1, uma nova classe chamada de Fabricante que conter as informaes: nome, que armazenar o nome desse fabricante e o veiculos, que conter o conjunto de veculos do fabricante (telefone e endereco no so informaes relevantes no exemplo). Faz-se necessrio a adio de uma informao na classe Veiculo chamada de fabricante, como mostrado na Figura 2.

Figura 2 - Relacionamento entre as classes Fabricante e Veiculo

Curso Hibernate

O atributo fabricante adicionado em Veiculo simplesmente para relacionar um veculo ao seu fabricante, enquanto o veiculos de Fabricante referencia a classe Veiculo. Como foram realizadas mudanas no domnio do exemplo orientado a objetos, faz-se necessria uma alterao no modelo do banco de dados. Primeiramente, o vnculo que foi realizado entre um fabricante e um veculo dever ser implementado atravs de uma chave estrangeira (referncia a uma outra tabela, pois em BDR no existe o conceito de colees) que se localizar na tabela VEICULO, caracterizando o mapeamento 1 para N, ou seja, um veculo possui apenas um fabricante e um fabricante possui vrios (N) veculos. Essa chave estrangeira ser realizada entre a informao nome da classe Fabricante e o atributo fabricante da classe Veiculo.

Figura 3

Exemplo de mapeamento 1 para N

Para um melhor entendimento, a Figura 3 mostra o mapeamento dos objetos para as tabelas no BDR. Nele observa-se que cada veculo est associado com um fabricante, isso implica dizer que na tabela de VEICULO existe uma referncia para a tabela FABRICANTE. Essa associao feita atravs da coluna fabricante da tabela VEICULO. Pensando em termos prticos, quando um veculo for inserido no banco de dados, ele ser ligado ao seu respectivo fabricante, no momento da insero. Para recuperar os veculos inseridos o desenvolvedor ter que implementar uma busca que retorne alm das informaes do veculo as informaes do seu fabricante, isso poder ser realizado fazendo a seguinte consulta SQL: SELECT * FROM fabricante WHERE nome = <fabricante>, onde <fabricante> o nome do fabricante que est na tabela VEICULO, por exemplo, caso a aplicao deseje as informaes do veculo do modelo Plio, ento para se buscar o fabricante a

Curso Hibernate seguinte consulta ser realizada: SELECT * FROM fabricante WHERE nome = 'Fiat'. Utilizando a mesma idia, os fabricantes so buscados; a nica diferena que agora a consulta que buscar os veculos associados com o fabricante retornar uma coleo de veculos (SELECT * FROM veiculo WHERE fabricante = <nomeFabricante>). Esse tipo de mapeamento muito utilizado em aplicaes em que os objetos fazem muita referncia a outros objetos. Com a idia do MOR vrios projetos de ferramenta comearam a ser desenvolvidas, visando facilitar a implementao da camada de persistncia, dentre elas o framework Hibernate, que um software livre de cdigo aberto e que est tendo uma forte adeso de novos projetos corporativos. 3.

INTRODUO AO HIBERNATE O Hibernate um framework de mapeamento objeto relacional para aplicaes Java, ou seja, uma ferramenta para mapear classes Java em tabelas do banco de dados e vice-versa. bastante poderoso e d suporte ao mapeamento de associaes entre objetos, herana, polimorfismo, composio e colees. O Hibernate no apresenta apenas a funo de realizar o mapeamento objeto relacional. Tambm disponibiliza um poderoso mecanismo de consulta de dados, permitindo uma reduo considervel no tempo de desenvolvimento da aplicao.

4.

ARQUITETURA A arquitetura do Hibernate formada basicamente por um conjunto de interfaces. A Figura 4 apresenta as interfaces mais importantes nas camadas de negcio e persistncia. A camada de negcio aparece acima da camada de persistncia por atuar como uma cliente da camada de persistncia. Vale salientar que algumas aplicaes podem no ter a separao clara entre as camadas de negcio e de persistncia. De acordo com a Figura 4, as interfaces so classificadas como:

Curso Hibernate Interfaces responsveis por executar operaes de criao, deleo, consulta e atualizao no banco de dados: Session, Transaction e Query; Interface utilizada pela aplicao para configurar o Hibernate: Configuration; Interfaces responsveis por realizar a interao entre os eventos do Hibernate e a aplicao: Interceptor, Lifecycle e Validatable. Interfaces que permitem a extenso das funcionalidades de mapeamento do Hibernate: UserType, CompositeUserType, IdentifierGenerator. O Hibernate tambm interage com APIs j existentes do Java: JTA, JNDI e JDBC.

Figura 4 - Arquitetura do Hibernate

4.1

SESSION (ORG.HIBERNATE.SESSION)

Curso Hibernate O objeto Session aquele que possibilita a comunicao entre a aplicao e a persistncia, atravs de uma conexo JDBC. um objeto leve de ser criado, no deve ter tempo de vida por toda a aplicao e no threadsafe. Um objeto Session possui um cache local de objetos recuperados na sesso. Com ele possvel criar, remover, atualizar e recuperar objetos persistentes. 4.2 SESSIONFACTORY (ORG.HIBERNATE.SESSIONFACTORY)

O objeto SessionFactory aquele que mantm o mapeamento objeto relacional em memria. Permite a criao de objetos Session, a partir dos quais os dados so acessados, tambm denominado como fbrica de objetos Sessions. Um objeto SessionFactory threadsafe, porm deve existir apenas uma instncia dele na aplicao, pois um objeto muito pesado para ser criado vrias vezes. 4.3 CONFIGURATION (ORG..HIBERNATE.CONFIGURATION)

Um objeto Configuration utilizado para realizar as configuraes de inicializao do Hibernate. Com ele, define-se diversas configuraes do Hibernate, como por exemplo: o driver do banco de dados a ser utilizado, o dialeto, o usurio e senha do banco, entre outras. a partir de uma instncia desse objeto que se indica como os mapeamentos entre classes e tabelas de banco de dados devem ser feitos. 4.4 TRANSACTION (ORG.HIBERNATE.TRANSACTION)

A interface Transaction utilizada para representar uma unidade indivisvel de uma operao de manipulao de dados. O uso dessa interface em aplicaes que usam Hibernate opcional. Essa interface abstrai a aplicao dos detalhes das transaes JDBC, JTA ou CORBA. 4.5 INTERFACES CRITERIA E QUERY

As interfaces Criteria e Query so utilizadas para realizar consultas ao banco de dados. 5.

CLASSES PERSISTENTES As classes persistentes de uma aplicao so aquelas que

10

Curso Hibernate implementam as entidades de domnio de negcio. O Hibernate trabalha associando cada tabela do banco de dados a um POJO (Plain Old Java Object). POJOs so objetos Java que seguem a estrutura de JavaBeans (construtor padro sem argumentos, e mtodos getters e setters para seus atributos). A Listagem 1 apresenta a classe Pessoa representando uma classe POJO.

Listagem 1

Exemplo de Classe POJO

Consideraes: O Hibernate requer que toda classe persistente possua um construtor padro sem argumentos, assim, o Hibernate pode instanci-las simplesmente chamando Construtor.newInstance(); Observe que a classe Pessoa apresenta mtodos setters e getters para acessar ou retornar todos os seus atributos. O Hibernate persiste as propriedades no estilo JavaBeans, utilizando esses mtodos;

11

Curso Hibernate A classe Pessoa possui um atributo id que o seu identificador nico. importante que, ao utilizar Hibernate, todos os objetos persistentes possuam um identificador e que eles sejam independentes da lgica de negcio da aplicao.

5.1

IDENTIDADE/IGUALDADE ENTRE OBJETOS Em aplicaes Java, a identidade entre objetos pode ser obtida a partir do operador ==. Por exemplo, para verificar se dois objetos obj1 e obj2 possuem a mesma identidade Java, basta verificar se obj1 == obj2. Dessa forma, dois objetos possuiro a mesma identidade Java se ocuparem a mesma posio de memria. O conceito de igualdade entre objetos diferente. Dois objetos, por exemplo, duas Strings, podem ter o mesmo contedo, mas verificar se as duas so iguais utilizando o operador ==, pode retornar um resultado errado, pois como j citado, o operado == implicar em uma verificao da posio de memria e no do contedo. Assim, para verificar se dois objetos so iguais em Java, deve-se utilizar o mtodo equals, ou seja, verificar se obj1.equals(obj2). Incluindo o conceito de persistncia, passa a existir um novo conceito de identidade, a identidade de banco de dados. Dois objetos armazenados em um banco de dados so idnticos se forem mapeados em uma mesma linha da tabela.

5.2

ESCOLHENDO CHAVES PRIMRIAS Um passo importante ao utilizar o Hibernate inform-lo sobre a estratgia utilizada para a gerao de chaves primrias. Uma chave candidata uma coluna ou um conjunto de colunas que identifica unicamente uma linha de uma tabela do banco de dados. Ela deve satisfazer as seguintes propriedades: nica; Nunca ser nula; Constante. 12

Curso Hibernate Uma nica tabela pode ter vrias colunas ou combinaes de colunas que satisfazem essas propriedades. Se a tabela possui um nico atributo que a identifique, ele por definio a sua chave primria. Se possuir vrias chaves candidatas, uma deve ser escolhida para representar a chave primria e as demais serem definidas como chaves nicas. Muitas aplicaes utilizam como chaves primrias chaves naturais, ou seja, que tm significados de negcio. Por exemplo, o atributo cpf da tabela Pessoa (associada classe Pessoa). Essa estratgia pode no ser muito boa em longo prazo, j que uma chave primria adequada deve ser constante, nica e no nula. Dessa forma, se for desejado que a chave primria da tabela Pessoa seja uma outra ao invs do cpf, podem surgir problemas j que provavelmente o cpf deve ser referenciado em outras tabelas. Um problema que poderia acontecer seria a remoo do cpf da tabela. O Hibernate apresenta vrios mecanismos internos para a gerao de chaves primrias. Veja a Tabela 1. Tabela 1 - Mecanismo de Gerao de Chaves Primrias Mecanismo Identity Descrio Mapeado para colunas identity no DB2, MySQL, MSSQL, Sybase, HSQLDM, Infomix. Mapeado em seqncias no DB2, PostgreSQL, Oracle, SAP DB, Firebird (ou generator no Interbase). L o valor mximo da chave primria e incrementa um. Deve ser usado quando a aplicao a nica a acessar o banco e de forma no concorrente. Usa algoritmo high/low para gerao de chaves nicas. Usa uma combinao do IP com um timestamp para gerar um identificador nico na rede.

Sequence

Increment

Hilo

uudi.hex

13

Curso Hibernate 6. OBJETOS PERSISTENTES, TRANSIENTES E DETACHED Nas diversas aplicaes existentes, sempre que for necessrio propagar o estado de um objeto que est em memria para o banco de dados ou vice-versa, h a necessidade de que a aplicao interaja com uma camada de persistncia. Isto feito, invocando o gerenciador de persistncia e as interfaces de consultas do Hibernate. Quando interagindo com o mecanismo de persistncia, necessrio para a aplicao ter conhecimento sobre os estados do ciclo de vida da persistncia. Em aplicaes orientadas a objetos, a persistncia permite que um objeto continue a existir mesmo aps a destruio do processo que o criou. Na verdade, o que continua a existir seu estado, j que pode ser armazenado em disco e ento, no futuro, ser recriado em um novo objeto. Em uma aplicao no h somente objetos persistentes, pode haver tambm objetos transientes. Objetos transientes so aqueles que possuem um ciclo de vida limitado ao tempo de vida do processo que o instanciou. Em relao s classes persistentes, nem todas as suas instncias possuem necessariamente um estado persistente. Elas tambm podem ter um estado transiente ou detached. O Hibernate define estes trs tipos de estados: persistentes, transientes e detached. Objetos com esses estados so definidos como a seguir: Objetos Transientes: so objetos que suas instncias no esto nem estiveram associados a algum contexto persistente. Eles so instanciados, utilizados e aps a sua destruio no podem ser reconstrudos automaticamente; Objetos Persistentes: so objetos que suas instncias esto associadas a um contexto persistente, ou seja, tem uma identidade de banco de dados. Objetos detached: so objetos que tiveram suas instncias associadas a um contexto persistente, mas que por algum motivo deixaram de ser associadas, por exemplo, por fechamento de sesso, finalizao de sesso. So objetos em um estado intermedirio, nem so transientes nem persistentes.

14

Curso Hibernate O ciclo de vida de um objeto persistente pode ser resumido a partir da Figura 5.

Figura 5: Ciclo de Vida - Persistncia

De acordo com a figura acima, inicialmente, o objeto pode ser criado e ter o estado transiente ou persistente. Um objeto em estado transiente se torna persistente se for criado ou atualizado no banco de dados. J um objeto em estado persistente, pode retornar ao estado transiente se for apagado do banco de dados. Tambm pode passar ao estado detached, se, por exemplo, a sesso com o banco de dados por fechada. Um objeto no estado detached pode voltar ao estado persistente se, por exemplo, for atualizado no banco de dados. Tanto do estado detached quanto do estado transiente o objeto pode ser coletado para destruio.

7.

INTRODUO A ANOTAES (ANNOTATIONS) Para utilizar o Hibernate Annotation, primeiramente, preciso copiar sua verso atual do site http://hibernate.org, disponvel em um arquivo compactado. Ento, este arquivo deve ser descompactado e 15

Curso Hibernate seu contedo consiste em um conjunto de arquivos JARs. Esses arquivos devem ser copiados para o diretrio das libs de sua aplicao. Os arquivos hibernate- annotations.jar e lib/ejb3-persistence.jar tambm devem referenciados no classpath da aplicao, juntamente com a classe do driver do banco de dados utilizado. Como j citado, o mapeamento objeto relacional utilizando Hibernate pode ser feito a partir de anotaes. As anotaes podem ser definidas como metadados que aparecem no cdigo fonte e so ignorados pelo compilador. Qualquer smbolo em um cdigo Java que comece com uma @ (arroba) uma anotao. Este recurso foi introduzido na linguagem Java a partir da verso Java SE 5.0. Em outras palavras, as anotaes marcam partes de objetos de forma que tenham algum significado especial. A Listagem 2 e a Listagem 3 apresentam exemplo de um tipo de anotao denominado de TesteAnotacao e do seu uso em um mtodo qualquer (metodoTeste), respectivamente. O exemplo meramente ilustrativo, de forma que o tipo de anotao definido no agrega nenhum significado especial ao cdigo fonte.

Listagem 2

Exemplo ilustrativo para a criao de um tipo de anotao

Listagem 3

Exemplo ilustrativo para o uso de um tipo de anotao

As anotaes podem possuir nenhum, um ou mais de um elementos em sua definio. Um exemplo de tipo de anotao sem nenhum atributo j foi visto nas Listagem 2 e na Listagem 3. Se um tipo de anotao possui um nico elemento, como definido e ilustrado na Listagem 4, no momento de se utilizar a anotao, um valor para este atributo deve ser passo entre parnteses, como mostrado na Listagem 5

16

Curso Hibernate

Listagem 4

Exemplo ilustrativo para a criao de um tipo de anotao

Listagem 5

Exemplo ilustrativo para o uso de um tipo de. Anotao

No caso em que o tipo da anotao ser definido com mais de um elemento, como mostrado na Listagem 6, na hora em que a anotao for usada, para atribuir valores para seus elementos preciso passlos tambm entre parnteses, porm definindo o nome do elemento e o seu valor, como exemplo ilustrado na Listagem 7.

Listagem 6

Exemplo ilustrativo para a criao de um tipo de anotao

Listagem 7

Exemplo ilustrativo para o uso de um tipo de anotao

7.1

TIPOS DE ANOTAES SUPORTADAS PELO JAVA 5.0

Dois tipos de anotaes so suportadas pelo Java 5.0: anotaes simples e meta anotaes. As anotaes simples so usadas apenas para agregar significado especial ao cdigo fonte, mas no para criar algum tipo de anotao. J as meta anotaes so aquelas utilizadas para definir tipos de anotaes. No o intuito desta seo detalhar cada um dos tipos de anotaes existentes no Java 5.0, mas apenas cit-las e apresentar os seus significados. 17

Curso Hibernate As anotaes simples do Java 5.0 so trs: @Override: indica que o mtodo que possui esta anotao deve ter a sua implementao sobrescrevendo a de sua superclasse. Se o mtodo anotado no tiver implementao, o compilador gerar um erro; @Deprecated: permite indicar que algum elemento do cdigo fonte est em desuso, ou com uso depreciado. A anotao servir para que o compilador alerte o programador quanto utilizao de um elemento em desuso; @Suppresswarnings: esta anotao indica ao compilador que os alertas (warnings) no elemento anotado no sejam informados ao programador. J as meta anotaes so: @Target: indica em que nvel dos elementos da classe a anotao ser aplicada, por exemplo: a qualquer tipo; a um atributo, a um mtodo, a um construtor, etc; @Retention: indica onde e quanto tempo a anotao ser considerada. Por exemplo: se apenas a nvel de cdigo fonte e ignoradas pelo compilador; se apenas pelo compilador em tempo de compilao e no pela JVM; ou consideradas pela JVM apenas em tempo de execuo; @Documented: indica que o elemento anotado deve ser documentado atravs de alguma ferramenta javadoc; @Inherited: indica que a classe anotada com este tipo automaticamente herdada. Por exemplo, se uma anotao definida a partir de @Inherited, uma classe anotada por esta nova anotao ir herdar automaticamente todos os seus elementos. Mais informaes sobre estes tipos de anotaes a partir do artigo An Introduction to Java Annotation por M. M. Islam Chisty (Outrubro, 2005). Inicialmente, o mapeamento objeto relacional com Hibernate era feito a partir de um conjunto de configuraes em arquivos XMLs. Com o surgimento das anotaes no Java SE 5.0, o framework Hibernate anexou este recurso, permitindo que as classes Java fossem mapeadas a partir de anotaes, simplificando o seu uso. A prxima seo

18

Curso Hibernate apresentar um exemplo simples do uso da persistncia de uma classe com Hibernate Annotations. 8.

CONFIGURANDO O HIBERNATE Pode-se configurar o Hibernate de trs maneiras distintas: Instanciar um objeto de configurao (org.hibernate.cfg.Configuration) e inserir suas propriedades programaticamente; Usar um arquivo .properties com as suas configuraes e indicar as classes mapeadas programaticamente; Usar um arquivo XML (hibernate.cfg.xml) com as propriedades de inicializao e os caminhos das classes mapeadas. Ser apresentada a configurao a partir do arquivo hibernate.cfg.xml. Um exemplo deste arquivo de configurao pode ser visto na Listagem 11. Vrios parmetros podem ser configurados. Basicamente, deve-se configurar: A URL de conexo com o banco de dados; Usurio e senha do banco de dados; Nmeros mximo e mnimo de conexes no pool; Dialeto.

19

Curso Hibernate

Listagem 11 - Arquivo de Configurao hibernate.cfg.xml

Resumindo as descries das propriedades a serem configuradas: hibernate.dialect: implementao do dialeto SQL especfico do banco de dados a ser utilizado. Usado para identificar as particularidades do banco de dados; hibernate.connection.driver_class: nome da classe do driver JDBC do banco de dados que est sendo utilizado; hibernate.connection.url: a URL de conexo especfica do banco que est sendo utilizado; hibernate.connection.username: o nome de usurio com o qual o Hibernate deve se conectar ao banco; hibernate.connection.password: a senha do usurio com o qual o Hibernate deve se conectar ao banco; hibernate.connection.pool_size: tamanho do pool de conexes; hibernate.connection.isolation: define o nvel de isolamento. Parmetro opcional; hibernate.show_sql: utilizado para definir se os SQL s gerados pelo Hibernate devem ou no ser exibidos (true | false).

20

Curso Hibernate O Hibernate trabalha com dialetos para um grande nmero de bancos de dados, tais como: DB2, MySQL, Oracle, Sybase, Progress, PostgreSQL, Microsoft SQL Server, Ingres, Informix entre outros. Possveis valores para os dilates esto presentes na Tabela 2.

Tabela 2 - Possveis valores de dialetos

J no final do arquivo hibernate.cfg.xml onde devem ser informados os arquivos das classes mapeadas que o Hibernate deve processar. Se alguma classe no for definida neste local, a mesma no poder ser persistida utilizando os mecanismos do Hibernate. 9.

MANIPULANDO OBJETOS PERSISTENTES O Hibernate utiliza objetos Session para persistir e recuperar objetos. Um objeto Session pode ser considerado como uma sesso de comunicao com o banco de dados atravs de uma conexo JDBC. O cdigo fonte exibido na Listagem 12 mostra a criao e persistncia de um objeto do tipo Aluno. Inicialmente alguns imports de objetos so feitos para se utilizar persistncia com o Hibernate. Em seguida, dentro do mtodo main, criase um objeto que conter as configuraes definidas do arquivo hibernate.cfg.xml. A partir deste arquivo, uma sesso para a persistncia de objetos aberta, juntamente com uma transao. Ento, criou-se um objeto do tipo Aluno, atribuiu-se valores

21

Curso Hibernate para seus atributos e, por fim, invocou-se o mtodo save do objeto Session. Com isso, uma linha na tabela aluno adicionada de acordo com os valores definidos no objeto. Assim, a persistncia desejada realizada e deve-se liberar tanto a transao quanto a sesso com o Hibernate.

Listagem 12 - Exemplo de Persistncia da Classe Aluno

O cdigo para a criao de um objeto SessionFactory deve ser chamado uma nica vez durante a execuo da aplicao. Objetos deste tipo armazenam os mapeamentos e configuraes do Hibernate e so muitos pesados e lentos de se criar. A Listagem 13 apresenta o resultado da execuo do cdigo fonte presente na Listagem 12. No caso, o Hibernate buscou um valor para a chave primria da tabela, utilizando a seqncia padro hibernate_sequence. Em seguida, o comando INSERT foi executado para inserir uma linha na tabela aluno de acordo com as informaes atribudas ao objeto montado.

22

Curso Hibernate

Listagem 13

Resultado da Execuo do Cdigo da Listagem 12

A Tabela 3 apresenta alguns dos mtodos que podem ser invocados a partir do objeto Session. Tabela 3 - Mtodos invocados a partir do objeto Session save(Object) Inclui um objeto em uma tabela do banco de dados.

saveOrUpdate(Object) Inclui um objeto na tabela caso ele ainda no exista (seja transiente) ou atualiza o objeto caso ele j exista (seja persistente). delete(Object) Apaga um objeto da tabela no banco de dados.

get(Class, Serializable Retorna um objeto a partir de sua chave id) primria. A classe do objeto passada como primeiro argumento e o seu identificador como segundo argumento.

Em relao ao mtodo saveOrUpdate, uma questo que se pode formular a seguinte: Como o Hibernate sabe se o objeto em questo j existe ou no no banco de dados, ou seja, se ele deve ser criado ou atualizado? . A resposta simples: se o valor atribudo ao identificador for diferente de zero, o objeto deve ter sua linha na tabela atualizada (deve-se garantir que o valor do identificador do objeto se refere a um valor da chave primria da tabela). Caso contrrio, uma nova linha ser adicionada tabela. A Listagem 14 e a Listagem 15 apresentam exemplos dos mtodos invocados a partir do objeto Session.

23

Curso Hibernate

Listagem 14 - Exemplo de Busca e Atualizao de um Objeto Aluno

Listagem 15 - Exemplo de Remoo de Objeto Aluno

Os resultados das execues dos cdigos presentes na Listagem 14 e na Listagem 15 podem ser vistos na Listagem 16 e na Listagem 17, respectivamente.

Listagem 16

Resultado da Execuo do Cdigo da Listagem 14

Listagem 17

Resultado da Execuo do Cdigo da Listagem 15

10. M APEANDO ATRIBUTOS DA CLASSE Esta seo destina-se a apresentar alguns exemplos de mapeamentos

24

Curso Hibernate de atributos de uma classe. Considerando a classe Cliente exibida na Figura 7, composta de um conjunto de atributos, onde um deles (id) corresponde chave primria da tabela correspondente. Dessa forma, pode-se criar uma tabela cliente na base de dados a partir do script mostrado na e Listagem 18.

Figura 7 - Classe Cliente

Listagem 18

Script para a Criao da Tabela cliente

A classe Cliente, ilustrada pela Listagem 19, possui exemplos de mapeamentos de atributos a partir das anotaes: @Column, @Transient, @Temporal. As anotaes @Id e @GeneratedValue tambm so utilizadas e servem para mapear a chave primria da tabela correspondente e definir como o seu valor ser gerado, respectivamente, como explicado anteriormente.

25

Curso Hibernate

Listagem 19

Mapeamento da Classe Cliente com Anotaes

A seguir uma breve descrio da utilizao destas anotaes: Anotao @Transient: informa que o atributo mapeado no possui correspondente na tabela mapeada pela classe, ou seja, no um atributo persistente; Atributos da anotao @Column utilizados: o name: nome da coluna na tabela do banco de dados que representa o atributo; unique: indica se a coluna na tabela que representa o atributo possui a restrio de unicidade ou no. Por padro, assume o valor false;

26

Curso Hibernate o nullable: indica se a coluna na tabela que representa o atributo pode assumir valor nulo ou no. Por padro, assume o valor true, indicando que pode assumir valores nulos; length: informa o tamanho mximo assumido pelo valor da coluna na tabela; precision: informa a preciso decimal dos possveis valores para a coluna mapeada pelo atributo; insertable: indica se o atributo ser inserido no momento da insero de uma linha na tabela. Por padro assume o valor true; updatable: indica se o atributo ser atualizado no momento da atualizao de uma linha na tabela. Por padro assume o valor true.

Anotao @Temporal: utilizada para mapeamento de datas e hora. Recebe um valor como argumento que pode ser: o o o TemporalType.DATE: usado para mapear datas; TemporalType.TIME: usado para mapear hora; TemporalType.TIMESTAMP: usado para mapear datas e hora.

11. ASSOCIAES O termo associao utilizado para se referir aos relacionamentos entre as entidades. Os relacionamentos n-para-n, n-para-1 e 1-para-n so os mais comuns entre as entidades de um banco de dados.
Nas sees seguintes, sero apresentados exemplos de mapeamentos

com anotaes para cada um dos tipos de relacionamentos citados. 11.1 ASSOCIAES 1 - N ( ONE- TO- MANY)

Para exemplificar o relacionamento 1-n, considere o relacionamento entre a entidade Centro e a entidade Universidade da Figura 8. O relacionamento diz que uma universidade possui um conjunto de n centros e um centro est associado a apenas uma nica universidade. Considere as classes de domnio Java de uma universidade e de um centro, respectivamente, mostradas na Listagem 20 e na Listagem 21.

27

Curso Hibernate Ambas as classes j possuem o seu mapeamento via anotaes inserido.

Figura 8 - Relacionamento entre Centro e Universidade

Listagem 20 - Classe de Domnio: Universidade

28

Curso Hibernate

Listagem 21 - Classe de Domnio: Centro

As classes de domnio Universidade e Centro so mapeadas para as tabelas universidade e centro, que podem ser criadas na base de dados a partir dos scripts apresentados na Listagem 22 e na Listagem 23, respectivamente.

Listagem 22

Script para a Criao da Tabela universidade

Listagem 23

Script para a Criao da Tabela centro

A classe de domnio Universidade a que possui um mapeamento do tipo 1-n atravs do atributo coleo de centros. O seu mapeamento foi feito na Listagem 20 a partir da

29

Curso Hibernate anotao @OneToMany. Como a coleo conter objetos do tipo Centro, ento est classe tambm dever ser uma classe persistente da aplicao. Na anotao @OneToMany, existe um atributo denominado mappedBy que dever receber como valor o nome do atributo na classe Centro (classe dos tipos de objetos da coleo) que se refere classe Universidade (onde h o mapeamento 1-n). Em outras palavras, a tabela centro possui uma chave estrangeira para a tabela universidade, representada pelo atributo Universidade universidade da classe Centro, que corresponder ao atributo mappedBy da anotao @OneToMany, ou seja, mappedBy= universidade . J o atributo fecth indica quando o contedo do atributo ser trazido da base de dados. Pode assumir dois valores: FetchType.EAGER: sempre que o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.EAGER far com que o seu contedo tambm seja trazido; FetchType.LAZY: sempre que o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.LAZY far com que o seu contedo somente seja trazido quando acessado pela primeira vez. A anotao @Cascade, tambm utilizada no mapeamento da coleo centros, serve para indicar com que ao em cascata o relacionamento ser tratado, ou seja, especifica quais operaes devero ser em cascata do objeto pai para o objeto associado. Por exemplo, pode assumir alguns dos valores abaixo: CascadeType.PERSIST: os objetos associados vo ser inseridos automaticamente quando o objeto "pai" for inserido; CascadeType.SAVE_UPDATE: os objetos associados vo ser inseridos ou atualizados automaticamente quando o objeto "pai" for inserido ou atualizado; CascadeType.REMOVE: os objetos associados ao objeto "pai" vo ser removidos, quando o mesmo for removido; CascadeType.REPLICATE: Se o objeto for replicado para outra base de dados, os filhos tambm sero;

30

Curso Hibernate CascadeType.LOCK: Se o objeto for reassociado com a sesso persistente, os filhos tambm sero; CascadeType.REFRESH: Se o objeto for sincronizado com a base de dados, os filhos tambm sero; CascadeType.MERGE: Se um objeto tiver suas modificaes mescladas em uma sesso, os filhos tambm tero; CascadeType.EVICT: Se o objeto for removido do cache de primeira nvel, os filhos tambm sero; CascadeType.ALL: juno de todos os tipos de cascade. Para ilustrar o efeito da anotao @Cascade(CascadeType.ALL), considere o exemplo da Listagem 24, onde, inicialmente, um objeto Universidade criado. Em seguida, dois objetos da classe Centro tambm so criados, recebem valores para seu atributo nome e so associados ao objeto universidade, que posteriormente persistido.

Listagem 24

Exemplo de Persistncia OneToMany. Efeito da anotao @Cascade(CascadeType.ALL)

A Listagem 25 apresenta o resultado da persistncia do objeto universidade presente na Listagem 24. Observa-se, que a partir do atributo cascade com valor CascadeType.ALL, inicialmente inserida uma linha na tabela universidade e em seguida duas linhas na tabela centro. Vale salientar, que na hora de inserir as linhas na tabela centro, como os objetos que as representavam foram associados ao objeto universidade, automaticamente, o Hibernate atribui como valor de suas

31

Curso Hibernate chaves estrangeiras, o valor gerado para a chave primria da linha criada na tabela universidade.

Listagem 25

Resultado da Execuo do Cdigo da Listagem 24

O atributo centros da classe Universidade foi mapeado com a anotao @OneToMany e com o atributo fecth=FetchType.EAGER. A Listagem 26 apresenta um exemplo de consulta a uma linha na tabela universidade com valor de chave primria igual a 100. Na Listagem 27 e na Listagem 28 esto os resultados da consulta considerando o atributo fecth da coleo definido como FetchType.EAGER e como FetchType.LAZY, respectivamente.

Listagem 26

Consulta para Ilustrar o Uso do Atributo fecth

Listagem 27

Resultado da Execuo do Cdigo da Listagem 26 com fecth=FetchType.EAGER

32

Curso Hibernate

Listagem 28

Resultado da Execuo do Cdigo da Listagem 26 com fecth=FetchType.LAZY

A partir destes resultados, possvel observar que realmente com o valor FetchType.EAGER, o SQL gerado pelo Hibernate na consulta de uma universidade realiza um left outer join com a tabela centro j trazendo os dados da coleo, podendo ser desnecessrio. Por outro lado, utilizando FetchType.LAZY, a consulta retorna apenas os dados referentes universidade, de forma que se fossem necessrios os dados da coleo, bastaria acessar o atributo que a representa no objeto universidade. A Listagem 29 apresenta um exemplo com a coleo centros mapeada com FetchType.LAZY. Neste exemplo, a mesma consulta universidade de chave primria igual a 100 feita e em seguida um acesso ao atributo centros, atravs da linha do cdigo fonte univ.getCentros().iterator(). O resultado pode ser visto na Listagem 30, em que duas SQLs so geradas, uma gerada no momento da consulta linha na tabela universidade de identificador igual a 100 e a outra no momento em que se itera a coleo centros do objeto anteriormente recuperado.

Listagem 29

Consulta para Ilustrar o Uso do Atributo fecth=FetchType.LAZY

33

Curso Hibernate

Listagem 30

Resultado da Execuo do Cdigo da Listagem 29

11.2

ASSOCIAES N-1 (MANY-TO-ONE) O relacionamento n-1 ser apresentado a partir do relacionamento existente entre as classes Centro e Universidade, mostrado tambm na Figura 8. Neste caso, o relacionamento est presente no mapeamento da classe Centro, como mostrado na Listagem 21, atravs da anotao @ManyToOne. Para facilitar o entendimento, o trecho de mapeamento many-to-one do atributo universidade da classe Centro pode ser visto tambm na Listagem 31.

Listagem 31 - Mapeamento ManyToOne

A anotao @ManyToOne tambm possui o atributo fetch, que possui o mesmo comportamento apresentado anteriormente. A anotao @JoinColumn utilizada para informar qual o nome da coluna que corresponde chave estrangeira do mapeamento, no caso, name= id_universidade . Nesta anotao tambm so aceitveis os atributos insertable e updatable que se assumirem true indica que o atributo deve ser inserido (insertable) ou atualizado (updatable) no momento em que o objeto que possui o relacionamento inserido ou atualizado, respectivamente. O atributo do relacionamento no

34

Curso Hibernate ser inserido se insertable = false e no ser atualizado se updatable = false. Outra anotao utilizada a @Fecth, que define como o atributo mapeado ser recuperado da base de dados. Pode assumir trs valores: FetchMode.JOIN: utiliza outer join para carregar entidades ou colees mapeadas; FetchMode.SELECT: utiliza um novo select para carregar entidades ou colees mapeadas; FetchMode.SUBSELECT: utiliza uma consulta subselect adicional para carregar colees adicionais. No permitido para mapeamentos ManyToOne. A Listagem 32 apresenta uma consulta base de dados do centro com valor de chave primria igual a 110. A Listagem 33 apresenta o resultado da consulta com o mapeamento do atributo universidade da classe Centro utilizando a anotao @Fecth recebendo com valor FetchMode.JOIN. Pode-se observar que uma nica consulta feita, realizando um JOIN entre as tabelas centro e universidade. J na Listagem 34, o resultado da consulta com o uso da anotao @Fetch com o valor FetchMode.SELECT resulta em duas consultas SELECT base de dados, uma para buscar as informaes do centro de chave primria igual a 110 e a outra para buscar as informaes da universidade associada.

Listagem 32

Consulta para Ilustrar o Uso da Anotao @Fecth

35

Curso Hibernate

Listagem 33

Resultado da Execuo do Cdigo da Listagem 32 com @Fetch(FetchMode.JOIN)

Listagem 34

Resultado da Execuo do Cdigo da Listagem 32 com @Fetch(FetchMode.SELECT)

11.3 ASSOCIAES N-N (MANY-TO-MANY) O relacionamento n-n ser feito a partir do relacionamento entre as entidades Departamento e Curso mostrado na Figura 9.

Figura 9 - Relacionamento n-n entre Curso e Departamento

Um relacionamento n-n implica em existir uma nova tabela para mapear o relacionamento no banco de dados. Vamos denominar essa nova tabela como DEPARTAMENTO_CURSO, como mostrado na Figura 10. Dessa forma, um departamento possui uma coleo de cursos e um curso uma coleo de departamentos. A existncia dessas colees nas classes de domnio opcional. Por exemplo, pode ser que em um sistema 36

Curso Hibernate real no seja necessrio saber todos os departamentos de determinado curso, mas se for realmente necessrio, o Hibernate apresenta outros mecanismos para a obteno desta informao.

Figura 10 - Tabela de relacionamento DEPARTAMENTO_CURSO

Para criar as tabelas curso, departamento e departamento_curso, pode-se utilizar os scripts presentes na Listagem 35, na Listagem 36 e na Listagem 37, respectivamente.

Listagem 35 - Script para a Criao da Tabela curso

Listagem 36 - Script para a Criao da Tabela departamento

Listagem 37 - Script para a Criao da Tabela departamento_curso

37

Curso Hibernate As classes Java das entidades Departamento e Curso esto ilustradas na Listagem 38 e Listagem 39, respectivamente. Ambas as classes possuem mapeamentos de colees com o relacionamento n-n, que feito a partir da anotao @ManyToMany. Para este mapeamento, foi preciso tambm do uso da anotao @JoinTable para informar qual a tabela intermediria entre as entidades Departamento e Curso. A anotao @JoinTable possui o atributo name que onde informado o nome da tabela intermediria que representa o mapeamento n-n, no caso, a tabela departamento_curso. Possui tambm o atributo schema, onde dever ser informado o esquema da base de dados em que a tabela se encontra. J o atributo joinColumns recebe como valor uma anotao @JoinColumn, informando qual o nome da coluna na tabela intermediria que representa a classe onde se est fazendo o mapeamento n-n. Em relao ao mapeamento na tabela Departamento, a coluna na tabela intermediria departamento_curso que a representa se chama id_departamento. Por fim, no atributo inverseJoinColumns deve ser informada qual a coluna que representa a outra entidade no relacionamento n-n. No mapeamento da classe Departamento, a outra classe do relacionamento a classe Curso, portanto, a coluna na tabela intermediria que a representa id_curso.

38

Curso Hibernate

Listagem 38 - Classe de Domnio: Departamento

Na classe Curso tambm h o mapeamento de um relacionamento n-n com a coleo departamentos. A explicao semelhante ao mapeamento da coleo cursos na classe Departamento.

39

Curso Hibernate

Listagem 39 - Classe de Domnio: Curso

O cdigo presente na Listagem 40 cria um instncia de um objeto Departamento. Em seguida recupera um objeto persistente da classe Centro com identificador igual a 110 e outro da classe Curso com identificador igual a 220. O objeto Curso adicionado na coleo de cursos do objeto Departamento criado. Por fim, o departamento persistido.

40

Curso Hibernate

Listagem 40

Exemplo com Mapeamento Usado a Anotao @ManyToMany: Persistncia de Departamento

O SQL gerado apresentado na Listagem 41. Observa-se que SELECTs na tabela centro, na tabela curso e na seqncia hibernate_seq so realizados. Depois, feito e um INSERT na tabela departamento e em seguida, uma incluso de linha na tabela de relacionamento departamento_curso, devido ao mapeamento n-n na classe Departamento.

Listagem 41

Resultado da Execuo do Cdigo Presente na Listagem 40

41

Curso Hibernate 11.4 ASSOCIAES N-N COM ATRIBUTOS Imagine que seria necessrio guardar a data em que foi feita a associao entre um determinado curso e um determinado departamento, ou seja, necessrio ter um novo atributo na tabela departamento_curso. Dessa forma, esta tabela no seria formada apenas pelos identificadores das tabelas curso e departamento, mas sim tambm pela data. Para essa situao, os mapeamentos dos relacionamentos com a anotao @ManyToMany nas classes Departamento e Curso no resolveriam o problema. Ento, deve-se criar uma nova classe DepartamentoCurso, como mostrado no diagrama da Figura 11, formada por uma chave primria composta por dois elementos e por um atributo que representa a data.

Figura 11 - Mapeamento n-n com Atributo

Para adicionar a coluna data tabela departamento_curso, basta utilizar o script apresentado na Listagem 42.

Listagem 42 - Script para a Adio da Coluna data na Tabela departamento_curso

Com a adio da coluna data, deve ser feito o mapeamento da tabela departamento_curso como mostrado na Listagem 43 a partir da classe DepartamentoCurso. Pode-se observar que a chave composta representada pelo atributo chaveComposta do tipo DepartamentoCursoPK e mapeada pela anotao @EmbeddedId. A classe DepartamentoCursoPK representa a chave primria composta e mapeada como mostrado na seo seguinte.

42

Curso Hibernate

Listagem 43 - Classe de Domnio: DepartamentoCurso

11.4.1 Composite-id Para mapear uma chave composta, deve-se criar uma classe que a represente. Esta classe deve ser mapeada com a anotao @Embeddable, como mostrado na Listagem 44 no mapeamento da chave composta DepartamentoCursoPK. Dentro desta classe deve-se mapear os atributos que compem a chave composta das maneiras vistas anteriormente. importante ressaltar que a classe que representa a chave composta deve implementar a interface Serializable.

Listagem 44 - Classe de Domnio: DepartamentoCursoPK

Para exemplificar o relacionamento n-n com atributos, observe o exemplo da Listagem 45. Primeiro um departamento e um curso so buscados na base de dados, ambos com identificadores iguais a 1. Em

43

Curso Hibernate seguida, cria-se uma instncia de um objeto da classe DepartamentoCursoPK que representa a chave composta. Os valores que compem a chave, curso e departamento, so atribudos. Finalmente, cria-se um objeto da classe DepartamentoCurso que representa a tabela de relacionamento entre as entidades, define-se a sua chave composta e a data de criao, persistindo-o na base de dados.

Listagem 45

Exemplo com Mapeamento de Chave Composta

O resultado da execuo do cdigo presente na Listagem 45 pode ser visto na Listagem 46.

44

Curso Hibernate

Listagem 46 Listagem 45

Resultado da Execuo do Cdigo Presente na

11.5

ASSOCIAES 1-1 (ONE-TO-ONE) Considere o relacionamento 1-1 entre as entidades Universidade e Endereo mostrado na Figura 12. Uma universidade tem um nico endereo e um endereo pertence apenas a uma nica universidade.

Figura 12 - Exemplo de Relacionamento 1-1

A Listagem 20 e a Listagem 47 apresentam as classes Java para as entidades Universidade e Endereco, respectivamente.

45

Curso Hibernate Na classe Endereco, o relacionamento 1-1 com a classe Universidade mapeado atravs da anotao @OneToOne e da anotao @JoinColumn usada para informar o nome da coluna que representa a chave estrangeira para a tabela universidade.

Listagem 47 - Classe de Domnio: Endereo

A tabela endereo pode ser criada a partir do script exibido na Listagem 48.

Listagem 48 - Script para a Criao da Tabela endereco

Para finalizar o mapeamento 1-1 entre as classes Universidade e Endereo, deve ser includo na classe Universidade o atributo endereco tambm mapeado com a anotao @OneToOne, como mostrado na Listagem 49. No mapeamento 1-1 na classe Universidade, como em sua tabela no h chave estrangeira

46

Curso Hibernate para a tabela endereco, deve-se informar qual atributo na classe Universidade refere-se ao mapeamento 1-1 do outro lado, no caso o atributo universidade, informado pelo atributo mappedBy da anotao @OneToOne. Tambm utilizada a anotao @Cascade passando como argumento CascadeType.ALL, informando que no momento que se inserir, atualizar ou remover uma universidade, a operao deve ser cascateada para a coluna da tabela.

Listagem 49

Incluso de Atributo endereco na classe Universidade

Para ilustrar o uso deste mapeamento, considere o exemplo mostrado na Listagem 50, onde, incialmente, objetos da classe Endereco e Universidade so criados. Em seguida, associa-se a universidade ao endereo e o endereo a universidade. Por fim, o objeto universidade persistido na base de dados. A Listagem 51 apresenta o resultado da execuo do cdigo presente na Listagem 50. Observa-se a universidade persistida na base de dados e em seguida, o endereo tambm fazendo a associao com a universidade criada.

Listagem 50

Exemplo para Ilustrar Mapeamento 1-1

47

Curso Hibernate

Listagem 51

Resultado da Execuo do Cdigo Presente na Listagem 50

12. DEFINIO DE CHAVE PRIMRIA Nos mapeamentos apresentados at o momento, a definio dos valores das chaves primrias foi feita apenas utilizando a seqncia hibernate_sequence. O exemplo presente na Listagem 52 mostra o mapeamento da chave primria da tabela cliente utilizando a seqncia de nome cliente_seq. Para isso, utilizou-se as anotaes @SequenceGenerator e @GeneratedValue. Na anotao @SequenceGenerator define-se qual seqncia criada na base de dados ser utilizada para o mapeamento. No caso, nomeia-se a seqncia com o nome SEQ_CLIENTE (name = SEQ_CLIENTE ). Para definir qual seqncia ser utilizada no mapeamento da chave primria, utiliza-se a anotao @GeneratedValue, onde informado que a definio do valor do atributo ser atravs de seqncias (strategy = GenerationType.SEQUENCE) e o nome da mesma (generator = "SEQ_CLIENTE").

Listagem 52

Mapeamento de Chave Primria Usando Seqncia Prpria

48

Curso Hibernate 13. COLEES O mapeamento de colees j foi apresentado no contexto dos relacionamentos atravs da anotao @OneToMany. Essa seo est destinada a apresentar o mapeamento dos quatro tipos de colees existentes (Set, Bag, List e Map), porm formadas por tipos primitivos. 13.1 Set Para exemplificar o mapeamento de um Set de tipos primitivos considere o mapeamento de uma coleo de String s para armazenar os telefones de um Aluno, como visto na Figura 13. Ento, na classe Aluno deve-se inserir o atributo telefones com seu mapeamento anotado, como mostrado na Listagem 53.

Figura 13 - Coleo de telefones para Aluno: Set

Para mapear esta coleo foi utilizada a anotao @CollectionOfElements. A anotao @JoinTable utlizada para informar o nome da tabela e esquema onde a coleo dos elementos mapeados sero armazendos, no caso atravs dos atributos name= aluno_telefone e schema= anotacoes . Na anotao @JoinTable tambm informada o nome da coluna que representa a classe onde a coleo est sendo mapeada, no caso a classe Aluno. Para informar esta coluna, utiliza-se o atributo joinColumns que recebe como valor a anotao @JoinColumn com o nome da coluna, no caso id_aluno. Por fim, informa-se a coluna que representar a informao do telefone utilizando a anotao @Column. Os telefones do aluno so armazenados na tabela aluno_telefone. Para o banco de dados est tabela separada da tabela aluno, mas para o Hibernate, ele cria a iluso de uma nica entidade.

49

Curso Hibernate

Listagem 53

Atributo telefones Inserido na Classe Aluno (Set)

Um Set no pode apresentar elementos duplicados, portanto a chave primria de aluno_telefone consiste nas colunas id_aluno e telefone. O script para a criao da tabela aluno_telefone est presente na Listagem 54.

Listagem 54 - Script para a Criao da Tabela aluno_endereo

Dado o mapeamento da coleo de telefones de Aluno, observe o exemplo mostrado na Listagem 55. Neste exemplo, cria-se um objeto Aluno que ter valores para seus atributos definidos, inclusive dois nmeros de telefone inseridos em sua coleo de String s. Por fim, o objeto Aluno persistido. O resultado mostrado na Listagem 56, onde primeiro inserida uma linha na tabela aluno e posteriormente duas linhas na tabela aluno_telefone.

50

Curso Hibernate

Listagem 55 - Exemplo de Mapeamento de Set

Listagem 56 - Resultado da Execuo do Cdigo Presente na Listagem 55

13.2

List Um List uma coleo ordenada que pode conter elementos duplicados. O mapeamento de uma lista requer a incluso de uma coluna de ndice na tabela do banco de dados. A coluna ndice define a posio do elemento na coleo, como visto na Figura 14, a coluna ndice representada pela coluna posio da tabela aluno_telefone. Dessa maneira, o Hibernate pode preservar a ordenao da coleo quando recuperada do banco de dados e for mapeada como um List.

Figura 14 - Coleo de telefones para Aluno: List

51

Curso Hibernate Para mapear a coleo de telefones da classe Aluno, define o atributo telefones como mostrado na Listagem 57. A diferea a incluso da definio do ndice atravs da anotao @IndexColumn(name = posio ), informando a coluna que ele representa na tabela.

Listagem 57

Atributo telefones Inserido na Classe Aluno (List)

Mapeando a coleo como um List, a chave primria da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e POSICAO, permitindo a presena de telefones (TELEFONE) duplicados na coleo. Para exemplificar, considera-se o exemplo presente na Listagem 58, com resultado de execuo presente na Listagem 59.

Listagem 58 - Exemplo de Mapeamento de List

Listagem 59 - Resultado da Execuo do Cdigo Presente na Listagem 58

52

Curso Hibernate 13.3 Map Maps associam chaves aos valores e no podem conter chaves duplicadas. Eles diferem de Sets no fato de que contm chaves e valores, ao passo que os Sets contm somente a chave. O mapeamento de um Map semelhante ao de um List, onde o ndice de posio passa a ser a chave. Veja a Figura 14. A Listagem 60 apresenta a coleo de telefones sendo mapeada como um Map. A chave primria da tabela aluno_telefone passa a ser as colunas id_aluno e chave, tambm permitindo a presena de telefones duplicados na coleo. A diferena dos outros mapeamentos que a chave mapeada atravs da anotao @MapKey(columns = {@Column(name = "chave")}).

Figura 15 - Coleo de telefones para Aluno: Map

Listagem 60

Atributo telefones Inserido na Classe Aluno (Map)

Para exemplificar, considera-se o exemplo presente na Listagem 61, com resultado de execuo presente na Listagem 62.

53

Curso Hibernate

Listagem 61 - Exemplo de Mapeamento de Map

Listagem 62 - Resultado da Execuo do Cdigo Presente na Listagem 61

13.4

Bag Um Bag consiste em uma coleo desordenada que permite elementos duplicados. Em Java no h implementao de um Bag, contudo o Hibernate fornece um mecanismo de que um List em Java simule o comportamento de um Bag. Pela definio de um List, uma lista uma coleo ordenada, contudo o Hibernate no preserva a ordenao quando um List persistido com a semntica de um Bag. Para usar o Bag, a coleo de telefones deve ser definida com o tipo List. Um exemplo de mapeamento de um Bag pode ser visto na Figura 16 e na Listagem 63.

Figura 16 - Coleo de telefones para Aluno: Bag

Para simular o Bag como List, a chave primria no deve ter

54

Curso Hibernate associao com a posio do elemento na tabela, assim ao invs da anotao @IndexColumn, utiliza-se a anotao @CollectionId, onde uma chave substituta diferente atribuda a cada linha da tabela na coleo. Entretanto, o Hibernate no fornece nenhum mecanismo para descobrir o valor chave substituta de uma linha em particular. Para o exemplo, a chave substituta representada pela coluna id_aluno_telefone da table aluno_telefone. necessrio informar como os seus valores sero gerados, neste caso, utlizada uma seqncia. A anotao @SequenceGenerator serve para definir o nome de uma seqncia no banco de dados. O atributo name informa como ser denominada a seqncia, j o atributo sequenceName informa qual seqncia se est utilizando. A anotao @CollectionId utlizada para definir a chave substituta. No atributo columns informa-se qual o nome da coluna na tabela; o atributo generator informa qual seqncia est sendo utilizada para gerar seus valores (no caso SEQ_HIBERNATE definida na anotao @SequenceGenerator); e o atributo type utilizado para informar o tipo desta coluna, no caso integer.

Listagem 63

Atributo telefones Inserido na Classe Aluno (Bag)

Para exemplificar, considera-se o exemplo presente na Listagem 58, onde a coleo agora est mapeada com semntica de Bag, com resultado de execuo presente na Listagem 64. Observa-se que a seqncia hibernate_sequence invocada duas vezes: uma para o valor da chave primria do objeto Aluno e outra para o valor da chave substitua da coleo de telefones.

55

Curso Hibernate

Listagem 64 - Resultado da Execuo do Cdigo Presente na Listagem 58

14. TRANSAES Uma transao uma unidade de execuo indivisvel (ou atmica). Isso significa dizer que todas as etapas pertencentes a uma transao so completamente finalizadas ou nenhuma delas termina. Para exemplificar o conceito de transaes, considere um exemplo clssico de transferncia entre contas bancrias: transferir R$ 150,00 da conta corrente do cliente A para a conta corrente do cliente B. Basicamente, as operaes que compem a transao so: 1) Debitar R$ 150,00 da conta corrente do cliente A 2) Creditar R$ 150,00 na conta corrente do cliente B Para a efetivao da transao descrita acima, seria necessrio seguir os seguintes passos: 1) Ler o saldo da conta corrente A (xA) 2) Calcular o dbito de R$ 150,00 da conta corrente A (dA = xA 150,00) 3) Gravar na base de dados o novo saldo da conta corrente A (xA = dA) 4) Ler o saldo da conta corrente B (xB) 5) Calcular o crdito de R$ 150,00 na conta corrente B (dB = xB + 150,00) 6) Gravar na base de dados o novo saldo da conta corrente B (xB = dB) Caso ocorra algum problema (por exemplo: falta de energia, falha no computador, falha no programa, etc.), a execuo dos passos anteriores pode ser interrompida. Se, por exemplo, houvesse

56

Curso Hibernate interrupo logo aps a execuo do 3 passo, a conta A teria um dbito de R$ 150,00 e ainda no teria sido creditado R$ 150,00 na conta corrente B. Neste caso, o banco de dados estaria em um estado inconsistente, afinal, R$ 150,00 teriam sumido da conta A sem destino. Dessa maneira, de suma importncia garantir que esses seis passos sejam totalmente executados. Caso haja alguma falha antes da concluso do ltimo passo, deve-se garantir tambm que os passos j executados sero desfeitos, de forma que ou todos os passos so executados ou todos os passos no so executados. Para garantir a consistncia do banco, esses seis passos devem ser executados dentro de uma transao, j que ela uma unidade de execuo atmica. Resumindo, uma transao garante que a seqncia de operaes dentro da mesma seja executada de forma nica, ou seja, na ocorrncia de erro em alguma das operaes dentro da transao todas as operaes realizadas desde o incio podem ser revertidas e as alteraes no banco de dados desfeitas, garantindo assim, a unicidade do processo. A transao pode ter dois fins: commit ou rollback. Quando a transao sofre commit, todas as modificaes nos dados realizadas pelas operaes presentes na transao so salvas. Quando a transao sofre rollback, todas as modificaes nos dados realizadas pelas operaes presentes na transao so desfeitas. Para que um banco de dados garanta a integridade dos seus dados deve possuir quatro caractersticas, conhecidas como ACID: Atomicidade: o banco de dados deve garantir que todas as transaes sejam indivisveis. Consistncia: aps a execuo de uma transao, o banco de dados deve continuar consistente, ou seja, deve continuar com um estado vlido. Isolamento: mesmo que vrias transaes ocorram paralelamente (ou concorrentemente), nenhuma transao deve influenciar nas outras. Resultados parciais de uma transao no devem ser vistos por outras transaes executadas concorrentemente. Durabilidade: aps a finalizao de uma transao, todas as alteraes feitas por ela no banco de dados devem ser

57

Curso Hibernate durveis, mesmo havendo falhas no sistema aps a sua finalizao. 14.1 MODELOS DE TRANSAES As definies do incio de uma transao, de seu fim e das aes que devem ser tomadas na ocorrncia de falhas so feitas atravs de um modelo de transao. Existem diversos modelos encontrados na literatura. Nesta seo sero abordados apenas quatro: Flat Transactions, Nested Transactions, Chained Transactions e Join Transactions. Flat Transaction. Modelo mais utilizado pela maioria dos Sistemas Gerenciadores de Banco de Dados (SGBD) e Gerenciadores de Transaes. Conhecida como modelo de transaes planas por apresentar uma nica camada de controle, ou seja, todas as operaes dentro da transao so tratadas como uma nica unidade de trabalho. Nested Transaction. Este modelo, tambm conhecido como Modelo de Transaes Aninhadas, possibilita que uma transao possa ser formada por vrias subtransaes. Em outras palavras, uma nica transao pode ser dividida em diversas unidades de trabalho, com cada unidade operando independente uma das outras. A propriedade de atomicidade vlida para as subtransaes. Alm disso, uma transao no pode ser validada at que todas as suas sub-transaes tenham sido finalizadas. Se uma transao for interrompida, todas as suas sub-transaes tambm sero. O contrrio no verdadeiro, j que se uma sub-transao for abortada a transao que a engloba pode: ignorar o erro; desfazer a sub-transao; iniciar uma outra subtransao. Chained Transaction. Tambm conhecido como Modelo de Transaes Encadeadas, esse modelo tem como objetivo desfazer as operaes de uma transao em caso de erro com a menor perda de trabalho possvel. Uma transao encadeada consiste em um conjunto de sub-transaes executadas seqencialmente, em que medida que as sub-transaes vo sendo executadas, so validadas e no podem mais ser desfeitas. Os 58

Curso Hibernate resultados do conjunto de transaes s sero visveis ao final da execuo de todas elas. Join Transaction. Esse modelo permite que duas transaes sejam unidas em uma s, de forma que todos os recursos passam a ser compartilhados. 14.2 TRANSAES E BANCO DE DADOS Uma transao de banco de dados formada por um conjunto de operaes que manipulam os dados. A atomicidade de uma transao garantida por duas operaes: commit e rollback. Os limites das operaes de uma transao devem ser demarcados. Assim, possvel saber a partir de qual operao a transao iniciada e em qual operao ela finalizada. Ao final da execuo da ltima operao que pertence transao, todas as alteraes no banco de dados realizadas pelas operaes que compe a transao devem ser confirmadas, ou seja, um commit realizado. Se houver algum erro durante a execuo de algumas das suas operaes, todas as operaes da transao que j foram executadas devem ser desfeitas, ou seja, um rollback realizado. A Figura 21 ilustra esses conceitos.

Figura 21 - Estados do sistema durante uma transao

14.3

AMBIENTES GERENCIADOS E NO GERENCIADOS As sees seguintes referem-se s definies dos conceitos relacionados a transaes JDBC e JTA, onde aparecem os

59

Curso Hibernate termos ambientes gerenciados e no gerenciados. Esta seo destina-se a explicar sucintamente o que so esses termos. Os ambientes gerenciados so aqueles caracterizados pela gerncia automtica de transaes realizadas por algum container. Exemplos de ambientes gerenciados so componentes EJB (Enteprise JavaBeans) executando em servidores de aplicaes (JBoss, Geronimo, etc). J os ambientes no gerenciados so cenrios onde no h nenhuma gerncia de transao, como por exemplo: Servlets, aplicaes desktop, etc. 14.4 TRANSAES JDBC A tecnologia JDBC (Java Database Connectivity) um conjunto de classes e interfaces escritas em Java, ou API, que realiza o envio de instrues SQL (Structured Query Language) para qualquer banco de dados relacional. Uma transao JDBC controlada pelo gerenciador de transaes SGBD e geralmente utilizada por ambientes no gerenciados. Utilizando um driver JDBC, o incio de uma transao feito implicitamente pelo mesmo. Embora alguns bancos de dados necessitem invocar uma sentena begin transaction explicitamente, com a API JDBC no preciso fazer isso. Uma transao finalizada aps a chamada do mtodo commit(). Caso algo acontea de errado, para desfazer o que foi feito dentro de uma transao, basta chamar o mtodo rollback(). Ambos, commit() e rollback(), so invocados a partir da conexo JDBC. A conexo JDBC possui um atributo auto-commit que especifica quando a transao ser finalizada. Se este atributo for definido como true, ou seja, se na conexo JDBC for invocado setAutoCommit(true), ativa-se o modo de auto commit. O modo auto commit significa que para cada instruo SQL uma nova transao criada e o commit realizado imediatamente aps a execuo e finalizao da mesma, no havendo a necessidade de aps cada transao invocar explicitamente o mtodo commit(). Em alguns casos, uma transao pode envolver o armazenamento de dados em vrios bancos de dados. Nessas situaes, o uso apenas do JDBC pode no garantir a 60

Curso Hibernate atomicidade. Dessa maneira, necessrio um gerenciador de transaes com suporte a transaes distribudas. A comunicao com esse gerenciador de transaes feita usando JTA (Java Transaction API). 14.5 TRANSAES JTA As transaes JTA so usadas em um ambiente gerencivel, onde existem transaes CMT (Container Managed Transactions). Neste tipo de transao no h a necessidade de programao explcita das delimitaes das transaes, esta tarefa realizada automaticamente pelo prprio container. Para isso, necessrio informar nos descritores dos EJBs a necessidade de suporte transacional s operaes e como ele deve gerenci-lo. O gerenciamento de transaes feito pelo Hibernate a partir da interface Transaction. 14.6 API PARA TRANSAES DO HIBERNATE A interface Transaction fornece mtodos para a declarao dos limites de uma transao. A Listagem 80 apresenta um exemplo de uso de transaes com a interface Transaction. A transao iniciada a partir da invocao ao mtodo session.beginTransaction(). No caso de um ambiente no gerenciado, uma transao JDBC na conexo JDBC iniciada. J no caso de um ambiente gerenciado, uma nova transao JTA criada, caso no exista nenhuma j criada. Casa j existe uma transao JTA, essa nova transao une-se a existente. A chamada ao mtodo tx.commit() faz com que os dados em memria sejam sincronizados com a base de dados. O Hibernate s realiza efetivamente o commit se o comando beginTransaction() iniciar uma nova transao (em ambos ambientes gerenciado ou no gerenciado). Se o beginTransaction() no iniciar uma nova transao (no caso de transaes JTA isso possvel), ento o estado em sesso apenas sincronizado com o banco de dados e a finalizao da transao feita de acordo com a primeira parte do cdigo fonte que a criou. Se ocorrer algum erro durante a execuo do mtodo acaoExecutada(), o mtodo tx.rollback() executado,

61

Curso Hibernate desfazendo o que foi feito at o momento em que o erro ocorreu. Observa-se que no final do cdigo a sesso finalizada a partir do comando session.close(), liberando a conexo JDBC e devolvendo-a para o pool de conexes.

Listagem 80 - Usando a Interface Transaction do Hibernate

14.7

FLUSHING Flushing o processo de sincronizar os dados em sesso (ou em memria) com o banco de dados. As mudanas nos objetos de domnio em memria feitas dentro do escopo de uma sesso (Session) no so imediatamente propagadas para o banco de dados. Isso permite ao Hibernate unir um conjunto de alteraes e fazer um nmero mnimo de interaes com o banco de dados, ajudando a minimizar a latncia na rede. A operao de flushing ocorre apenas em trs situaes: quando dado commit na transao, algumas vezes antes de uma consulta ser executada (em situaes que alteraes podem influenciar em seu resultado) e quando o mtodo Session.flush() invocado. O Hibernate possui um modo flush que pode ser definido a partir do comando session.setFlushMode(). Este modo pode assumir os seguintes valores: FlushMode.AUTO: valor padro. Faz com que o Hibernate no realize o processo de flushing antes de todas as consultas, somente realizar se as mudanas dentro da transao alterar seu resultado. FlushMode.COMMIT: especifica que os estados dos objetos em memria somente sero sincronizados com a 62

Curso Hibernate base de dados ao final da transao, ou seja, quando o mtodo commit() chamado. FlushMode.NEVER: especifica que a sincronizao s ser realizado diante da chamada explcita ao mtodo flush(). 14.8 NVEIS DE ISOLAMENTO DE UMA TRANSAO As bases de dados tentam assegurar que uma transao ocorra de forma isolada, ou seja, mesmo que estejam acontecendo outras transaes simultaneamente, como se ela estivesse ocorrendo sozinha. O nvel de isolamento de uma transao especifica quais dados esto visveis a uma sentena dentro de uma transao. Eles impactam diretamente no nvel de acesso concorrente a um mesmo alvo no banco de dados por transaes diferentes. Geralmente, o isolamento de transaes feito usando locking, que significa que uma transao pode bloquear temporariamente um dado para que outras transaes no o acessem no momento que ela o est utilizando. Muitos bancos de dados implementam o nvel de isolamento de uma transao atravs do modelo de controle concorrente multiverses (MCC Multiversion Concorrency Control). Dentre alguns fenmenos que podem ocorrer devido quebra de isolamento de uma transao esto trs: Dirty Read (Leitura Suja): uma transao tem acesso a dados modificados por uma outra transao ainda no finalizada que ocorre concorrentemente. Isso pode causar problema, pois pode ocorrer um erro dentro da transao que est modificando os dados e as suas alteraes serem desfeitas antes de confirmadas, ento possvel que a transao que acessa os dados j modificados esteja trabalhando se baseando em dados incorretos. Nonrepeatable Read (Leitura que no pode ser repetida): uma transao l mais de uma vez um mesmo dado e constata que h valores distintos em cada leitura. Por exemplo, uma transao A l uma linha do banco; uma transao B modifica essa mesma linha e

63

Curso Hibernate finalizada (commit) antes que a transao A; a transao A l novamente esta linha e obtm dados diferentes. Phantom Read (Leitura Fantasma): em uma mesma transao uma consulta pode ser executada mais de uma vez e retornar resultados diferentes. Isso pode ocorrer devido a uma outra transao realizar mudanas que afetem os dados consultados. Por exemplo, uma transao A l todas as linhas que satisfazem uma condio WHERE; uma transao B insere uma nova linha que satisfaz a mesma condio antes da transao A ter sido finalizada; a transao A reavalia a condio WHERE e encontra uma linha fantasma na mesma consulta feita anteriormente. Existem quatro nveis de isolamento da transao em SQL. Eles se diferenciam de acordo com a ocorrncia ou no dos fenmenos anteriormente descritos, como mostrado na Tabela 4.
Nvel de Isolamento Read Uncommited Read Commited Repeatable Read Serializable Dirty Read Nonrepeatable Phanton Read

SIM NO NO NO

SIM SIM NO NO

SIM SIM SIM NO

Tabela 4 - Nveis de Isolamento da Transao em SQL

A escolha do nvel de isolamento Read Uncommited no recomendada para banco de dados relacionais, j que permite ler inconsistncias e informaes parciais (mudanas realizadas por uma transao ainda no finalizada podem ser lidas por outra transao). Se a primeira transao no for concluda, mudanas na base de dados realizadas pela segunda transao podem deix-la com um estado inconsistente. Com o nvel Read Commited, uma transao somente visualiza mudanas feitas por outras transaes quando confirmadas, permitindo que transaes s acessem estados consistentes do banco. No caso de uma atualizao/excluso de uma linha de alguma tabela por uma transao, pode ser que a mesma 64

Curso Hibernate tenha acabado de ser modificada por uma transao concorrente. Nesta situao, a transao que pretende atualizar fica esperando a transao de atualizao que iniciou primeiro ser efetivada ou desfeita. Se as atualizaes da primeira transao forem desfeitas, seus efeitos sero desconsiderados e a segunda transao efetivar suas mudanas considerando a linha da tabela anteriormente lida. Caso contrrio, a segunda transao ir ignorar a atualizao caso a linha tenha sido excluda ou aplicar a sua atualizao na verso atualizada da linha. O nvel Repeatable Read no permite que uma transao sobrescreva os dados alterados por uma transao concorrente. Uma transao pode obter uma imagem completa da base de dados quando iniciada. Este nvel ideal para a gerao de relatrios, pois em uma mesma transao, um registro lido diversas vezes e seu valor se mantm o mesmo at que a prpria transao altere seu valor. Em relao ao nvel Serializable, ele fornece o nvel de isolamento de transao mais rigoroso. Ele permite uma execuo serial das transaes, como se todas as transaes fossem executadas uma atrs da outra. Dessa forma, pode-se perder um pouco do desempenho da aplicao.

14.9

CONFIGURANDO O NVEL DE ISOLAMENTO No Hibernate cada nvel de isolamento identificado por um nmero: 1: Read Uncommited 2: Read Commited 4: Repeatable Read 8: Serializable Para configur-lo basta incluir a linha presente na Listagem 81 no arquivo de configurao *.cfg.xml. Neste exemplo, o nvel de isolamento foi definido como Repeatable Read.

65

Curso Hibernate

Listagem 81

Configurao do Nvel de Isolamento

15. CONCORRNCIA Em algumas situaes pode acontecer que duas ou mais transaes que ocorrem paralelamente leiam e atualizem o mesmo dado. Considerando que duas transaes leiam um mesmo dado x quase que simultaneamente. Ambas as transaes vo manipular esse mesmo dado com operaes diferentes e atualiz-lo na base de dados. Para exemplificar, a Listagem 82 apresenta um exemplo de duas transaes concorrentes manipulando o mesmo dado x. No primeiro passo, ambas as transaes lem o dado x com o mesmo valor (2). Em seguida, T1 soma o valor x que leu com 1 e o valor de x para T1 passa a ser 3 (2 + 1). J T2, soma o valor de x lido a 3 e x passa a ter o valor 5 (2 + 3). Por fim, ambos T1 e T2 gravaro os novos valores de x calculados na base de dados, respectivamente. Como no h controle de concorrncia de acesso ao dado x, o seu valor final corresponder a 5, ou seja, o valor calculado por T2, significando que as alteraes feitas por T1 foram descartadas.

Listagem 82

Exemplo de Transaes Concorrentes

Para evitar a situao descrita anteriormente, deve-se controlar o acesso concorrente ao dado, ou seja, deve-se implementar o mecanismo de Locking. O gerenciamento de locking e da concorrncia pode ser feito de duas formas: Pessimista: utilizar o controle pessimista significa que se uma transao T1 l um dado e tem a inteno de atualiz-lo, esse dado ser bloqueado (nenhuma outra transao poder l-lo) at que T1 o libere, normalmente aps a sua atualizao.

66

Curso Hibernate Otimista: utilizar o controle otimista significa que se T1 l e altera um dado ele no ser bloqueado durante o intervalo entre a leitura e atualizao. Caso uma outra transao T2 tenha lido esse mesmo dado antes de T1 o atualiz-lo tente alter-lo em seguida na base de dados, um erro de violao de concorrncia deve ser gerado. 15.1 LOCK OTIMISTA Para ilustrar o gerenciamento do tipo otimista, um exemplo dado a partir das Figura 22 e Figura 23. O problema mostrado na Figura 22, onde, inicialmente, duas transaes (ilustradas por Thread 1 e Thread 2) acessam um mesmo dado na base de dados (SELECT Dado), uma seguida da outra. Logo em seguida, a primeira transao (Thread 1) atualiza este dado na base de dados e depois quem tambm o atualiza a segunda transao (Thread 2). Nesta abordagem otimista, acontece que a atualizao do dado feita pela segunda transao sobrescreve a atualizao realizada pela primeira, ou seja, a atualizao feita pela primeira transao perdida.

Figura 22 - Loocking Otimista: Atualizao Sobrescrita

Para resolver o problema descrito anteriormente com a abordagem otimista, pode-se utilizar o conceito de Version Number, que um padro utilizado para versionar numericamente os dados de uma linha de uma tabela na base de dados. Por exemplo, na Figura 23, tambm, inicialmente, 67

Curso Hibernate duas transaes (ilustradas por App 1 e App 2) acessam um mesmo dado na base de dados (SELECT Dado), uma seguida da outra. Com isso, esse mesmo dado nas duas transaes so rotulados com a verso atual dele na base de dados, no caso, Verso 1. Logo em seguida, a segunda transao atualiza este dado. Quando a atualizao vai ser feita, verificado se a verso do dado na transao corresponde verso dele na base de dados. Nesta primeira atualizao, a verso da transao 1 e a da base de dados tambm. Como elas so iguais, a atualizao efetivada e a verso do dado na base de dados passa a ser a Verso 2. Por fim, a primeira transao vai tambm atualizar este mesmo dado. Dessa forma, tambm feita uma comparao entre as verses do dado na transao e na base de dados. Neste caso, a verso na transao a 1 e na base de dados 2, ou seja, as verses no correspondem. Assim, um erro disparado e a atualizao desejada pela primeira transao no concretizada, evitando que a atualizao feita pela segunda transao no seja desfeita.

Figura 23 - Loocking Otimista: Abodargem com Version Number

Com o Hibernate, uma forma de utilizar o versionamento dos dados utilizar a anotao @Version no mapeamento das tabelas. Para exemplificar o seu uso, considera-se a classe ContaCorrente presente na Listagem 83 que ser mapeada para a tabela conta_corrente na base de dados. Dentre os diversos atributos da classe t o atributo denominado versao do tipo inteiro que ir guardar a verso atual das linhas da tabela.

68

Curso Hibernate

Listagem 83 - Classe de Domnio: ContaCorrente. Primeira Estratgia Locking Otimista

A tabela conta_corrente tambm deve ter uma coluna para onde esse atributo versao ser mapeado, como mostrado no script de criao da tabela na Listagem 84. De acordo com o mapeamento feito na classe ContaCorrente, toda vez que uma determinada linha for atualizada na base de dados, a sua coluna versao ser incrementada de uma unidade, indicando a nova verso dos dados.

Listagem 84 - Script para a Criao da Tabela conta_corrente

Considerando o exemplo apresentado na Listagem 85, em que um objeto ContaCorrente criado e persistido na base de dados, observa-se o resultado presente na Figura 24 da

69

Curso Hibernate insero do mesmo como linha da tabela correspondente. No caso, a linha foi inserida e a verso atual da mesma assumiu o valor zero, correspondendo primeira verso.

Listagem 85

Persistindo Objeto com Atributo Version Number

Figura 24 - Resultado da Execuo do Cdigo Presente na Listagem 85

Caso a prxima operao seja uma atualizao do objeto que corresponde a esta linha, como mostrado na Listagem 86, verifica-se o resultado na Figura 25, onde os dados da conta corrente foram atualizados. Tambm teve-se a coluna versao sendo incrementada de uma unidade, atualizando a informao de versionamento da linha da tabela.

Listagem 86

Atualizando Objeto com Atributo Version Number

70

Curso Hibernate

Figura 25 - Resultado da Execuo do Cdigo Presente na Listagem 86

Outra forma de implementar o lock otimista utilizando o atributo que representa a verso do dado como sendo do tipo timestamp. Neste caso, a classe ContaCorrente do exemplo anterior ao invs de ter um atributo inteiro para guardar a verso do dado, teria uma atributo do tipo java.util.Date para guardar o instante no tempo da ltima atualizao. Neste caso, a classe de domnio com o mapeamento seria equivalente mostrada na Listagem 87. Neste exemplo, a tabela conta_corrente deve conter uma coluna do tipo timestamp denominada data_ultima_atualizao.

Listagem 87 - Classe de Domnio: ContaCorrente. Segunda Estratgia Locking Otimista

71

Curso Hibernate Se a tabela no possuir uma coluna para guardar a verso do dado ou a data da ltima atualizao, com Hibernate, h uma outra forma de implementar o lock otimista, porm essa abordagem s deve ser utilizada para objetos que so modificados e atualizados em uma mesma sesso (Session). Se este no for o caso, deve-se utilizar uma das duas abordagens citadas anteriormente. Com essa ltima abordagem, quando uma determinada linha vai ser atualizada, o Hibernate verifica se os dados dessa linha correspondem aos mesmos dados que foi recuperado. Caso afirmativo, a atualizao efetuada. Para isso, no mapeamento da tabela, deve-se utilizar o atributo optimisticLock = OptimisticLockType.ALL da anotao @org.hibernate.annotations.Entity (Alm da anotao javax.persistence.Entity), como mostrado na Listagem 91.

Listagem 88 - Classe de Domnio: ContaCorrente. Terceira Estratgia Locking Otimista

Dessa maneira, quando uma linha dessa tabela fosse atualizada, o SQL equivalente gerado para a atualizao seria como o exibido na Listagem 89. Neste exemplo, considera-se a atualizao do saldo para R$ 1.500,00 de uma determinada conta de saldo R$ 1.000,00.

72

Curso Hibernate

Listagem 89 - Exemplo com Lockin Otimista: optimisticLock = OptimisticLockType.ALL

15.2

LOCK PESSIMISTA A estratgia de lock pessimista para proibir o acesso concorrente a um mesmo dado da base de dados feita bloqueando o mesmo at que a transao seja finalizada. Alguns banco de dados, como o Oracle e PostgreSQL, utilizam a construo SQL SELECT FOR UPDATE para bloquear o dado at que o mesmo seja atualizado. O Hibernate fornece um conjunto de modos de lock (constantes disponveis na classe LockMode) que podem ser utilizados para implementar o lock pessimista. Considerando o exemplo da Listagem 90, onde um determinado aluno consultado na base de dados e tem seu nome atualizado. Neste caso, no h um bloqueio ao dado, ento qualquer outra transao pode acessar este mesmo dado concorrentemente e modific-lo, de forma que poder ocorrer uma incosistncia dos dados. Na Listagem 91, h um exemplo de uso do lock pessimista para resolver este problema, bastando passar a constante LockMode.UPGRADE como terceiro argumento do mtodo get do objeto Session.

Listagem 90 - Exemplo de Transao sem Lock

Listagem 91 - Exemplo de Transao com Lock Pessimista: LockMode.UPGRADE

73

Curso Hibernate O mtodo get do objeto Session pode receber como terceiro argumento para implementar o lock pessimista as seguintes constantes. Lock.NONE: S realiza a consulta ao banco se o objeto no estiver no cache1. Lock.READ: Ignora os dados no cache e faz verificao de verso para assegurar-se de que o objeto em memria o mesmo que est no banco. Lock.UPDGRADE: Ignora os dados no cache, faz verificao de verso (se aplicvel) e obtm lock pessimista do banco (se suportado). Lock.UPDGRADE_NOWAIT: Mesmo que UPGRADE, mas desabilita a espera por liberao de locks, e dispara uma exceo se o lock no puder ser obtido. Caso especial do Oracle que utiliza a clusula SELECT ... FOR UPDATE NOWAIT para realizar locks. Lock.WRITE: Obtida automaticamente quando o Hibernate realiza alguma insero ou atualizao na base de dados. 16. CACHING O cache uma tcnica comumente utilizada para aprimorar o desempenho da aplicao no que diz respeito ao acesso ao banco de dados. Com o cache possvel fazer uma cpia local dos dados, evitando acesso ao banco sempre que a aplicao precise, por exemplo, acessar dados que nunca ou raramente so alterados e dados no crticos. O uso do cache no indicado para manipulao de dados crticos, de dados que mudam freqentemente ou de dados que so compartilhados com outras aplicaes legadas. Uma m escolha das classes que tero objetos em cache pode gerar inconsistncias na base de dados. Existem trs tipos principais de chache: Escopo de Transao: utilizado no escopo da transao, ou seja, cada transao possui seu prprio cache. Duas transaes diferentes no compartilham o mesmo cach. Escopo de Processo: h o compartilhamento do cache entre uma ou mais transaes. Os dados no escopo do cache de uma

74

Curso Hibernate transao podem ser acessados por uma outra transao que executa concorrentemente, podendo provocar implicaes relacionadas ao nvel de isolamento. Escopo de Cluster: cache compartilhado por vrios processos pertencentes a mquinas virtuais distintas e deve ser replicado por todos os ns do cluster. Considerando o cache no escopo da transao, se na transao houver mais de uma consulta a dados com mesmas identidades de banco de dados, a mesma instncia do objeto Java ser retornada. Pode ser tambm que o mecanismo de persistncia opte por implementar identidade no escopo do processo, de forma que a identidade do objeto seja equivalente identidade do banco de dados. Assim, se a consulta a dados em transaes que executam concorrentemente for feita a partir de identificadores de banco de dados iguais, o resultado tambm ser o mesmo objeto Java. Outra forma de se proceder retornar os dados em forma de novos objetos. Assim, cada transao teria seu prprio objeto Java representando o mesmo dado no banco. No escopo de cluster, necessrio haver comunicao remota, em que os dados so sempre manipulados por cpias. Em geral, utilizase o JavaGroups, que consiste em uma plataforma utilizada como infra-estrutura para a sincronizao do cache no no cluster. Nas situaes em que estratgias de MOR permitem que vrias transaes manipulem uma mesma instncia de objeto persistente, importante ter um controle de concorrncia eficiente, por exemplo, bloqueando um dado enquanto ele no atualizado. Utilizando o Hibernate, ter-se- um conjunto diferente de instncias para cada transao, ou seja, tem-se identidade no escopo da transao. 16.1 ARQUITETURA DE CACHE COM HIBERNATE A Figura 26 apresenta a arquiteura de cache com o Hibernate. Existem dois nveis de caches. O primeiro nvel encontra-se em nvel de uma sesso (Session), ou em nvel de transao de banco de dados ou at mesmo de uma transao de aplicao. Este nvel no pode ser desabilitado e garante a identifidade do objeto dentro da sesso/transao. Dessa forma, dentro de uma mesma sesso, garantida que se a aplicao requisitar o mesmo objeto persistente duas vezes, ela receber de volta mesma instncia, evitando um trfego maior na base de

75

Curso Hibernate dados. Com o uso do cache em nvel de transao, nunca podero existir diferentes representaes do mesmo registro de banco de dados ao trmino de uma transao, tendo apenas um objeto representando qualquer registro. Mudanas realizadas em um objeto, dentro de uma transao, so sempre visveis para qualquer outro cdigo executado dentro da mesma transao. Quando so feitas chamadas atravs dos mtodos: load(), find(), list(), iterate() ou filter() o contedo do objeto primeiramente procurado no nvel de cach. O segundo nvel de cache opcional e pode abranger o nvel do escopo do processo ou do cluster. um cache de estado e no de instncias persistentes. Por ser opcional, preciso configurar este nvel de cache para ser usado na aplicao. Cada classe que precisar ter objetos em cache possui uma configurao individual, pois cada uma ter particularidade de mapeamento.

Figura 26 - Arquitetura de Cach

O Cache Provider utilizado para informar qual poltica de

76

Curso Hibernate cache de segundo nvel ser utilizada na aplicao. Essa poltica definida no arquivo hibernate.cfg.xml a partir da propriedade hibernate.cache.provider_class e pode assumir algum dos valores abaixo: EHCache (org.hibernate.cache.EhCacheProvider): usado para o gerenciamento de caches no escopo do processo. Possui uma boa documentao e fcil de configurar. Alm disso, suporta cache de consultas que ser apresentado na prxima sesso. OSCache (org.hibernate.cache.OSCacheProvider): usado para o gerenciamento de caches no escopo do processo ou do cluster. SwarmCache (org.hibernate.cache.SwarmCacheProvider): usado para o gerenciamento de caches no escopo do cluster. No suporta cache de consultas. JBossCache (org.hibernate.cache.TreeCacheProvider): usado para o gerenciamento de caches no escopo do cluster. um servio de replicao por cluster transacional. Suporta cache de consultas. 16.2 MAPEANDO CACHE Quando se utiliza o segundo nvel de cache, importante utilizar uma estratgia para gerenciar o nvel de concorrncia dos dados. A estratgia de concorrncia uma mediadora, responsvel por armazenar e recuperar os dados no cache. Com o Hibernate, possvel utilizar uma de quatro estratgias: Transacional: utilizado em ambiente JTA (gerencivel) e para manter dados em cache so mais consultados do que atualizados. Garante o nvel de isolamento da transao at o nvel repeatable-read, em que o valor mantido durante toda a transao. Leitura/Escrita (Read-Write): utilizada se a aplicao precisar atualizar os dados que esto em cache. No deve ser utilizada quando o nvel de isolamento da transao for do tipo Serializable. Utilizado em ambientes que no utilizam cluters.

77

Curso Hibernate Nonstrict Read-Write: utilizada se os dados em cache dificilmente sejam atualizados, ou seja, se for quase que improvvel duas transaes atualizarem o mesmo dado simultaneamente. importante tambm a utilizao de um nvel rgido de isolamento da transao. No garante que o estado do cache seja sincronizado com o do banco de dados. Read-Only: utilizada se o cache for aplicado a dados da aplicao que somente so lidos, ou seja, nunca so modificados. Estratgia simples, segura em nvel de escopo de cluster e apresenta melhor performance. A Tabela 5 apresenta quais nveis de cache so suportados por quais polticas de cach.

Tabela 5

Polticas X Nveis de Cach

78