Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 331953 - [Hibernate] Roll back entity identifiers after unsuccessful resource save
Summary: [Hibernate] Roll back entity identifiers after unsuccessful resource save
Status: RESOLVED FIXED
Alias: None
Product: EMF
Classification: Modeling
Component: Teneo (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Martin Taal CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-06 16:00 EST by Aleksander Bandelj CLA
Modified: 2011-02-21 02:03 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aleksander Bandelj CLA 2010-12-06 16:00:14 EST
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
Comment 1 Martin Taal CLA 2011-02-21 02:03:39 EST
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?