These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Modifying Discriminator Values
PostPosted: Wed Dec 05, 2007 11:41 am 
Newbie

Joined: Wed Dec 05, 2007 11:20 am
Posts: 4
I'm having difficulty determining the best approach for modifying a discriminator value after the record has been inserted when using a table per class hierarchy approach. The example that I will use is the Payment mapping from the Hibernate documentation.

<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property name="amount" column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
<property name="creditCardType" column="CCTYPE"/>
...
</subclass>
<subclass name="CashPayment" discriminator-value="CASH">
...
</subclass>
<subclass name="ChequePayment" discriminator-value="CHEQUE">
...
</subclass>
</class>


Now let's say that I insert a CashPayment into the table with the pseudo code below.

Code:
CashPayment payment = new CashPayment();
payment.setAmount(2.50);
session.save(payment);


A record is successfully written to the DB. Then when I retrieve the record, the instance is a CashPayment as expected.

Code:
Payment payment = session.get(Payment.class, 1234);


Now here's my problem The user interface that I am building allows the payment type to be changed from a cash payment to a credit card payment (this is theoretical). There doesn't seem to be an easy way to do this. One approach is to manually update the database value, but I am trying to avoid that because I cannot guaurantee that the user will want to permanently save the value from the interface. The other approach that I've tried is to create a new CreditCardPayment instance and copy to the attributes from the cash instance to the credit instance.

Code:
Payment payment = session.get(1234);
CreditCardPayment newPayment = new CreditCardPayment ();
newPayment.setAmount(payment.getAmount());
session.evict(payment);
session.save(newPayment);


This performs an update but does not update the discriminator value. And also I am not extremely happy with the approach but could live with it.

Does anyone have any solutions that have worked well for them in the past?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 11, 2007 5:44 am 
Newbie

Joined: Tue Nov 20, 2007 4:57 am
Posts: 7
I'm trying to do the very same thing. So far, the only solution for this seems to be using jdbc calls unfortunately


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 11, 2007 7:09 am 
Beginner
Beginner

Joined: Wed Apr 26, 2006 4:40 am
Posts: 24
Well, you can't change the class of an instance, so you can't change a discriminator value.

The problem is, that the data base allows this, which is a little tricky.

The straight forward way would be to copy the data from the base class into a new instance of the different payment class, delete the old data and insert the new one.

This is of course a problem if you allready have other data which references on the record you want to delete.

An other way would be to drop the hard wired inheritance, and map the data more like it is represented in the data base, e.g. as several one-to-one relationships which may return null values.

Then it would be no problem to remove the obsolete payment method and add the new one.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 11, 2007 12:58 pm 
Newbie

Joined: Wed Dec 05, 2007 11:20 am
Posts: 4
The solution that I went with is to create a new instance of the appropriate type and copy the data from the old object to the new object with an init method. To get around the issue of Hibernate not including the discriminator column in the update statement, I modified my mapping file to include a separate property for the discriminator column and set the discriminator to insert="false" as shown below.

<discriminator column="PAYMENT_TYPE" type="string" insert="false" />
<property name="paymentType" column="PAYMENT_TYPE" />


Now when I call save on the new instance, it will update the record to the new payment type value.

Thanks for your help. Let me know if others have alternatives.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 08, 2008 5:52 pm 
Newbie

Joined: Tue Jan 08, 2008 5:46 pm
Posts: 1
Hi, ascherer,

Could you please clarify if you update the old record with new payment type value or create a new record with new payment type value and dropped the old record? If it is the first case, could you please tell me how to convert your trick to using annotation?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 10:21 am 
Newbie

Joined: Wed Dec 05, 2007 11:20 am
Posts: 4
jchs86 -

The approach I used performs an update on the discriminator column and not an insert row/delete row combination.

I'm not as familar with configuring Hibernate with annotations but I'm guessing that you may need to define the discriminator attribute twice on your entity (I defined it twice in the mapping file). One attribute would be declared as a discriminator column with insert=false and the second attribute would be a normal property pointing to the discriminator column that inherently offers you the option to update the value. The key point is that the discriminator attribute does not offer update support so I needed a property that could be updated.

I also created some convenience methods on the entities to make the conversions between types easier, which also made this mapping less transparent.

I've tried a few different approaches to solving this issue and had the most success with this one. The insert row/delete row solution just didn't seem right to me since I am only affecting one column. Others may disagree.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 10:21 am 
Newbie

Joined: Wed Dec 05, 2007 11:20 am
Posts: 4
jchs86 -

The approach I used performs an update on the discriminator column and not an insert row/delete row combination.

I'm not as familar with configuring Hibernate with annotations but I'm guessing that you may need to define the discriminator attribute twice on your entity (I defined it twice in the mapping file). One attribute would be declared as a discriminator column with insert=false and the second attribute would be a normal property pointing to the discriminator column that inherently offers you the option to update the value. The key point is that the discriminator attribute does not offer update support so I needed a property that could be updated.

I also created some convenience methods on the entities to make the conversions between types easier, which also made this mapping less transparent.

I've tried a few different approaches to solving this issue and had the most success with this one. The insert row/delete row solution just didn't seem right to me since I am only affecting one column. Others may disagree.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 09, 2008 12:16 pm 
Newbie

Joined: Tue Dec 09, 2008 12:10 pm
Posts: 1
Hi, ascherer,
I am not able to get update of discriminator column working with what you have said. Have spent quite some time on this. Can you give a more detailed information of the steps you have done. I may be missing something here. Was doing an insert/update before. Have to change it to update as some associations are lost on delete. Your help would be very much appreciated.

Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.