Just my two cents, you can avoid the lookup by using a JPQL UPDATE query. If used to update a single record you avoid the lookup. If versioning is an issue this may not be ideal (still you could manually set the version), also if you expect to reuse objects you lose the ability to proxy, if those are not issues... there is no reason not to do this.
On Thu, Jan 7, 2016 at 4:26 PM, CRANFORD, CHRIS <chris.cranf...@setech.com> wrote: > In the case of non-versioned domain models or cases where you aren't > concerned with state collisions, the traditional lookup/render/lookup/merge > workflow works quite well. > > The problem though comes into play when you are concerned about versioned > models and more importantly, controlling state transition across concurrent > modifications. What I have seen developers do in the past is that they > expose the @Version property to the form and have that value posted back > along with the changed attributes during the save/update operation. This > approach works, but the security risk is you're exposing a critical piece > of data that is subject to user manipulation to bypass optimistic locking. > > A better approach is to follow a similar paradigm that JSF uses called > conversation scopes. The struts2-conversation-plugin offers this kind of > feature. > > The plugin basically allows you to expose a set of action properties to a > named scope. The plugin in combination with a few custom tags, allowed a > form identifier to be placed as a hidden field in your form when you render > your view. When the view's changes are posted back to the save/update > action, the plugin first takes the hidden field conversation id and looks > up the state from the session that was saved when the conversation was > started. Any field flags to be included in the conversation will be > rehydrated with the state it had when the prior action was executed. The > struts framework then can use it's normal property injection mechanism to > set the appropriate state on the model. Since the version of the domain > model isn't being exposed to the client, there is no concern with a user > hijacking the optimistic locking mechanism of your JPA provider to force > changes to occur when a collision should happen. > > A typical action might look like the following. The annotations I show my > now map exactly to the plugin as we use a modified proprietary version here > but the gist remains the same. > > @ConversationSupport(conversation = "myconversion") > public class SomeAction extends ActionSupport implements > ModelDriven<ViewModel> { > > private Long id; > @ConversationField private DomainModel domainModel; > @ConversationField private ViewModel viewModel; > > @BeginConversation(conversation = "myconversion") > public String renderView() { > try { > this.domainModel = someService.find(id); > this.viewModel = new ViewModel(domainModel); > return SUCCESS; > } > catch(Exception ex) { > addActionError(getText(ERROR_UNEXPECTED_EXCEPTION)); > return ERROR; > } > } > > @Conversation(conversation = "myconversion") > public String saveView() { > try { > // copy values from this.viewModel to this.domainModel > someService.update(this.domainModel); > return SUCCESS; > } > catch(OptimisticLockException ex) { > // you could elect to find the domainModel again, update it and try > to take > // the changes in domainModel + the changes from the user in viewModel > // and merge them then send the user back to the view again letting > them > // know some fields were changed while they were making their changes. > // They can verify their changes again and resubmit. I don't do > this here > // but instead just tell the user the record was changed and they > need to > // leave and come back in, but its up to you. > addActionError(getText(ERROR_RECORD_ALREADY_MODIFIED)); > return INPUT; > } > catch(Exception ex) { > addActionError(getText(ERROR_UNEXPECTED_EXCEPTION)); > return ERROR; > } > } > > /* other stuffs */ > > } > > > > -----Original Message----- > From: C N Davies [mailto:c...@xcogia.com] > Sent: Wednesday, January 06, 2016 10:24 PM > To: 'Christoph Nenning' <christoph.nenn...@lex-com.net>; 'Struts Users > Mailing List' <user@struts.apache.org> > Subject: RE: Editing a JPA entity > > Christoph I understand why this happens, I was simply asking if there was > a better way to do this using some struts session magic or such. Seems > there isn't so I'll just do it the old long winded way. > > > -----Original Message----- > From: Christoph Nenning [mailto:christoph.nenn...@lex-com.net] > Sent: Tuesday, January 5, 2016 6:57 PM > To: Struts Users Mailing List <user@struts.apache.org> > Subject: Re: Editing a JPA entity > > > I'm using an action to retrieve a list of entities and render these as > > a list, the user can then select an edit button that calls an action > > that retrieves the individual entity and renders the edit page. Once > > the user > has > > completed editing they hit the save button which calls the action that > calls > > the entity manager's merge method to update the db. Each of these > actions > > call methods of the same action class, but the entity ends up in a > detached > > state so merge will fail. I could just retrieve the entity again and > then > > update each data member but this seems like a very messy way to do it. > Is > > there a better way to do this with struts? > > > > > > > > I'm using struts 2.3.20 with hibernate 4.3.11 > > > > > > > Well, that is basic http. When data is SELECTed from DB and the html page > is rendered the server is done. That means at this point there are no more > references to attached jpa objects. In terms of http: the handling of GET > request is completed. > > When the user hits save the browser issues another http request, usually a > POST request. On the server side there is no more state or information that > there has been a GET request before and entities had been loaded. > > So yes, you have to retrieve the entity again and update it. > > > > Regards, > Christoph > > This Email was scanned by Sophos Anti Virus > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@struts.apache.org > For additional commands, e-mail: user-h...@struts.apache.org > > > Email secured by Check Point > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@struts.apache.org > For additional commands, e-mail: user-h...@struts.apache.org > >