Hibernate [BUG?] AssertionFailure: null id in entry

Pessoal,

Estou com uma aplicação WEB usando Tomcat, Hibernate, MySQL e JSF.

Em um dos objetos persistentes tenho o seguinte mapeamento:

private Long id;
// e o mapeamento no .hbm.xml:
<id name="id" column="id" type="java.lang.Long">
	<generator class="identity"></generator> //Aqui eu já coloquei native também...
</id>

Ao criar o registro via Browser e mandar salvar, o hibernate está gerando o seguinte erro:

Olhando o erro, é lógico que o ID está nulo, eu quero inserir um registro no banco de dados, numa tabela com primary key auto_increment. Ou seja, quero que o banco retorne o valor, por isso ele entra como nulo.

Fora esse campo, a tabela possui vários outros campos e um deles é unique, tanto no banco como no mapeamento do hibernate.

Alguém pode oferecer uma luz?

Obrigado…

O método checkID() onde está lançando a exception:

public void checkId(Object object, EntityPersister persister, Serializable id, EntityMode entityMode) throws HibernateException {

	if ( id != null && id instanceof DelayedPostInsertIdentifier ) {
		// this is a situation where the entity id is assigned by a	post-insert generator
		// and was saved outside the transaction forcing it to be delayed
		return;
	}

	if ( persister.canExtractIdOutOfEntity() ) {

		Serializable oid = persister.getIdentifier( object, entityMode );
		if (id==null) {
			throw new AssertionFailure("null id in " + persister.getEntityName() + " entry (don't flush the Session after an exception occurs)");
		}
		if ( !persister.getIdentifierType().isEqual(id, oid, entityMode) ) {
			throw new HibernateException(
			"identifier of an instance of " +
			persister.getEntityName() +
			" was altered from " + id +
			" to " + oid
			);
		}
	}

}

Caso isso ajude.

[quote=Guilherme Gomes]O método checkID() onde está lançando a exception:

public void checkId(Object object, EntityPersister persister, Serializable id, EntityMode entityMode) throws HibernateException {

	if ( id != null && id instanceof DelayedPostInsertIdentifier ) {
		// this is a situation where the entity id is assigned by a	post-insert generator
		// and was saved outside the transaction forcing it to be delayed
		return;
	}

	if ( persister.canExtractIdOutOfEntity() ) {

		Serializable oid = persister.getIdentifier( object, entityMode );
		if (id==null) {
			throw new AssertionFailure("null id in " + persister.getEntityName() + " entry (don't flush the Session after an exception occurs)");
		}
		if ( !persister.getIdentifierType().isEqual(id, oid, entityMode) ) {
			throw new HibernateException(
			"identifier of an instance of " +
			persister.getEntityName() +
			" was altered from " + id +
			" to " + oid
			);
		}
	}

}

Caso isso ajude.[/quote]

Bem, se é bug ou não eu não sei, mas é no mínimo uma aplicação incorreta do conceito de assertivas. Um método público não deve validar parâmetros com assertivas.

[quote=victorwss][quote=Guilherme Gomes]O método checkID() onde está lançando a exception:

public void checkId(Object object, EntityPersister persister, Serializable id, EntityMode entityMode) throws HibernateException {...

Caso isso ajude.[/quote]

Bem, se é bug ou não eu não sei, mas é no mínimo uma aplicação incorreta do conceito de assertivas. Um método público não deve validar parâmetros com assertivas.[/quote]

Vitor. esse código é do hibernate … :idea:
org.hibernate.event.def.DefaultFlushEntityEventListener

Eu to passando pelo mesmo problema do Guilherme…

Se alguem souber, por favor da um help! :?

como resolveram?

Boa noite!

Eu já passei por essa situação. Comigo aconteceu logo após uma ConstraintViolationException do hibernate, então não conseguia fazer mais nada durante aquela sessão. Dei uma lida em alguns forums (inclusive aqui: http://www.guj.com.br/java/100669-problema-hibernate-entry-dont-flush-the-session-after-an-exception-occurs) , e disseram que o hibernate da rollback na transação e invalida as demais tentativas daquela sessão. Isso é até, de certa forma, o correto a se fazer, pois vc não tem certeza do estado do banco de dados após uma exceção, então acredito que o Hibernate proceda assim para que possa ser verificada a consistência do banco.

Como eu sei que era intencional meu erro de ConstraintViolationException, corrigi este problema simplesmente fechando e abrindo outra sessão:

catch (ConstraintViolationException e)
        {
            FacesContext.getCurrentInstance().addMessage("Mensagem", new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Este atributo já está cadastrado!", ""));

            ss.close();
            ss = factory.openSession();

        }

Mas como disse, deve ter cuidado com essa opção… no meu caso resolveu, mas foi por minha conta e risco!

Até +!

mas ai você abre a nova sessão e re-faz a transação?

Boa noite!

Neste caso nao, pois esse erro de Constraint é se já existe um objeto com os mesmos dados (atributos configurados como constraint) do que o objeto na view, então simplesmente exibo uma mensagem ao usuário que o objeto já existe, que ele não pode inseri-lo novamente.

Então não há necessidade de retentar a mesma transação, mas sim que ele altere os dados da view e tente novamente.

Até +!

Estou montando uma aplicação e encontrei o mesmo problema. Após muita pesquisa consegui resolver.
O problema é que de acordo com a mensagem de erro informado pelo Hibernate da a entender que o problema é no ID, “Olhando o erro, é lógico que o ID está nulo”. Porem no meu caso o erro não era esse.
Consegui resolver o problema após rever os arquivos xml de mapeamento (.hbm). Especificações de tipagem, limitações(Ex. length), e descrição do relacionamento tem que estar de acordo com o bd, caso contrario o hibernate retorna essa mensagem.

Espero ter ajudado!

Também passei por isso, mas o meu caso era justamente o que o caro colega, DutraJardim, comentou (valeu cara!): Era uma inconsistência entre o Hibernate e o BD. Esses tipos de problema em que a mensagem nada tem a ver com o que realmente acontece é que nos deixa loucos…

pessoal tbem estou passando por isso, como resolveram?
parte do meu codigo…

minha classe cliente

@Entity
@Table(name = "cliente")
public class Cliente implements java.io.Serializable {
    @Id
    @GeneratedValue
    private Integer codigo;
    @Column(name = "nome", unique = true)
    private String nome;
    @Column(name = "cpf", unique = true)
    private String cpf;
//outros atributos construtores e getters e setters

meu clienteDAO

public class ClienteDAO<Cliente> {

private Session session;

public void save(Cliente cliente) throws HibernateException {
        try {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();
            session.persist(cliente);
        } finally {
            session.getTransaction().commit();
        }
    }

a exception gerada

realmente é um erro estranho a solucao que tive foi remover o atributo da anotação unique dos campos e do banco, depois disso o erro nao aconteceu mais,
temporariamente vou ter q fazer uma consulta no aplicativo para nao haver nomes & cpf duplicados no banco de dados antes de inserir o registro apesar de nao ser a melhor pratica, pois como o vinigodoy disse sobrecarrega um pouco o banco com consultas