You should be able to add a "cascade" option of "save" (or one of the other options) to the response.answers set. Then you just have to send the Response object to hibernate and it figures it out and saves all the children answers for you.
The reason you're getting the error is that the response on the answers object does not have an id yet. And because answers.response also doesn't have a cascade set, it won't try to save it...it just says "whoops, I don't have the primary key". Ben On Mon, Aug 15, 2011 at 11:01 PM, Barbara Lerner <[email protected]>wrote: > I have a class called CodedResponse that has a field whose type is > Set<CodedAnswer>. The CodedAnswer class has a field whose type is > CodedResponse. When I try to persist a CodedAnswer object, I get an > exception that I don't understand how to fix. CodedResponses seem to > persist fine. Here are the details: > > org.hibernate.exception.GenericJDBCException > could not insert: [org.openmrs.module.draftforms.CodedAnswer] > > > org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103) > > org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91) > > org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) > > org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:40) > > org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158) > > org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2638) > > org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48) > org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250) > > org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298) > > org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181) > > org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107) > > org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187) > > org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172) > > org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94) > > org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70) > org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507) > org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499) > org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495) > * > org.openmrs.module.draftforms.db.hibernate.HibernateDraftFormsDAO.saveOrUpdateCodedAnswer(HibernateDraftFormsDAO.java:170) > > org.openmrs.module.draftforms.impl.DraftFormsServiceImpl.saveOrUpdateCodedAnswer(DraftFormsServiceImpl.java:172) > * > ... > * > org.openmrs.module.draftforms.web.controller.EditDropRadioCheckFormController.handleSubmission(EditDropRadioCheckFormController.java:142) > * > ... > > My classes are: > > public class CodedResponse extends Item{ > > private Integer num; //The number of the item > private Concept concept; > private char selectionStyle; // 'c' is checkbox; 'r' is radio button > private boolean checkbox; // True if the options are to be > displayed checkbox style > private boolean radio; // True if the options are to be displayed radio > button style > private boolean dropdown; // True if the options are to be > displayed dropdown menu style > > private Set<CodedAnswer> answers = new TreeSet<CodedAnswer>(); // A > list of the possible answers > > ... > } > > public class CodedAnswer implements Comparable<CodedAnswer> { > public static final long serialVersionUID = 1L; > private Integer id; //The id of the Item > private Integer answerNumber; // For ordering the answers > private String title; //The title of the answer > private CodedResponse codedResponse; //The CodedResponse this is an > answer to > private Concept concept; > private boolean other = false;; //If true, this is an "other" option > private String text = ""; // Additional text to go with the answer. > ... > } > > My hbm.xml files contain: > > <hibernate-mapping package="org.openmrs.module.draftforms"> > > <id name="id" type="int" column="id" unsaved-value="0"> > <generator class="native" /> > </id> > <property name="title" type="java.lang.String" column="title" not-null= > "true"/> > > <many-to-one name="concept" column="concept_id" class= > "org.openmrs.Concept" /> > > <property name="other" type="java.lang.Boolean" column="other" length="1" > /> > > <property name="text" type="java.lang.String" column="text" length="500" > /> > > > <many-to-one > name="codedResponse" > column="coded_response_id" > class="CodedResponse" > not-null="true"/> > > > </class> > </hibernate-mapping> > > <hibernate-mapping package="org.openmrs.module.draftforms"> > > <class name="Item" table="draftforms_items"> > > > <id name="id" type="int" column="id" unsaved-value="0"> > <generator class="native" /> > </id> > ... > > <joined-subclass name="CodedResponse" table="draftforms_coded_response"> > <key column="id"/> > <property name="num" type="int" column="num"/> > <many-to-one name="concept" column="concept_id" class= > "org.openmrs.Concept" /> > <property name="checkbox" type="java.lang.Boolean" column="checkbox" > length="1" /> > <property name="radio" type="java.lang.Boolean" column="radio" length="1" > /> > > > <set name="answers" inverse="true"> > > <key column="coded_response_id" not-null="true"/> > <one-to-many class="CodedAnswer"/> > > </set> > </joined-subclass> > </class> > > </hibernate-mapping> > > The mysql tables are: > > mysql> describe draftforms_coded_response; > +------------+------------+------+-----+---------+-------+ > | Field | Type | Null | Key | Default | Extra | > +------------+------------+------+-----+---------+-------+ > | id | int(11) | NO | PRI | NULL | | > | num | varchar(3) | YES | | NULL | | > | concept_id | int(10) | YES | | NULL | | > | checkbox | tinyint(1) | YES | | NULL | | > | radio | tinyint(1) | YES | | NULL | | > +------------+------------+------+-----+---------+-------+ > > mysql> describe draftforms_coded_answer; > +-------------------+--------------+------+-----+---------+-------+ > | Field | Type | Null | Key | Default | Extra | > +-------------------+--------------+------+-----+---------+-------+ > | id | int(11) | NO | PRI | NULL | | > | title | varchar(50) | YES | | NULL | | > | concept_id | int(10) | YES | | NULL | | > | other | tinyint(1) | YES | | NULL | | > | text | varchar(500) | YES | | NULL | | > | coded_response_id | int(11) | YES | | NULL | | > +-------------------+--------------+------+-----+---------+-------+ > > The code that does the persistence looks like this: > > Set<CodedAnswer> possibleAnswers = new TreeSet<CodedAnswer>(); > for (ConceptAnswer answer : response.getConcept().getAnswers()) { > CodedAnswer nextPossibleAnswer = new CodedAnswer(answer, response); > possibleAnswers.add(nextPossibleAnswer); > } > response.setAnswers(possibleAnswers); > > service.saveOrUpdateCodedResponse(response); > > // Need to make the question persistent before the answers > for (CodedAnswer answer : response.getAnswers()) { > service.saveOrUpdateCodedAnswer(answer); <-- This is the line > referenced in the stack trace > } > > ------------------ > > Barbara Lerner > Associate Professor > Computer Science Dept. > Mt. Holyoke College > > > > > > > ------------------------------ > Click here to > unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from > OpenMRS Developers' mailing list _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

