Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: ids for this class must be manually assigned before calling save()

  1. #1
    Join Date
    Oct 2007
    Posts
    5

    Default 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);

  2. #2
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    "Assigned" generator means exactly that - you need to provide the id before calling save().

  3. #3
    Join Date
    Oct 2007
    Posts
    5

    Default

    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

  4. #4
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    Using "assigned" generator and saveOrUpdate is not what I'd suggest. Try using save().

  5. #5
    Join Date
    Oct 2007
    Posts
    5

    Default

    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

  6. #6
    Join Date
    Oct 2007
    Posts
    5

    Default

    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)

  7. #7
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    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.

  8. #8
    Join Date
    Oct 2007
    Posts
    5

    Default

    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

  9. #9
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    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.

  10. #10
    Join Date
    Oct 2008
    Posts
    1

    Wink

    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
  •