LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 08-29-2012, 06:03 PM   #1
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,956
Blog Entries: 1

Rep: Reputation: 81
Ebean: why is Ebean trying to do an update by doing where with all fields?


Hi!

I have this entity (associated with Ebean) that I want to save after having performed some changes on some of the fields.

I get a javax.persistence.OptimisticLockException: MissingResource exception in DmlHandler.checkRowCount().

Now, I just noticed that in the update query, ebean is using all fields of the entity in the "where" clause instead of using the field I had marked as @Id in the entity. Why is that?

Code:
@Id
@Column(name = FIELD_ID)
@GeneratedValue
private int id;
I suppose that it's checking that a row was actually modified and if it's using all the new values in the where clause, the fields that I changed won't match and so there's a Missing Resource, of course.

Thanks in advance.
 
Old 08-30-2012, 12:00 PM   #2
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,956
Blog Entries: 1

Original Poster
Rep: Reputation: 81
I've been following the code and I found something about Concurrency Mode in UpdateMeta.getDynamicUpdatePlan(ConcurrencyMode, PersistRequestBean<?>).

Code:
private SpiUpdatePlan getDynamicUpdatePlan(ConcurrencyMode mode, PersistRequestBean<?> persistRequest) {

	Set<String> updatedProps = persistRequest.getUpdatedProperties();
	
	if (ConcurrencyMode.ALL.equals(mode)){
		// due to is null in where clause we won't bother trying to 
		// cache plans for ConcurrencyMode.ALL
		String sql = genSql(mode, persistRequest, null);
		if (sql == null){
		    // changed properties must have been updatable=false
		    return UpdatePlan.EMPTY_SET_CLAUSE;
		} else {
		    return new UpdatePlan(null, mode, sql, set, updatedProps);
		}
	}
		
	// we can use a cached UpdatePlan for the changed properties
	int hash =  mode.hashCode();
	hash = hash * 31 + (updatedProps == null ? 0 : updatedProps.hashCode());
	Integer key = Integer.valueOf(hash);
	
	BeanDescriptor<?> beanDescriptor = persistRequest.getBeanDescriptor();
	SpiUpdatePlan updatePlan = beanDescriptor.getUpdatePlan(key);
	if (updatePlan != null){
		return updatePlan;
	}
	
	// build a new UpdatePlan and cache it
	
	// build a bindableList that only contains the changed properties
	List<Bindable> list = new ArrayList<Bindable>();
	set.addChanged(persistRequest, list);
	BindableList bindableList = new BindableList(list);
		
	// build the SQL for this update statement
	String sql = genSql(mode, persistRequest, bindableList);
	
	updatePlan = new UpdatePlan(key, mode, sql, bindableList, null);
		
	// add the UpdatePlan to the cache
	beanDescriptor.putUpdatePlan(key, updatePlan);
		
	return updatePlan;
}

ConcurrencyMode has been set to "ALL" and I think that's why it's using all the fields. Now, the mode has been determined by PersistRequestBean.determineConcurrencyMode().

Code:
/**
 * Determine the concurrency mode depending on fully/partially populated
 * bean.
 * <p>
 * Specifically with version concurrency we want to check that the version
 * property was one of the loaded properties.
 * </p>
 */
public ConcurrencyMode determineConcurrencyMode() {
	if (loadedProps != null) {
		// 'partial bean' update/delete...
		if (concurrencyMode.equals(ConcurrencyMode.VERSION)) {
			// check the version property was loaded
			BeanProperty prop = beanDescriptor.firstVersionProperty();
			if (prop != null && loadedProps.contains(prop.getName())) {
				// OK to use version property
			} else {
				concurrencyMode = ConcurrencyMode.ALL;
			}
		}
	}
	return concurrencyMode;
}
Is there something I can do to change the ConcurrencyMode?

PS I don't know if this is related but I have done a getX from the entity so shouldn't that property be saved in loadedProps at least?
 
Old 08-30-2012, 01:25 PM   #3
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,956
Blog Entries: 1

Original Poster
Rep: Reputation: 81
Seems like concurrencyMode is the one to blame here.

Here's this code from UpdateMeta.genSql(ConcurrencyMode, PersistRequestBean<?>, BindableList):

Code:
if (ConcurrencyMode.VERSION.equals(conMode)) {
	if (version == null){
		return null;
	}
	version.dmlAppend(request, false);
	
} else if (ConcurrencyMode.ALL.equals(conMode)) {
	
	all.dmlWhere(request, true, request.getOldValues());
}
first equals() call is false, then second equals() is true. I think I have to hack the concurrency mode. How is that done? ANd hasn't it bothered me before? Weird.
 
Old 08-30-2012, 02:33 PM   #4
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,956
Blog Entries: 1

Original Poster
Rep: Reputation: 81
Adding a @Version field to the entity seems to have solved the whole thing.
 
  


Reply

Tags
ebean, entity, java, jpa, persistence


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Building ebean (java): Where is scala.collection.JavaConversions.java? eantoranz Programming 1 03-18-2012 10:32 AM
[SOLVED] deleting fields in lines that have more fields than the average patolfo Linux - Software 4 09-14-2011 11:03 AM
[SOLVED] get fields using awk ashok.g Programming 9 12-09-2009 01:21 AM
Breaking fields tt1ect Programming 1 12-14-2008 06:51 PM
inittab fields env Linux - General 2 03-04-2005 12:36 PM


All times are GMT -5. The time now is 05:27 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration