Re: AssertionFailure null id in entry
In article <2b83b063-c6ea-4aae-b1f8-f357e99172fe@m34g2000hsf.googlegroups.com>, Stefanie Ertheld <Dooing@gmx.de> wrote:
Ok, shortened, this is what my mapping class looks like:
@Entity (access=AccessType.PROPERTY)
@Table(name= "MYTABLE", catalog= "MYCATALOG",
uniqueConstraints=
{...@javax.persistence.UniqueConstraint(columnNames=
{"MYROW1", "MYROW2", "MYROW3"})}
)
public class MYOBJECT implements Serializable{
private Integer id;
private String MYROW1;
private String MYROW2;
private String MYROW3;
@Id (generate=GeneratorType.AUTO)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMYROW1() {
return this.MYROW1;
}
@Column (insertable=true, updatable=true, name="MYROW1")
public void setMYROW1(String MYROW1) {
this.MYROW1 = MYROW1;
}
public String getMYROW2() {
return this.MYROW2;
}
@Column (insertable=true, updatable=true, name="MYROW2")
public void setMYROW2(String MYROW2) {
this.MYROW2 = MYROW2;
}
public String getMYROW3() {
return this.MYROW3;
}
@Column (insertable=true, updatable=true, name="MYROW3")
public void setMYROW3(String MYROW3) {
this.MYROW3 = MYROW3;
}
public boolean equals(Object o) {
if (this == o) return true;
return false;
}
public int hashCode(){
return -1;
}
public String toString(){
return "";
}
}
However, as stated before, when I have a duplicate unique key, it
throws the weird error ("dont flush the session...") I stated above.
Now deleted the id autoincrement field from my mapping class and used
the unique key as a primary key, so I used an aditional mapping class
just for this unique key - hmmmm makes me thinking - maybe the problem
was that you ALWAYS need a separate mapping class for key - be it a
primary, foreign or unique key - could this be the reason?!
Thanks in advance,
Stefanie
It would be easier to help if you were more precise. I searched the Hibernate
source for the error you mentioned, didn't find anything, and then noticed the
obvious typo.
The "don't flush" ... error only showed up 1 time, in
DefaultFlushEntityEventListener.
Here's the code:
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
);
}
}
}
Now Hibernate needs to do 2 things - it needs to persist an object to the
database, and it needs to get the persisted values reflected in the object. I
will not pretend to be a Hibernate expert - here's a few SWAGS:
Given that the class is called DefaultFlushEntityEventListener, Hibernate has
decided it's time to do a flush - that is, actually commit your insert/update
to the database. Given that the error occurs in the method checkId, it has
nothing to do with the surrogate key you mentioned earlier.The id is null -
and Hibernate does not know how to resolve it. If this is an update, it's a
programming error. But it sounds like it's an insert.
The hashcode method in your class is scary. It returns a constant -1. This is
bad. I don't know if it is relevant or not. Is there any chance this would
cause Hibernate to do an update when an insert is expected? I dunno. Remove it
or improve it. Seriously. No hashcode is better than this.
Hmm, looking at the Hibernate code again, I wonder if that is the issue. If
the id was not null, it would return from the first if statement:
if ( id != null && id instanceof DelayedPostInsertIdentifier )
So the id is null.
So the persister thinks it can extract the id from the entity ..
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)");
But it fails. I have not looked at the persister code. Again, a swag or 2 ...
1) Some thing is wrong with your code. Hibernate thinks the save is an update.
It needs the id.
2) Something is wrong with the annotation. It looks ok to me, but I don't use
MySql. At this point, we're talking about issues specific to the RDBMS used.
How is Id defined in the database? Some serial type? Does MySql use sequences
(Oracle and Postgres do)? Is this the appropriate annotation for a PK given
it's datatype for MySql? I dunno.
But I do know that Hibernate's persistor thinks it can get the id from the
object and fails.
HTH
Eric