-
Oct 30th, 2007, 03:43 AM
#1
ids for this class must be manually assigned before calling save()
Hi I am new with hibernate and have problem trying to insert and object onto the database. I get the following exception.
Sorry for posting my entire code here but I am just clueless on how to resolve this. I appreciate any help you can give me. Many thanks!
Jeev
Exception in thread "main"
org.springframework.orm.hibernate3.HibernateSystem Exception: ids for this class must be manually assigned before calling save(): spar.comms.ops.impl.Pattern; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): spar.comms.ops.impl.Pattern
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): spar.comms.ops.impl.Pattern
at org.hibernate.id.Assigned.generate(Assigned.java:3 3)
I know that this has to do with the fact that I am using assigned id. I read somewhere that this could be resolved by using timestamp. Hence my code below
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="spar.comms.ops.impl.Pattern" table="patternsetdatabase">
<id name="patternId" column="PatternId">
<generator class="assigned"/>
</id>
<property name="thumbNailFile" type="java.lang.String" column="ThumbNailFile" />
<property name="imageFile" type="java.lang.String" column="ImageFile" />
<property name="siftDescriptorFile" type="java.lang.String" column="SIFTDescriptorFile" />
<property name="versionNumber" type="java.lang.String" column="VersionNumber" />
<property name="quantMatrixVectorRow" type="java.lang.Integer" column="QuantMatrixVectorRow" />
<!-- <timestamp name="timeStamp" column="TimeStamp" source="vm" generated="always" />-->
<property name="timeStamp" type = "timestamp" column="TimeStamp"/>
</class>
package spar.comms.ops.impl;
import java.sql.Timestamp;
import spar.comms.ops.OperationData;
/**
*
* @author Jeevan
*/
public class Pattern extends OperationData{
private String patternId;
private String thumbNailFile;
private String siftDescriptorFile;
private String versionNumber;
private String imageFile;
private Timestamp timeStamp;
private int quantMatrixVectorRow;
public Timestamp getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(Timestamp timeStamp) {
this.timeStamp = timeStamp;
}
public String getImageFile() {
return imageFile;
}
public void setImageFile(String imageFile) {
this.imageFile = imageFile;
}
public String getPatternId() {
return patternId;
}
public void setPatternId(String patternId) {
this.patternId = patternId;
}
public int getQuantMatrixVectorRow() {
return quantMatrixVectorRow;
}
public void setQuantMatrixVectorRow(int quantMatrixVectorRow) {
this.quantMatrixVectorRow = quantMatrixVectorRow;
}
public String getSiftDescriptorFile() {
return siftDescriptorFile;
}
public void setSiftDescriptorFile(String siftDescriptorFile) {
this.siftDescriptorFile = siftDescriptorFile;
}
public String getThumbNailFile() {
return thumbNailFile;
}
public void setThumbNailFile(String thumbNailFile) {
this.thumbNailFile = thumbNailFile;
}
public String getVersionNumber() {
return versionNumber;
}
public void setVersionNumber(String versionNumber) {
this.versionNumber = versionNumber;
}
}
public class PatternDBAccess {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate template) {
this.hibernateTemplate = template;
}
public void updatePattern(Pattern pattern){
this.hibernateTemplate.saveOrUpdate(pattern);
}//end updatePattern
And in the Main class
PatternDBAccess dbAccess =(PatternDBAccess) context.getBean("patternDBAccess");
Pattern pattern1 = new Pattern();
pattern1.setPatternId("test1");
pattern1.setQuantMatrixVectorRow(1);
pattern1.setSiftDescriptorFile("testing");
pattern1.setThumbNailFile("testing");
pattern1.setImageFile("testing");
pattern1.setVersionNumber("test1");
dbAccess.updatePattern(pattern1);
-
Oct 30th, 2007, 06:07 AM
#2
"Assigned" generator means exactly that - you need to provide the id before calling save().
-
Oct 30th, 2007, 06:12 AM
#3
Thanks dejanp,
But that is what confuses me. Don't I assign the id when I call my bean's setPatternId(). That is done before I call updatePattern which is essentially
public void updatePattern(Pattern pattern){
this.hibernateTemplate.saveOrUpdate(pattern);
}//end updatePattern
So the id has been assigned, no?
Thanks again!
Jeev
-
Oct 30th, 2007, 06:26 AM
#4
Using "assigned" generator and saveOrUpdate is not what I'd suggest. Try using save().
-
Oct 30th, 2007, 06:35 AM
#5
Thanks again DejanP.
Is there a problem with saveOrUpdate()?
The thing is, I would like to create a simple interface to the database. Through one method call, the bean passed in would either be inserted if it doesn't exist or it would be updated if it already exists. I thought saveOrUpdate() would do that just fine. However, I read somewhere that this can be problem with assigned id, but also read somewhere that it can be overcome by including a timestamp field in the bean. Apparently hibernate would decide whether to insert or update depending on the timestamp field. But that doesn't seem to work. Do you know of a good way of resolving this. Once again many thanks!
Jeev
-
Oct 30th, 2007, 07:32 AM
#6
OK, I have rewritten my updatePattern() method to not use HibernateTemplate.saveOrUpdate() but as the follows.
public void saveOrUpdatePattern(Pattern pattern){
Pattern patternx =(Pattern) this.hibernateTemplate.get(pattern.getClass(),patt ern.getPatternId());
if(patternx!=null){
this.hibernateTemplate.merge(pattern);
}//end if
else{
this.hibernateTemplate.save(pattern);
}
this.hibernateTemplate.flush();
}//end updatePattern
However, I get the following exception when i call merge(). I thought merge() was just supposed to copy the fields of the non-persistence object onto the row with the same primary key id?
Really appreciate any advice you can give.
Jeev
Exception in thread "main" org.springframework.dao.DataIntegrityViolationExce ption: Could not execute JDBC batch update; nested exception is org.hibernate.exception.ConstraintViolationExcepti on: Could not execute JDBC batch update
Caused by: org.hibernate.exception.ConstraintViolationExcepti on: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert( SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.conver t(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(Ab stractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(Ac tionQueue.java:237)
at org.hibernate.engine.ActionQueue.executeActions(Ac tionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListe ner.performExecutions(AbstractFlushingEventListene r.java:298)
at org.hibernate.event.def.DefaultFlushEventListener. onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.j ava:1000)
at org.springframework.orm.hibernate3.HibernateAccess or.flushIfNecessary(HibernateAccessor.java:388)
at org.springframework.orm.hibernate3.HibernateTempla te.execute(HibernateTemplate.java:363)
at org.springframework.orm.hibernate3.HibernateTempla te.merge(HibernateTemplate.java:752)
at spar.comms.ops.impl.PatternDBAccess.saveOrUpdatePa ttern(PatternDBAccess.java:42)
at spar.testing.TestPatternDBAccess.main(TestPatternD BAccess.java:49)
Caused by: java.sql.BatchUpdateException: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'test2' for key 1"
at com.mysql.jdbc.PreparedStatement.executeBatch(Prep aredStatement.java:1492)
at org.apache.commons.dbcp.DelegatingStatement.execut eBatch(DelegatingStatement.java:297)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch( BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(Ab stractBatcher.java:246)
-
Oct 30th, 2007, 07:44 AM
#7
The timestamp feature works, but not as you implemented it - you need to use <timestamp> element for it and and not a simple <property>.
I'd try to use update() instead of merge.
-
Oct 30th, 2007, 07:52 AM
#8
Thanks DejanP. Did just that and it works but am puzzled why methods like merge() and saveOrUpdate() do not do like what they said they do in the javadoc or Manning's Spring In Action book?
Anyway, thanks again.
Jeev
-
Oct 30th, 2007, 08:01 AM
#9
I must admit I never read a book on Spring or Hibernate and that I trust only the source code, javadocs and reference documentation (in that order).
Afaik - saveOrUpdate() works as advertised, it's just that generator=assigned is a special case that's not trivial to implement correctly. Merge is a bit more complicated - it's takes into account the first level cache of the session. I'd suggest reading Hibernate reference docs Chapter 10.
-
Oct 22nd, 2008, 10:53 AM
#10
5.1.4.7. Assigned Identifiers
If you want the application to assign identifiers (as opposed to having NHibernate generate them), you may use the assigned generator. This special generator will use the identifier value already assigned to the object's identifier property. Be very careful when using this feature to assign keys with business meaning (almost always a terrible design decision).
Due to its inherent nature, entities that use this generator cannot be saved via the ISession's SaveOrUpdate() method. Instead you have to explicitly specify to NHibernate if the object should be saved or updated by calling either the Save() or Update() method of the ISession.
quote fron NHibernate documentation
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules