tracker issue : CF-4024472

select a category, or use search below
(searches all categories and all time range)
Title:

ORM entities are incorrectly created when using single table inheritance with mappedSuperClass

| View in Tracker

Status/Resolution/Reason: To Fix//Bounced

Reporter/Name(from Bugbase): Mingo Hagen / Mingo Hagen (Mingo Hagen)

Created: 07/22/2015

Components: ORM Support

Versions: 2016,11.0,10.0

Failure Type: Incorrect w/Workaround

Found In Build/Fixed In Build: CF11_Final /

Priority/Frequency: Major / Some users will encounter

Locale/System: ALL / Platforms All

Vote Count: 2

Related Bugs:
CF-4178506 - Similar to
CF-4178506 - Similar to


Problem Description:
  When you have a base component (base.cfc) with MappedSuperClass set to true, a 
  persisted component (animal.cfc) inheriting from that and another (dog.cfc) 
  inheriting from that one ColdFusion throws an exception (a Hibernate one). 
  To make this bug more fun, CF doesn't always throw this exception.

  The reason why this happens becomes clear when you set
  this.ormsettings.savemapping=true and take a look at the hbmxml files. 

  The XML in dog.hbmxml contains the fields from base.cfc:
  <property name="name" type="string"><column name="name"/></property>

Steps to Reproduce:
  Use the files included with this bug.

Actual Result:
  An exception: Repeated column in mapping for entity: {entity-name} column: {column-name} (should be mapped with insert="false" update="false")

Expected Result:
  Correctly generated hibernate entities.

Any Workarounds:
  You can write your own .hbmxml files to work around the problem.

----------------------------- Additional Watson Details -----------------------------

Watson Bug ID:	4024472

External Customer Info:
External Company:  
External Customer Name: Mingo
External Customer Email:  
External Test Config: My Hardware and Environment details: Tested on Windows (multiple) on CF9 through 11.

Attachments:

  1. July 23, 2015 00:00:00: 1_bug-orm-cf11.zip
  2. November 18, 2015 00:00:00: 2_acf-4024472.zip

Comments:

I mentioned it in the title, but forgot to add it to the description, I've only noticed this when using the "Table per hierarchy" paradigm.
Comment by External U.
6474 | July 22, 2015 05:01:42 PM GMT
A mappedsuperclass should contain only the common properties. Any persistent component that has it as its ancestor will inherit it's properties.
Comment by Himavanth R.
6475 | September 25, 2015 05:00:47 AM GMT
So, are you saying that the files in the included zip fila are supposed to throw a 'Repeated column in mapping for entity: dog column: name (should be mapped with insert="false" update="false")' exception?
Comment by External U.
6476 | September 28, 2015 03:21:17 AM GMT
For clarity: the dog entity gets the following HBM XML generated: <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <subclass discriminator-value="dog" entity-name="dog" extends="cfc:18502eb2916b8041cf1e.animal" lazy="true" name="cfc:18502eb2916b8041cf1e.dog"> <property name="name" type="string"> <column name="name"/> </property> <property name="furColor" type="string"> <column name="furColor"/> </property> </subclass> </hibernate-mapping> Notice the extra name property, that's not supposed to be there, because that should be inherited from the animal class.
Comment by External U.
6477 | September 28, 2015 03:27:10 AM GMT
That is correct. To achieve the desired functionality you will have to move the name property from base to animal. You would still be able to set the name from dog entity. <cfset fido = entityNew( "dog" ) /> <cfset fido.setName( "Fido" ) />
Comment by Himavanth R.
6478 | September 28, 2015 04:17:45 AM GMT
but I'm not able to do anything, since CF throws an exception.
Comment by External U.
6479 | September 28, 2015 09:35:12 AM GMT
> To achieve the desired functionality you will have to move the name property from base to animal. Then, what's the point of a base class?
Comment by External U.
6480 | September 28, 2015 09:35:58 AM GMT
Well that is the difference between mappedsuperclass and persistent superclass. Mappedsuperclass has properties that are actually inherited by all of it's children and the properties go in the mapping xml as well. A persistent superclass is used when there are multiple entities connected to each other through either a common table or a join column. In case of table per heirarchy, ORM knows it's only one table and so doesn't copy the properties of persistent superclass in to mapping xml.
Comment by Himavanth R.
6481 | September 28, 2015 10:31:25 PM GMT
> In case of table per heirarchy, ORM knows it's only one table and so doesn't copy the properties of persistent superclass in to mapping xml. And that's just my reason for filing this bug, CF _does_ copy the properties from the mapped super class (base.cfc) once there's a layer between the base.cfc and the dog.cfc (animal.cfc). base.cfc has id and name properties - animal.cfc inherits those properties (as copies) - dog.cfc should inherit those through extends=animal, but here is where the bug comes in, it actually gets a copy of the name property as I've shown you when I posted the HBM XML code generated by CF: <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <subclass discriminator-value="dog" entity-name="dog" extends="cfc:18502eb2916b8041cf1e.animal" lazy="true" name="cfc:18502eb2916b8041cf1e.dog"> ******** THIS ONE: ********** <property name="name" type="string"> <column name="name"/> </property> <property name="furColor" type="string"> <column name="furColor"/> </property> </subclass> </hibernate-mapping>
Comment by External U.
6482 | September 29, 2015 05:04:45 AM GMT
Hi Himavanth, Since you won't answer, I'll add another tidbit which shows that CF generates different .hbmxml files at different times (explaining the part in my original report mentioning that CF doesn't always throw the error). Follow these steps: 1. Set this.ORMSettings.saveMapping to true 2. remove previously generated .hbmxml files 3. clear the template cache 4. navigate to the app (causing a ORMReload()) This will generate the (in my opinion) incorrect .hbmxml files which results in the "Repeated column in mapping for entity" error. Now remove the dog.hbmxml file and reload the application. This will generate a different .hbmxml file, still wrong (namely a <class> file instead of a <subclass> file), but not resulting in an error because suddenly dog is no longer inheriting from animal... So you're still saying that this is not a bug and entirely how you meant it to work?
Comment by External U.
6483 | November 05, 2015 06:04:53 AM GMT
I gotta say I'm with Mingo on this. And irrespective of what properties are supposed to go where in the hibernate file, it's *ColdFusion's* job to sort all that out, and it seems to me that CF is mishandling the processing of the inheritance hierarchy here. CF should be able to infer from Mingo's config what needs to be done, and it's messing it up. *Mingo* hasn't double-specified the NAME property: CF has simply messed up how it converts the CFC config into the hibernate files. Equally the way Mingo has described the property inheritance in his CFCs is appropriate and correct. However Mingo's already explained all this, and this - YET AGAIN - seems like an Adobe engineer simply not taking the appropriate amount of time and care and thoroughness to actually read what's in front of them, and - I suspect - not even having run Mingo's code and looked at the results. Did you run the code and look at the results, Himavanth? (be honest). And if you think Mingo has misconfigured his ORM settings, then - Himavanth - it's kinda up to you do advise how he *should* be doing it. With a modified version of his code. Note: don't touch the inheritance hierarchy (it's correct), you must only adjust the ORM settings.
Comment by External U.
6484 | November 06, 2015 03:26:16 AM GMT
Hi Mingo, So you're saying if you delete one hbmxml file and force ORM to reload partially, it behaves wierdly. That does look like a bug (and it's completely different from what this bug was originally logged for) and i will take it. I am still not sure about the original bug though. I think you are saying CF should not copy the properties of mappedsuperclass because it is being inherited through a table-per-heirarchy superclass. I am saying CF should treat a mappedsuperclass and a persistent superclass differently irrespective of what else is in the heirarchy to provide both the functionalities to developers. There is a middle ground though. Probably not inherit the mappedsuperclass's properties only in table-per-heirarchy but inherit it in table-per-subclass. But i think that will lead to more confusion than a solution. No?
Comment by Himavanth R.
6485 | November 08, 2015 10:43:10 PM GMT
Ok, at least we agree on that bug, I'll file that seperately, but getting back to the actual issue: What I'm saying is that I get an error message when I add mappedSuperClass to the base cfc. That's it. Why should I suddenly get an error? Especially one that I can fix by editing the .hbmxml files manually. Shouldn't CF do that for me?
Comment by External U.
6486 | November 09, 2015 03:27:15 AM GMT
Hi Himavanth, I hoped it wouldn't come to this, but I've just tested it on Lucee and I'm sure you don't want to hear it, but they do generate the hbm.xml files correctly. Using a <subclass>, omitting the properties of the mapped super class.
Comment by External U.
6487 | November 10, 2015 05:57:16 AM GMT
This is to be expected really: it's not like the Lucee team would coincidentally implement the same bug in the same way. But it demonstrates it *is* a bug in the implementing in ColdFusion, and possibly also with Himavanth's understanding of how this ought to be working. Maybe go look at the source code for the Lucee implementation to see how you should be doing it, Himavanth?
Comment by External U.
6488 | November 10, 2015 07:57:44 AM GMT
Was stuck with something else. Give me a day. Will revisit this.
Comment by Himavanth R.
6489 | November 17, 2015 03:37:38 AM GMT
Thanks dude.
Comment by External U.
6490 | November 17, 2015 03:45:51 AM GMT
Just checked this again. Have you read my earlier comment? My question was, if there is a case of having a similar column(for something like auditing) in all tables (of table-per-subclass scenario), how would you achieve that when this bug is fixed? Would you put the column in each entity that extends the base? BTW, I do understand this scenario could be rare.
Comment by Himavanth R.
6491 | November 18, 2015 04:03:53 AM GMT
From an ORM perspective, this is irrelevant, isn't it? ORM mappings should be considered from a perspective of "storing this object in the DB": it's an object-centric concept, rather than positioning it from a DB-centric POV. Row-auditing etc is a DB conceit, not an object conceit.
Comment by External U.
6492 | November 18, 2015 04:13:29 AM GMT
Hi Himavanth, Thank you for looking into it further, I've reread your comments and rechecked my example code and a couple things sprung up: - This bug specifically mentions table-per-hierarchy, not table-per-subclass. - The example code I provided has an error in it: it's missing the discriminator arguments. Adding those arguments does not however fix the issue, it will result in the same error. So, to fix this the dog subclass should simply not repeat the properties of its parent class, since it has extends="cfc:animal" which to me means that it inherits those properties from the animal class. I've uploaded new example code (including the generated hbmxml files as I would like to see them).
Comment by External U.
6493 | November 18, 2015 05:29:08 AM GMT
Mingo, Yes this bug talks about table-per-heirarchy. I was actually no longer talking about the issue but about the solution itself. What i was trying to imply is that CF shouldn't make any change that is specific to table-per-heirarchy because that will be confusing. I think we are just going in a circle here. So let's keep things simple. The contention here is whether or not dog.cfc should copy the properties defined in base.cfc.. right? You are saying it shouldn't copy for table-per-heirarchy. I am saying there should not be any difference in that logic between table-per-heirarchy and table-per-subclass. Now if you say, it shouldn't copy for table-per-subclass as well for consistency, there will be a loss of feature here. There will be no way of creating same column in all tables of a table-per-subclass without redundancy. Let me know if i am missing something.
Comment by Himavanth R.
6494 | December 21, 2015 03:47:18 AM GMT
Hi Himavanth, Thank you for your reply. When I mentioned "table-per-hierarchy", it was merely to show you where the bug shows up, not how it should be different from the other strategies. > You are saying it shouldn't copy for table-per-heirarchy. No, I say: it shouldn't copy when using mappedSuperClass=true. If you are saying I'm not correct and that this is not a bug, can you show me where my mistake is in the sample code I provided? Best regards, Mingo Hagen.
Comment by External U.
6495 | December 21, 2015 04:39:59 AM GMT
@Himavanth. It might be handy if you interact with Mingo on the CFML Slack channel. I see you have signed-up for it, but you never seem to use it. It's a bit more "immediate" than bugbase posts every few weeks ;-)
Comment by External U.
6496 | December 21, 2015 04:59:49 AM GMT
@Mingo: > When I mentioned "table-per-hierarchy", it was merely to show you where the bug shows up, not how it should be different from the other strategies. Ofcourse. You would have to think about the behaviour in other strategies(table-per-subclass) too when looking for a solution. > No, I say: it shouldn't copy when using mappedSuperClass=true. Yes. Including that. Still the same argument. > If you are saying I'm not correct and that this is not a bug, can you show me where my mistake is in the sample code I provided? Hmm. I had given that detail in my post 3 months ago. Here .... To achieve the desired functionality you will have to move the name property from base.cfc to animal.cfc A mappedsuperclass should contain only the common properties. Any persistent component that has it as its ancestor will inherit it's properties.
Comment by Himavanth R.
6497 | December 22, 2015 04:47:08 AM GMT
> To achieve the desired functionality you will have to move the name property from base.cfc to animal.cfc Then... what's the point of having a mappedSuperClass if you can have any properties in it? > A mappedsuperclass should contain only the common properties. Like... 'name'? > Any persistent component that has it as its ancestor will inherit it's properties. If only this were true. In CF it doesn't inherit... it copies, which result in the error this bug is about.
Comment by External U.
6498 | December 22, 2015 10:52:35 AM GMT
If I could edit a comment that would be nice, but I can't... so here's the edit: "Then... what's the point of having a mappedSuperClass if you can have any properties in it?" should be: "Then... what's the point of having a mappedSuperClass if you can't have any properties in it?"
Comment by External U.
6499 | December 22, 2015 10:54:00 AM GMT
> "Then... what's the point of having a mappedSuperClass if you can have any properties in it?" Please refer to my reply on Sep 29 for this question. I think it would be an exaggeration to say "you can't have any properties in it."
Comment by Himavanth R.
6500 | February 11, 2016 03:05:11 AM GMT
> I think it would be an exaggeration to say "you can't have any properties in it." I think so too, but that is what it comes down to. > Please refer to my reply on Sep 29 for this question. I have already addressed the point you raise in that answer, see my response of 3:34:45 AM GMT+00:00 Sep 29, 2015.
Comment by External U.
6501 | February 11, 2016 04:21:27 AM GMT
> > Please refer to my reply on Sep 29 for this question. > I have already addressed the point you raise in that answer, see my response of 3:34:45 AM GMT+00:00 Sep 29, 2015. Can't agree there. You have taken my statement about persistent superclass and applied it to mappedsuperclass, don't you think? Let me assure you that i would be more than happy to make the change you requested if it didn't have the potential to cause confusion and loss of feature in table-per-subclass as i have explained in my note on Dec 21, 2015.
Comment by Himavanth R.
6502 | February 11, 2016 04:52:05 AM GMT
Ok, going with the "Table per hierarchy" example in the ColdFusion docs (https://helpx.adobe.com/coldfusion/developing-applications/coldfusion-orm/define-orm-mapping/advanced-mapping.html) you are saying that you can _not_ put a base.cfc above Payment.cfc with any other properties except a `fieldtype="id"` one? If that's the case, you can close this bug and I stand corrected. But just so you know, you can make that work without problem in Hibernate. And if that is indeed the case, you might want to put that in the docs.
Comment by External U.
6503 | February 11, 2016 08:49:31 AM GMT
> you are saying that you can _not_ put a base.cfc above Payment.cfc with any other properties except a `fieldtype="id"` one? Yes for table-per-heirarchy. No for table-per-subclass where you can put properties in base which would then be copied in to all subclasses.
Comment by Himavanth R.
6504 | February 12, 2016 05:15:33 AM GMT
Ok, so we do agree on how it works, we just don't agree on which way is the right way. This makes this 'issue' into a feature request, I guess? It is a feature that would be logical in my eyes since right now there is a pretty basic scenario (having an updateDate on a row, for example) in Hibernate which you can't create using ColdFusion. If you don't want to, or are unable to add this, I think the hbm.xml generator should throw an error when it finds properties in a mappedSuperClass when following the per-hierarchy strategy. Because right now it acts as if that should be possible and only throws an error when hibernate encounters the extra properties, which can be a real hassle when you are relying on ColdFusion to manage the hibernate part for you (ie. when you're not generating the mapping files).
Comment by External U.
6505 | February 12, 2016 06:50:22 AM GMT
> Ok, so we do agree on how it works, we just don't agree on which way is the right way. Yes. I have been saying the same all this while. > This makes this 'issue' into a feature request, I guess? Well that doesn't matter yet as long as the functionality requested is valid. > right now there is a pretty basic scenario (having an updateDate on a row, for example) in Hibernate which you can't create using ColdFusion. I wouldn't say you can't create using ColdFusion. All you would have to do is move the property from mappedsuperclass to persistent superclass. Doesn't that work for you? True it works in hibernate but that's when you create the XMLs yourself. With ColdFusion generating them for you, i think there should be specific rules about how you write those super classes. Any logic here based on assumptions might cause long term confusions as explained in my post dated Dec 21, 2015. > I think the hbm.xml generator should throw an error when it finds properties in a mappedSuperClass when following the per-hierarchy strategy. Agreed there should be some way to tell the difference. My view is that mappedsuperclass makes little sense in a per-heirarchy case.
Comment by Himavanth R.
6506 | February 17, 2016 12:26:50 AM GMT
Hi Himavanth, Thank you for your reply. > I wouldn't say you can't create using ColdFusion. All you would have to do is move the property from mappedsuperclass to persistent superclass. Doesn't that work for you? Yes, that works, however the mappedSuperClass functionality is there so you wouldn't have to copy those fields. The way the tables are generated (per hbmxml instructions) should not restrict the way you design your cfc model. > True it works in hibernate but that's when you create the XMLs yourself. If I can, why can't ColdFusion? > With ColdFusion generating them for you, i think there should be specific rules about how you write those super classes. Any logic here based on assumptions might cause long term confusions as explained in my post dated Dec 21, 2015. I agree, I just think those rules should be different ones than what you think. The logic you're currently using confuses me and others with me. > Agreed there should be some way to tell the difference. Good, so this ticket is re-opened? Or should I make a new one, specifically asking for a better error message? > My view is that mappedsuperclass makes little sense in a per-heirarchy case. I don't think it matters what your (or my) view is, if it's possible using Hibernate, than why not support it?
Comment by External U.
6507 | February 19, 2016 10:53:04 AM GMT
I want to reiterate that this affects not only table per hierarchy but also singlet table inheritance when using a mapped super class. It also adds the mapped super class properties to the outmost child tables which is wrong. it should add them to the parent persistent entity. This works as expected in Railo and Lucee. Makes mapped super class unusable if you have complex inheritance models.
Comment by External U.
6508 | May 04, 2016 04:16:33 PM GMT
see my comments
Vote by External U.
6514 | May 04, 2016 04:16:42 PM GMT
If there is a way to patch cf10,11, and 2016. That would be great!
Comment by External U.
6509 | May 05, 2016 10:21:05 AM GMT
Found a new one that's related to this one: https://bugbase.adobe.com/index.cfm?event=bug&id=CF-4178506
Comment by External U.
6510 | August 03, 2016 03:48:42 PM GMT
The fix is risky and hence will get shipped in next release.
Comment by Awdhesh K.
6511 | March 23, 2017 11:57:12 AM GMT
@Awdhesh, Do you have a specific release in mind? Best regards, Mingo.
Comment by Mingo H.
6512 | September 29, 2017 10:27:39 AM GMT
@Mingo, this will be addressed in CF Aether release
Comment by Vamseekrishna N.
6513 | October 03, 2017 04:47:45 AM GMT