found a second work around method , this is more OO - avoid using detached object .
Since the problem is caused by the hibernate detached object which cannot recognise the dirty properties changed if select-before-update attribute is not set to "true" , we just do our best to avoid it.
my problem is caused by the "reuse" of libraryUser which are return from formBackingObject() to onSubmit() in BorrowForm.java ,
my service class LibraryImpl.java ,Code:public class BorrowForm extends AbstractLibraryFormController {
public BorrowForm() {
setCommandClass(LibraryUser.class);
setCommandName("libraryUser");
setSessionForm(true);
}
protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
String cardKey = request.getParameter("cardKey");
...
LibraryUser libraryUser = getLibrary().findLibraryUser(cardKey);
...
return libraryUser;
}
...
public ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
String barcode = request.getParameter("barcode");
long lutId = RequestUtils.getLongParameter(request,"libraryUserTypeId", 0);
// the below libraryUser is a detached object !
// l cannot reuse it ! it cause difficulty l have mention in my first post.
// **********************************************************************
LibraryUser libraryUser = (LibraryUser) command;
Long libraryUserId = libraryUser.getId();
Long libraryUserTypeId = new Long(lutId);
// l get another libraryuser inside the method lend(..) , see the code below
// *********************************************************************
getLibrary().lend(barcode,libraryUserId,libraryUserTypeId);
return new ModelAndView(getSuccessView()+ "?" + "cardKey="
+ libraryUser.getCardKey());
}
LibraryUser.java's lend method , notice that it is return a void instead of a borrow ,Code:public class LibraryImpl implements LibraryFacade {
...
public void lend(String barcode,Long libraryUserId,Long libraryUserTypeId){
LibraryUser libraryUser = loadLibraryUser(libraryUserId.longValue());
LibraryUserType libraryUserType = null;
Set libraryUserTypes = libraryUser.getLibraryUserTypes();
Iterator it = libraryUserTypes.iterator();
while (it.hasNext()) {
LibraryUserType lut = (LibraryUserType) it.next();
if (lut.getId().equals(libraryUserTypeId)) {
libraryUserType = lut;
break;
}
}
Item item = loadItemByBarcode(barcode);
libraryUser.lend(item,libraryUserType);
// l can use storeLibraryUser(..) now , it won't cause multi-unwanted update
// ***********************************************************************
storeLibraryUser(libraryUser);
}
}
it insert only one borrow , hibernate knew who have been modified.Code:public void lend(Item item,LibraryUserType libraryUserType) {
Borrow newBorrow = new Borrow();
newBorrow.setItem(item);
newBorrow.setLibraryUser(this);
newBorrow.setLibraryUserType(libraryUserType);
Date today = new Date();
newBorrow.setBorrowDate(today);
long oneDay = 86400000;
// check the convertion OK or not -> int to long
long duration = libraryUserType.getDuration().longValue();
long itemDuration = item.getItemDuration().getItemDurationValue().longValue();
Date dueDate = new Date(today.getTime()+(duration*oneDay)+(itemDuration*oneDay));
newBorrow.setDueDate(dueDate);
this.getBorrows().add(newBorrow);
}
Remark :Code:...
Hibernate: insert into BORROWS (VERSION, BORROW_DATE, DUE_DATE, RETURN_DATE, REPORTLOST_DATE, RENEWED_NO, LIBRARY_USER_TYPE_ID, ITEM_ID, USER_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
...
1. This is fast code , just to illustrate idea.
2. l don't know what will happen if l keep avoiding detached object , l think this is not better than the psuedo code.
Alarmnummer , thanks for the explaination , but l still don't understand second answer
it seems that you are exposing your service object for someone to take control , ?? .Quote:
And the save method is needed if you bind information to the domain objects and need to save it. So a save method can bypass all logic.
Yes , l understood . :)Quote:
-If you are a 'professional' you have learned to give up hope and use what you have got. You have learned that the struggeling is normal and finally you accept it as the way you do your work and start to defend it if others complain because it sucks. In some cases you even make up 'design patterns' with complicated names to deal with the problems of the bad solution.
-Or you are to stupid to realise it sucks in the first place and do it because this is the way everybody does it.
-Or you find it great because: if it is so difficult to use, it must be good!
I`m a littlebit sarcastic, but I hope you get the point.
moon
