This one time, at band camp, Craig M. Anderson said:
...
CMA> I can add a user just fine, I can also modify and delete the user with no
problem, except for this single problem. When a user comes into the user manager they
are presented with a form that lists the users, the query to get this list is done
setting the database to readonly mode. The user then clicks on the edit button for a
specific user and is taken to a form contains all the user information, part of this
form is a set of four radio buttons representing the users role. I can change anything
about this user but the role with no problem. If I change the role I get the error:
CMA>
CMA> "Object, com.searchdog.sysadmin.application.User@239780, links to another
object, com.searchdog.sysadmin.application.Role@af7a03 that is not
loaded/updated/created in this transaction."
CMA>
CMA>
CMA> So, to fix this I add the line calling Database.update() on the role object. I
can now save the updated user, unless I don't change the Role, then I get the error:
CMA>
CMA> "org.exolab.castor.jdo.DuplicateIdentityException: update object which is
already in the transaction"
CMA>
CMA>
CMA> What is going on? I have included my code below so you can view it if
neccessary, I am using the built in database pooling by Resin and the postgres
database.
...
CMA> /**
CMA> * UpdateUser method updates the submitted User object in the
CMA> * database using our OR software.
CMA> */
CMA> public void updateUser(User updatedUser) throws Exception {
CMA> // Get a database connection.
CMA> db = jdo.getDatabase();
CMA>
CMA> // Update the company in the database.
CMA> try {
CMA> // Get the user from the database.
CMA> db.begin();
CMA> oql = db.getOQLQuery( "SELECT u FROM com.searchdog.sysadmin.application.User
u WHERE id = $1" );
CMA> oql.bind( updatedUser.getId() );
CMA> result = oql.execute();
CMA> while (result.hasMore()) {
CMA> this.user = (User)result.next();
CMA> }
CMA> result.close();
CMA>
CMA> // Update the general user settings.
CMA> this.user.setFirstName( updatedUser.getFirstName() );
CMA> this.user.setLastName( updatedUser.getLastName() );
CMA> this.user.setEmail( updatedUser.getEmail() );
CMA> this.user.setPassword( updatedUser.getPassword() );
CMA>
CMA> // Udate the role information.
CMA> Role updatedRole = updatedUser.getRole();
CMA> db.update(updatedRole);
CMA> this.user.setRole( updatedRole );
CMA>
CMA> // Save the updated user to the database.
CMA> oql.close();
CMA> db.commit();
CMA> db.close();
CMA> } catch (Exception e) {
CMA> // Rollback transaction on failure, throw exception.
CMA> if (db.isActive()) {
CMA> db.rollback();
CMA> }
CMA> throw new Exception("Error updating User object in the database.", e);
CMA> }
CMA> }
It seems that your use of the db.update() method is correct. The getRole()
method performs a query to fetch the Role object and the updateUser()
method performs its own query and update()s the Role object - pretty
straightforward.
I see you're fetching the updatedRole object from the updatedUser
object. But based on the exception that is thrown, it seems that Castor's
cache is not aware of the the Role object being queried in the current
transaction context. I'm assuming that the User object has a one-to-one
relationship with the Role object, but without seeing the mapping I can
only guess. Can you post the mapping descriptor?
Bruce
--
perl -e 'print unpack("u30","<0G)U8V4\@4VYY9&5R\"F9E<G)E=\$\!F<FEI+F-O;0\`\`");'
-----------------------------------------------------------
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
unsubscribe castor-dev