Confusão: @NotNull vs. @Column (anulável = false) com JPA e Hibernate


242
  1. Quando eles aparecem em um campo / captador de um @Entity, qual é a diferença entre eles? (Eu persisto a Entidade através do Hibernate ).

  2. A qual estrutura e / ou especificação cada uma delas pertence?

  3. @NotNullestá localizado dentro javax.validation.constraints. No javax.validation.constraints.NotNulljavadoc diz

    O elemento anotado não deve ser nulo

    mas não fala da representação do elemento no banco de dados, por que eu adicionaria a restrição nullable=falseà coluna?

Respostas:


328

@NotNullé uma anotação de Validação de Bean JSR 303 . Não tem nada a ver com as restrições do banco de dados. Como o Hibernate é a implementação de referência do JSR 303, no entanto, ele captura essas restrições de maneira inteligente e as converte em restrições de banco de dados para você, então você recebe duas pelo preço de uma. @Column(nullable = false)é a maneira JPA de declarar uma coluna como não nula. Ou seja, o primeiro é destinado à validação e o segundo à indicação de detalhes do esquema do banco de dados. Você está apenas recebendo ajuda extra (e bem-vinda!) Do Hibernate nas anotações de validação.


2
Obrigado! Então, se eu quiser que a persistência do JPA não esteja vinculada à implementação do Hibernate (ou seja, mude para EJB3), preciso usar as duas anotações (para proibir nulo no campo e na coluna)?
rapt

3
Eu não sei. Não há especificação que diga que um provedor JPA deve reconhecer anotações JSR 303, mas isso não significa que outros fornecedores não. Não sei dizer se alguém faz ou não.
Ryan Stewart

7
Os fornecedores de JPA não precisam fornecer a implementação JSR303, mas são conforme a especificação necessária para fornecer a capacidade de integração com qualquer implementação JSR303 de terceiros. Portanto, embora o Hibernate forneça o JSR303, você pode, por qualquer motivo, decidir não usá-lo e usar outra pessoa ou usar uma implementação JPA como openJPA e usar outra pessoa para fornecer o JSR303. 'se eu quiser que a persistência do meu JPA não esteja vinculada à implementação do Hibernate (ou seja, altere o EJB3)' O JPA faz parte da especificação do EJB3.
Shahzeb 16/09

5
@ Shahzeb: A questão não é sobre quem suporta / fornece a validação JSR 303. É sobre qual ORM (s) reconhecer JSR 303 anotações como @NotNull, @Size, @Min, @Max, etc., e traduzi-los em restrições de banco de dados.
Ryan Stewart

1
Sim, mas meu comentário é válido no contexto do que o OP pediu no comentário subsequente que você não sabia.
Shahzeb 16/09

18

As versões mais recentes do provedor JPA de hibernação aplicam as restrições de validação de bean (JSR 303) como @NotNullDDL por padrão (graças aos hibernate.validator.apply_to_ddl propertypadrões de true). Mas não há garantia de que outros fornecedores de JPA façam ou tenham a capacidade de fazer isso.

Você deve usar anotações de validação de bean como @NotNullpara garantir que as propriedades do bean sejam configuradas com um valor nulo ao validar java beans na JVM (isso não tem nada a ver com restrições de banco de dados, mas na maioria das situações deve corresponder a elas).

Além disso, você deve usar a anotação JPA @Column(nullable = false)para fornecer dicas ao provedor jpa para gerar a DDL correta para criar colunas da tabela com as restrições de banco de dados desejadas. Se você pode ou deseja confiar em um provedor de JPA como o Hibernate, que aplica as restrições de validação de bean ao DDL por padrão, você pode omiti-las.


10

É interessante notar que todas as fontes enfatizam que @Column (nulo = falso) é usado apenas para geração de DDL.

No entanto, mesmo se não houver anotação @NotNull e a opção hibernate.check_nullability estiver configurada como true, o Hibernate executará a validação das entidades a serem persistidas.

Ele lançará PropertyValueException dizendo que "a propriedade not-null faz referência a um valor nulo ou transitório", se os atributos nullable = false não tiverem valores, mesmo que essas restrições não sejam implementadas na camada do banco de dados.

Mais informações sobre a opção hibernate.check_nullability estão disponíveis aqui: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .


7

A APP @Column anotação

O nullableatributo da @Columnanotação tem dois propósitos:

  • é usado pela ferramenta de geração de esquema
  • é usado pelo Hibernate durante a descarga do contexto de persistência

Ferramenta de geração de esquema

A ferramenta de geração de esquema HBM2DDL converte o @Column(nullable = false)atributo de entidade em uma NOT NULLrestrição para a coluna da tabela associada ao gerar a CREATE TABLEinstrução.

Como expliquei no Guia do Usuário do Hibernate , é melhor usar uma ferramenta como Flyway em vez de confiar no mecanismo HBM2DDL para gerar o esquema do banco de dados.

Liberação de contexto de persistência

Ao liberar o contexto de persistência, o Hibernate ORM também usa o @Column(nullable = false)atributo de entidade:

new Nullability( session ).checkNullability( values, persister, true );

Se a validação falhar, o Hibernate lançará PropertyValueExceptionae impedirá que a instrução INSERT ou UPDATE seja executada desnecessariamente:

if ( !nullability[i] && value == null ) {
    //check basic level one nullablilty
    throw new PropertyValueException(
            "not-null property references a null or transient value",
            persister.getEntityName(),
            persister.getPropertyNames()[i]
        );    
}

Para mais detalhes sobre como o mecanismo de liberação do Hibernate funciona, consulte este artigo .

A @NotNullanotação de validação de bean

A @NotNullanotação é definida pelo Bean Validation e, assim como o Hibernate ORM é a implementação JPA mais popular, a implementação mais popular do Bean Validation é o Hibernate Validator estrutura .

Ao usar o Hibernate Validator junto com o Hibernate ORM, o Hibernate Validator emitirá um ConstraintViolationao validar a entidade.


Por que você afirma que a via aérea é melhor do que gerar esquema?
Andronicus

1
Essa é uma boa observação. Atualizei a resposta com um link de referência.
Vlad Mihalcea

Obrigado pela referência e ótima resposta!
Andronicus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.