0

I am writing Test cases for a webapp which requires me to mock controllers and verify results from URL hits. However, I am getting the error "detached entity passed to persist". The webapp however is live and working without errors meaning the problem is with my test.

I use the following test-context for hibernate

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                     <prop key="org.hibernate.envers.audit_table_prefix">history_</prop>
                     <prop key="org.hibernate.envers.audit_table_suffix"></prop>
                     <prop key="org.hibernate.envers.revision_type_field_name">_REV_TYPE</prop>
                     <prop key="org.hibernate.envers.revision_on_collection_change">false</prop>
            <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
        </props>
    </property>

The context doesn't work for a table in the database where it gives the above error on updating an object using persist. The table schema simplified is as follows

'id' int(11) NOT NULL AUTO_INCREMENT,
'code' varchar(64) NOT NULL,
'num_added' int(11) NOT NULL DEFAULT '0',
'created' datetime NOT NULL,
'updates' datetime NOT NULL,
PRIMARY KEY('id'),
UNIQUE KEY 'uq_code' ('code')

I have tried other answers on stackoverflow suggesting that id must not be present in the object being persisted as it leads hibernate to belive that object is in sync with database, however leaving id empty still gives same error. Using merge instead of persist gives an error that says

"Duplicate entry 'M923' for key 'uq_code' ; SQL [n/a]; constraint [null]"

I have tried refreshing the session after every URL hit like so

private void refresh(){
    if(openSessionInViewFilter!=null){
       openSessionInViewFilter.destroy();
       openSessionInViewFilter = new OpenSessionInViewFilter();
       openSessionInViewFilter.setServletContext(servletContext);
       openSessionInViewFilter.setSessionFactoryBeanName("sessionFactory");

       this.controller = MockMvcBuilders.standaloneSetup(Controller).addFilters(openSessionInViewFilter).build();
    }
}

but the error remains the same. Similarly, turning session parameters singleSession and hibernate.transaction.auto_close_session to true/false also doesn't help. What is the problem here.

Sarthak Nigam
  • 117
  • 1
  • 10

1 Answers1

0

The error message says that the field Code must be unique in the database, but your test case is attempting to persist duplicates. Either your test case is using the same values repeatedly, or it is attempting to use values already in the database.

Duplicate entry 'M923' for key 'uq_code' 

'code' varchar(64) NOT NULL,
K.Nicholas
  • 10,956
  • 4
  • 46
  • 66
  • but that is the error I get if I replace persist(object) with merge(object) and I know that the values aren't repeated. Could it be something with my session? – Sarthak Nigam Mar 09 '16 at 17:45
  • Well, if it's detached, you can't use persist, you have to use merge. If it's a merge it shouldn't complain about the code value. Perhaps a separate test to insure that merge works with a unique key? Did you declare the unique key in the Entity? – K.Nicholas Mar 09 '16 at 18:45
  • Hi, yes i did, its a field called 'code'. Could it be a problem with my session? I am using the openSessionInViewFilter, does that have problems with merge? Also, does calling persist to update after calling merge to insert cause any problems – Sarthak Nigam Mar 13 '16 at 11:30
  • Don't know on both accounts, I just wouldn't use persist when I shoud be doing a merge. – K.Nicholas Mar 13 '16 at 13:07