No momento de fazer o mapeamento objeto relacional, temos a opção de definir como vamos tratar as chaves primárias: se vamos trazer para a aplicação a responsabilidade de definir esse valor único (quando declaramos apenas a anotação @Id), ou se vamos deixar essa responsabilidade com o provedor de persistência (quando também declaramos a anotação @GeneratedValue).
Ao citar o termo provedor de persistência, saiba que estamos referenciando o framework escolhido para que a aplicação possa se comunicar com o banco de dados. Alguns exemplos são o Hibernate, EclipseLink e OpenJPA.
Neste documento será apresentado como utilizar a anotação @GeneratedValue.
@GeneratedValue
A anotação @GeneratedValue é utilizada para informar que a geração do valor do identificador único da entidade será gerenciada pelo provedor de persistência. Essa anotação deve ser adicionada logo após a anotação @Id. Quando não anotamos o campo com essa opção, significa que a responsabilidade de gerar e gerenciar as chaves primárias será da aplicação, em outras palavras, do nosso código, como vemos no exemplo a seguir:
@Entity
public class Produto {
@Id @GeneratedValue
private long id;
}
Com o código deste exemplo, a JPA passará a utilizar a estratégia de geração de chave primária do banco de dados ao qual a aplicação está conectada.
strategy
Caso optemos por modificar a estratégia de geração da chave primária, passamos essa informação no atributo strategy de @GeneratedValue. A JPA suporta quatro estratégias, definidas na enum GenerationType e explicadas na tabela a seguir.
Estratégia | Descrição |
GenerationType.AUTO | Valor padrão, deixa com o provedor de persistência a escolha da estratégia mais adequada de acordo com o banco de dados. |
GenerationType.IDENTITY | Informamos ao provedor de persistência que os valores a serem atribuídos ao identificador único serão gerados pela coluna de auto incremento do banco de dados. Assim, um valor para o identificador é gerado para cada registro inserido no banco. Alguns bancos de dados podem não suportar essa opção. |
GenerationType.SEQUENCE | Informamos ao provedor de persistência que os valores serão gerados a partir de uma sequence. Caso não seja especificado um nome para a sequence, será utilizada uma sequence padrão, a qual será global, para todas as entidades. Caso uma sequence seja especificada, o provedor passará a adotar essa sequence para criação das chaves primárias. Alguns bancos de dados podem não suportar essa opção. |
GenerationType.TABLE | Com a opção TABLE é necessário criar uma tabela para gerenciar as chaves primárias. Por causa da sobrecarga de consultas necessárias para manter a tabela atualizada, essa opção é pouco recomendada. |
Tabela 1. Estratégias de geração de chave primária suportadas pela JPA.
@Entity
public class Produto {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String nome;
//getters e setters omitidos
}
Neste caso, o identificador único será gerado pela coluna de auto incremento do banco de dados.
generator
Caso optemos por trabalhar com a estratégia de geração da chave primária conhecida como SEQUENCE, é comum declararmos outro atributo na anotação @GeneratedValue, o generator. Nele, especificamos um nome para a sequence, e esse mesmo nome será mapeado à sequence do banco de dados através da anotação @SequenceGenerator.
Na seção abaixo apresentamos um exemplo que demonstra como declarar esse atributo.
Exemplo prático
Suponha que criamos a entidade Pessoa e desejamos que o identificador único dessa entidade seja criado por uma sequence do banco de dados. Para isso, podemos fazer o mapeamento conforme o código abaixo:
@Entity
public class Pessoa {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator=”pessoa_sequence”)
@SequenceGenerator(name=”pessoa_sequence”, sequenceName=”pes_seq”)
private long id;
private String cpf;
private String nome;
//getters e setters omitidos...
}
Com a execução desse código será criada uma tabela de nome Pessoa no banco de dados (caso não exista e assim seja configurado) com as colunas id, cpf e nome, sendo id a chave primária cujo valor será gerado pela sequence de nome pes_seq do banco de dados.
Dessa vez, note que em @GeneratedValue também declaramos o atributo generator. Este recebe uma string, o nome da sequence que informamos em @SequenceGenerator. No atributo sequenceName, desta última anotação, apenas passamos o nome da sequence no banco de dados.