Criar a aplicação contendo a classe persistente Aluno, o Managed Bean AlunoMB, o arquivo
indexemplo:xhtml e o arquivo listar.xhtml, conforme mostrados anteriormente.
Conceitos e Ciclo de Vida
Alguns conceitos são de extrema importância para o entendimento do Hibernate:
q
1 Ciclo de Vida de Persistência: estados e transições de estados que dizem respeito à persistência de um objeto;
1 Unidade de Trabalho: conjunto de operações que são consideradas como um grupo (algumas vezes atômico);
1 Contexto de Persistência: mecanismo que mantém todos os objetos persistentes, seus estados e modificações. Mantido por uma Session em Hibernate
Figura 7.2
Conteúdo de uma aplicação.
JA VA – F ra m ew or ks e A pl ic aç õe s Co rp or at iv as get() load() Query.list() Query.uniqueResult() Query.iterate() find() getReference() Query.getResultList() Query.getSingleResult() save() saveOrUpdate() persist() merge() evict() close() clear() delete() remove() update() saveOrUpdate() merge() lixo new Transiente Desligado Persistente lixo lixo Removido
A figura 7.3 mostra os estados e os métodos que fazem com que um objeto transite entre esses estados. Os estados são:
q
1 Transientes: instanciados com new. Não são persistidos imediatamente;
1 Persistentes: objetos que possuem um correspondente na base e já estão persistidos; 1 Removidos: objeto marcado para remoção no final do processo corrente;
1 Desligados: objetos persistidos, mas que estão fora de um contexto de persistência. Exemplo: objetos que ainda existem depois que uma sessão foi fechada. Não há garantia de sincronismo desses com a base.
Anotações
Para anotar uma entidade, usa-se @Entity. Por exemplo, a classe Pessoa a seguir será persistente:
@Entity
public class Pessoa { ...
}
Para criar um identificador único, que no banco de dados se reflete como uma chave primária, usa-se @Id, como no exemplo a seguir:
@Entity
public class Pessoa { @Id
private Long id; }
Para customizar o nome da tabela no banco de dados e o nome da coluna, usa-se @Table e @Column. No exemplo a seguir, o nome da tabela foi alterado. Se não for usado, o nome da tabela deve ser o mesmo nome da classe:
Figura 7.3
Ciclo de Vida de Objetos.
ão @Entity
@Table(name = “tb_pessoa”) public class Pessoa { @Id
private Long id; }
No exemplo a seguir, o nome da coluna também foi customizado. Se não for usado, o nome da coluna deve ser o mesmo nome do atributo da classe.
@Entity
@Table(name = “tb_pessoa”) public class Pessoa { @Id
@Column(name=“pess_id”) private Long id; }
q
Alguns atributos de @Column são:
1 length: limita a quantidade de caracteres em uma string; 1 nullable: se o campo pode ter null ou não;
1 unique: se a coluna pode ter campos repetidos ou não; 1 precision: quantidades de dígitos de um número decimal; 1 scale: quantidade de casas decimais de um número decimal. E seu uso pode ser observado no exemplo a seguir.
@Entity
public class Pessoa { @Id
private Long id;
@Column(length=30, nullable=false, unique=true) private String nome;
@Column(precision=3, scale=2) private BigDecimal altura; }
Deve-se manter a consistência entre os tamanhos na anotação e nas tabelas. O Hibernate possui ferramentas de Engenharia Reversa que conseguem crias as classes persistentes a partir de um banco de dados já criado, e vice-versa.
q
1 Deve-se manter a consistência entre o banco de dados e as anotações; 1 Hibernate tem ferramentas de Engenharia Reversa.
JA VA – F ra m ew or ks e A pl ic aç õe s Co rp or at iv as
Chaves primárias
Para chaves primárias simples, anota-se com @Id o atributo cujo campo é a chave.
q
São tipos permitidos para chaves primárias: 1 Tipos primitivos (e seus wrappers); 1 String;
1 java.util.Date; 1 java.sql.Date;
1 java.math.BigDecimal; 1 java.math.BigInteger.
Para chaves autogeradas, usa-se tipos discretos (inteiros). Para chaves compostas, cria-se uma classe contendo as respectivas chaves:
1 Classe que contém as chaves deve ser anotada com @Embeddable. Deve imple- mentar os métodos equals() e hashCode();
1 Na entidade, anota-se o atributo contendo a classe das chaves com @EmbeddedId (javax.persistence.EmbeddedId).
Os exemplos a seguir mostram o uso de chave composta.
@Embeddable
public class PessoaPK implements Serializable { @Column(name=”pess_idade”)
protected Integer idade;
@Column(name=”pess_cpf”) protected String CPF; public PessoaPK() {} // equals, hashCode } @Entity
public class Pessoa implements Serializable { @EmbeddedId
private PessoaPK pessoaPK;
private String endereco; // setters/getters }
q
Características de uma Classe de Chave Primária (composta): 1 Classe deve ser pública;
1 Propriedades devem ser públicas ou protegidas; 1 Deve ter um construtor público, sem argumentos; 1 Deve implementar hashCode() e equals(Object other); 1 Deve implementar Serializable;
1 Deve representar múltiplos atributos da classe de entidade;
1 Os nomes da classe de chave primária e dos atributos na entidade que são chaves primária, devem coincidir;
ão
Para geração automática de chaves primárias, usa-se @GeneratedValue, que possui os seguintes atributos:
q
strategy: maneira de gerar a chave primária, que pode ser:
1 GenerationType.AUTO: (default) usa o tipo de geração definido no banco de dados subjacente;
1 GenerationType.IDENTITY: atribui uma chave primária usando o campo identity da tabela;
1 GenerationType.SEQUENCE: atribui uma chave primária usando uma sequence; 1 GenerationType.TABLE: usa uma tabela criada para manter as chaves primárias. Quando a estratégia definida é via o uso de uma sequência, é preciso utilizar a anotação @SequenceGenerator e alguns atributos específicos.
q
@GeneratedValue(strategy=GenerationType.SEQUENCE)
1 Cria um sequenciador que atribui valores à chave primária na hora da persistência (antes do commit());
1 Pode ser um contador ou um elemento sequence do banco; 1 É global à aplicação: várias entidades podem usá-lo. Atributos de @SequenceGenerator:
1 name: nome da sequence, usado internamente pelas entidades na anotação @GeneratedValue;
1 initialValue: (default 1) valor inicial das sequências geradas;
1 allocationSize: (default 50) incremento usado na geração dos números; 1 sequenceName: o nome do elemento Sequence no banco de dados.
Os exemplos a seguir mostram dois tipos de sequenciadores. O primeiro inicia seu valor em 1 e retorna valores espaçados em 100.
@Entity
@SequenceGenerator(name=”seq”, initialValue=1, allocationSize=100)
public class Pessoa {
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator=”seq”) @Id
private long id; }
O próximo sequenciador usa uma entidade sequence do banco de dados para obter o próximo valor a ser gerado como Id.
@Entity
JA VA – F ra m ew or ks e A pl ic aç õe s Co rp or at iv as
Datas
Para persistência de Datas, usa-se em Java: 1 java.util.Date;
1 java.util.Calendar.
Esses tipos são mapeados automaticamente para os tipos de data/hora dos bancos de dados. Por default, a data e a hora são armazenados no banco. Para mudar o comporta- mento, usa-se:
q
@Temporal, que pode receber um dos seguintes valores: 1 TemporalType.DATE: armazena apenas data; 1 TemporalType.TIME: armazena apenas horário; 1 Temporal.TIMESTAMP: (default) armazena data e hora. O exemplo a seguir mostra o uso de datas.
@Entity
public class Pessoa {
@Id
@GeneratedValue
private Long id;
@Temporal(TemporalType.DATE)
private Calendar nascimento; }