[Resolvido] hibernate - PropertyValueException ao persistir

5 respostas
F

Boa Noite pessoal,

Estou tendo o seguinte problema em meu código:

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.model.Medicamentos.nome

Código que dispara a exception, entityManager.persist(m);

Medicamentos m = new Medicamentos();
entityManager.persist(m);
list.add(m);
@Entity
@Table(name = "MEDICAMENTOS", catalog = "", schema = "")
@NamedQueries({@NamedQuery(name = "Medicamentos.findAll", query = "SELECT m FROM Medicamentos m"), @NamedQuery(name = "Medicamentos.findByIdmedicamento", query = "SELECT m FROM Medicamentos m WHERE m.idmedicamento = :idmedicamento"), @NamedQuery(name = "Medicamentos.findByNome", query = "SELECT m FROM Medicamentos m WHERE m.nome = :nome")})
public class Medicamentos implements Serializable {
    @Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
    private static final long serialVersionUID = 1L;

    @Id
    //@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "IDMEDICAMENTO" )
    @GeneratedValue(generator="IDMEDICAMENTO")
    @SequenceGenerator( name = "IDMEDICAMENTO", sequenceName = "MEDICAMENTOS_IDMEDICAMENTO_GEN", allocationSize = 20 )
    @Basic(optional = false)
    @Column(name = "IDMEDICAMENTO")
    private Integer idmedicamento;

    @Basic(optional = false)
    @Column(name = "NOME")
    private String nome;

    public Medicamentos() {
    }

// segue gets e sets

estou utilizando o FireBird, minha lista está vinculada a GUI com Bean Bindings, do mais nada de diferente, mas quando tento criar um novo objeto dá esse erro,
setei nome como possivel de nulo no Bean e dessa forma ele passa por esse ponto… mas quando executo

entityManager.getTransaction().commit();

acontece:

SEVERE: GDS Exception. 335544347. validation error for column NOME, value "*** null ***"
22/12/2008 22:00:09 org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: could not insert: [com.model.Medicamentos]

debugando, verifiquei que o objeto criado recebe normalmente os valores e o atributo nome nesse momento não está nulo…

tive alguns problemas com o campo auto numerico, relacionado com GenerateValue e etc… mas agora ele está recebendo o valor do sequence correto…
poderia ser relacionado com isso? alguma diferença entre objetos ao comitar?

alguem poderia me dar uma força, valeu!

5 Respostas

F

Preenchendo o atributo nome, legal ele funciona, mas como posso setar o Hibernate para que o valor de um atributo aceite nulo até que eu comite a transação?

já que adiciono o objeto vazio e após isso preencho os atributos?

mesmo marcando a anotation @Basic como true ele gera um erro por que meu campo no banco está como not null

com o TopLink estava funcionando normal dessa forma… quando passei para o Hibernate tive esse problema.

alguem pode me dar uma dica!?
Valeu

Y

Nao entendi bem a duvida, Fabio.

Voce quer adicionar o objeto vazio na session e depois setar os valores? Ou quer adicionar o registro no BD depois fazer um update nos valores?

No primeiro caso, apesar de estranho, nao ha problemas. A nao ser que o Hibernate faca a validacao dos “requireds” ja na hora que vc poe o objeto na session. Isso realmente eu nao sei pq nao uso esse recurso, faco a validacao antes de passar para a camada de persistencia e no BD. Se for esse o caso, provavelmente apenas liberando o null vc resolve o problema.

Se for o segundo caso, so se vc tirar a constraint no banco ou utilizar uma trigger.

P.S. Será que sou a unica pessoa no mundo a ter total aversao ao Hibernate com annotations? O negocio fica absolutamente ilegivel.

F

YvGa:
Nao entendi bem a duvida, Fabio.

Voce quer adicionar o objeto vazio na session e depois setar os valores? Ou quer adicionar o registro no BD depois fazer um update nos valores?

No primeiro caso, apesar de estranho, nao ha problemas. A nao ser que o Hibernate faca a validacao dos “requireds” ja na hora que vc poe o objeto na session. Isso realmente eu nao sei pq nao uso esse recurso, faco a validacao antes de passar para a camada de persistencia e no BD. Se for esse o caso, provavelmente apenas liberando o null vc resolve o problema.

Se for o segundo caso, so se vc tirar a constraint no banco ou utilizar uma trigger.

P.S. Será que sou a unica pessoa no mundo a ter total aversao ao Hibernate com annotations? O negocio fica absolutamente ilegivel.

Bom dia YvGa,

Então o que acontece é o seguinte, o sistema estava utilizando TOPLINK, e ao acionar o botão NOVO REGISTRO ele cria o objeto e coloca na session (persist()), depois o utilizador tem a possibilidade de alterar por exemplo o atributo nome e acionar SALVAR.

Mostrando o SQL percebi que o Hibernate faz o processo em 2 etapas, primeiro ele da um INSERT e depois se houve alteração, um UPDATE, putz… normal né… , mas no INSERT o objeto tem os atributos nulos, ai o FireBird reclama por causa do Not-Null.

O problema é que no TOPLINK essa codificação funcionava, não debuguei o SQL que ele gera mais acredito que ele deve verificar a existencia de alterações no estado do objeto e ao inves de efetuar INSERT(com o está inicial do objeto, campo NOME null) + UPDATE da alteração de estado, ele atualiza o estado e faz apenas o INSERT já com o objeto preenchido, isso é uma suposição, por que ele não reclama do campo nulo.

Existe algum comando que faça o Hibernate efetuar essa verificação e inibir a etapa do UPDATE?

A ideia seria o que você falou, colocar o objeto na sessão, permitir alterações no seu estado e por fim comitar a transação persistindo os novos registro e os alterados (de um Jlist).

Se não existir vou ter que persist() apenas quando o utilizardor clicar em salvar assim pego os objetos já preenchidos e evito o conflito do null.

obs. sou iniciante em ORM.

obrigado.

Y

Fabio, o Hibernate só faz o insert na hora do commit, se ele esta fazendo antes deve ser algo configuravel. E o update ele faz somente se houve alteracao. Mesmo que vc chame explicitamente o session.save(), se o Hibernate verificar que nao houve alteracao ele nao faz o update (Quando vc utiliza os UserTypes ele faz um insert depois um update, mas provavelmente nao tem nada a ver com seu problema.


Mostrando o SQL percebi que o Hibernate faz o processo em 2 etapas, primeiro ele da um INSERT e depois se houve alteração, um UPDATE, putz… normal né… , mas no INSERT o objeto tem os atributos nulos, ai o FireBird reclama por causa do Not-Null.

É aqui que eu nao estou entendendo, ao clicar em novo registro vc chama o session.persist(), isso? Se for isso o Hibernate tentara fazer o Insert e o Firebird vai reclamar. Nao tem jeito, nao sei como o Toplink trata isso. Mas com o Hibernate ele tentará por nulo em uma coluna not-null.

Ainda esta um pouco confuso pra mim, mas a solucao seria nao fazer o persist no inicio. Manipular o objeto como for necessario e no final, chamar o session.save(objeto) e commitar. Isso nao eh possivel?

F

YvGa:
Fabio, o Hibernate só faz o insert na hora do commit, se ele esta fazendo antes deve ser algo configuravel. E o update ele faz somente se houve alteracao. Mesmo que vc chame explicitamente o session.save(), se o Hibernate verificar que nao houve alteracao ele nao faz o update (Quando vc utiliza os UserTypes ele faz um insert depois um update, mas provavelmente nao tem nada a ver com seu problema.

Na verdade pode ser feito a persistencia ao clicar em salvar… é que como estava funcionando acabei ficando com a pulga atráz da orelha… :?. e decidi pesquisar um pouco mais sobre.

É um form com um Jtable e um campo para o nome, um CRUD simples, com um JtableBinding, então dessa forma não era preciso verificar alteração na list do binding, clicou em NOVO, list.add(obj) e entity.persist(obj) e blz, era so commit() no SALVAR e boa.

Já alterei o codigo pra persistir tudo no final, mas realmente é interessante, o porque o TOPLINK não reclamava desse processo.

vou alterar o UP pro TOPLINK de novo e ver o SQL que ele ira gerar, so pra tirar a duvida e se realmente ele tratar diferente, como imagino vou postar o resultado.

de qualquer forma obrigado pela explicação, abraço!!

Criado 22 de dezembro de 2008
Ultima resposta 24 de dez. de 2008
Respostas 5
Participantes 2