sharedPK wrote:
Chubbard,
Customer cust = mgr.getCustomer(2011l); //Retrieves the Customer
ClientPreference clntPref = cust.getPreference(); //Retrieves the Client Preference
clntPref.getPrefCommMode.setId("EML"); //Changing the preferred communication mode from Phone to Email
save(cust); // Saves the parent customer, but tries to update the preferred communication mode table
Now, I have not tried to create a new PreferredCommunicationMode object,I use the ClientPrefernce parent entity but why does it still try to update the preferred communication mode table ? Its not a transient/detached instance
You're violating a cardinal rule doing that. You can't just switch IDs of objects. An ID is something that never, ever, I mean never ever ever ever ever ever changes. You can't call setId(). That's a rule that applies always.
You're trying to change the relationship between ClientPreference and PrefCommMode objects. That relationship is stored in a column in ClientPreference table. And that relationship is represented in the object model by the reference returned by ClientPreference.getPrefCommMode().
Your code above is altering the PrefCommMode object, and hibernate detects that change to the object. Not the relationship between the objects. That's controlled by the reference returned from ClientPreference.getPrefCommMode(). Hibernate uses that reference returned in order to detect changes made to the relationship. You want to use setPreCommMode() method on ClientPreferences in order modify that relationship.
Since you're using the string name as an ID your modifying the object, not the relationship stored in the ClientPreferences. Hibernate doesn't detect that you've modified the relationship instead it sees you modifying the object, and tries to update the PrefCommMode table instead.
If you wanted to change the communication mode of the client's preferences I suggest you do something like the following:
Code:
// you can cache this so you don't have to query for it every time. Also you'll have to translate between List -> Map, but that code is trivial so I'm not writing it.
Map<String,PrefCommMode> communicationMapCache = toMap( session.createQuery("from CommMode").list() );
Customer cust = mgr.getCustomer(2011);
ClientPreference clntPref = cust.getPreference();
clnPref.setPrefCommMode( communicationMapCache.get( "EML" ) );
In fact I would probably enapsulate that Map instead the PrefCommMode DAO and do something like:
Code:
public class ClientPreferenceDao {
CommunicationModeDao commModeDao;
public ClientPreferenceDao( CommunicationModeDao dao ) {
commModeDao = dao;
}
public void updatePreferences() {
Customer cust = mgr.getCustomer(2011);
ClientPreference clntPref = cust.getPreference();
clnPref.setPrefCommMode( commModeDao.get( "EML" ) );
}
}
This is all discussed again in the Transistive Persistence discussion in the documentation and a better explaination in Hibernate in Action book. My only knock against that book is it only discusses the XML configuration and not annotations. And it's sometimes hard to map back and forth between the two. Someone should rewrite it using annotations because it's very thorough. Much better than the free documentation.