| Summary: | [Hibernate] Roll back entity identifiers after unsuccessful resource save | ||
|---|---|---|---|
| Product: | [Modeling] EMF | Reporter: | Aleksander Bandelj <aleksander.bandelj> |
| Component: | Teneo | Assignee: | Martin Taal <mtaal> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | ||
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Whiteboard: | |||
I applied your changes in the latest build. Instead of iterating over all eobjects I only iterate over the new eobjects. Can you check if it works for you? |
Build Identifier: Let's consider saving of resource that fails because of database constraint or trigger. Hibernate makes no attempt to synchronize database and session in this case, so there are objects with assigned identifiers which are considered saved by Hibernate, but are not present in database. This leads to StaleObjectExceptions later on. It would be nice to add some form of resynchronization to teneo resource. My working implementation modifies finally clause in HibernateResource#saveResource (override points are useful for other things as well) if (!hasSessionController) { if (err) { beforeSaveRollback(); mySessionWrapper.rollbackTransaction(); afterSaveRollback(); // see bugzilla 221950 // mySessionWrapper.close(); } else { mySessionWrapper.commitTransaction(); } } And then (seems slighlty awkward): protected void beforeSaveRollback() { // assigned ids Session session= sessionWrapper.getHibernateSession(); for (EObject eobject : super.getContents()) { String entityName= session.getEntityName(eobject); String identifierName= getIdentifierName(eobject, session); Serializable id= session.getIdentifier(eobject); Criteria exists= session.createCriteria(entityName).add(Restrictions.eq(identifierName, id)); if(exists.uniqueResult() == null) { rollbackID(eobject, identifierName); } } } protected void afterSaveRollback() { // not necessary // sessionWrapper.clear(); // sessionWrapper.close(); // sessionWrapper = null; } protected void rollbackID(EObject eobject, String identifierName) { if(identifierName == null) return; EStructuralFeature identifier= eobject.eClass().getEStructuralFeature(identifierName); if(identifier == null) return; eobject.eUnset(identifier); IdentifierCacheHandler.getInstance().setID(eobject, null); } private String getIdentifierName(EObject eobject, Session hs) { String entityName= hs.getEntityName(eobject); if(entityName == null) return null; ClassMetadata entityMetaData= hs.getSessionFactory().getClassMetadata(entityName); if(entityMetaData == null) return null; String identifierName= entityMetaData.getIdentifierPropertyName(); return identifierName; } Reproducible: Always