Referencing more than one class using the same mapping

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Referencing more than one class using the same mapping

Esteban A. Maringolo
Let's suppose I want to have a "abstract" reference to any other object which is persisted, but that have different descriptor and different tables

Ej. OwnerClass will have a reference (instVar) holding an instance of Foo, Bar or Baz.

OWNERCLASS_TABLE will be as follows:

OWNER_ID | REF_CLASS | REF_ID
1        | Foo       | 100

2        | Bar       | 101
3        | Bar       | 100
4        | Baz       | 102

From the RDBMS point of view it will break relationships, because I can't define a FK on REF_ID because Foo, Bar, and Baz could be stored in different tables (otherwise I wouldn't need the REF_CLASS).

But I could still join tables given the proper filtering.


It's like an Embedded value, but using an "embedded reference" instead.
Is this possible with GLORP? Has anybody done this before?
I did this before with another Smalltalk ORM and because its use was light, there was no visible performance impact.


Regards!









--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

jtuchel
Esteban,

I am a bit late ( ;-) ) to the topic, but maybe this is still of interest...

I'm not aware of a ready-made embedded reference implementation, but I have used the pattern of an embedded value for such a thing. Only I had to implement a class for the "embedded reference" myself.
I implemented a superclass for all possible kinds of references and concrete subclasses for all the possible link types. The link objects use a 1:1 relationship to a well-defined table.

So there is something like

               1:1
OwnerClass <-------> AbstractLinkClass
                     

AbstractLink has subclasses:

                1:1
FooLinkClass <------> Foo


                1:1
BarLinkClass <------> Bar

                1:1
BazLinkClass <------> Baz



Since the link back from Foo/Bar/Baz is always back to the same OwnerClass/table, this is very much like a simple link table, just that the linking objects are mapped as embedded objects.

I've used this pattern in both TopLink and Glorp and this works quite nicely. The only negative is that there is a bunch of tiny objects that needs to be mapped, cached and maintained and the code sometimes just reads a bit shaky. You wouldn't implement a Class for such a use case in pure OO, so this is a bit weird. But you can hide a lot of that behind a nice API. The most challenging thing here was proper naming for the link objects, because they server no real purpose other than making your objects compatible to relational theory ;-) So you end up with "...Manager" or "...Link" or such crappy names.

I hope my explanation is clear and this is helpful for somebody, even if too late for you.

A completely different picture is if Foo, Bar and Baz are subclasses of a common abstract superclass. In that case you could use a HorizontalTypeResolver and forget about the REF_CLASS attribute as a whole. You just have to make sure you provide a Join on the Foo/Bar/Baz side of the descriptor system, because there is no forward pointer that could say which table to join to ;-)



Joachim
 
    



 

Am Samstag, 16. August 2014 03:48:08 UTC+2 schrieb Esteban A. Maringolo:
Let's suppose I want to have a "abstract" reference to any other object which is persisted, but that have different descriptor and different tables

Ej. OwnerClass will have a reference (instVar) holding an instance of Foo, Bar or Baz.

OWNERCLASS_TABLE will be as follows:

OWNER_ID | REF_CLASS | REF_ID
1        | Foo       | 100

2        | Bar       | 101
3        | Bar       | 100
4        | Baz       | 102

From the RDBMS point of view it will break relationships, because I can't define a FK on REF_ID because Foo, Bar, and Baz could be stored in different tables (otherwise I wouldn't need the REF_CLASS).

But I could still join tables given the proper filtering.


It's like an Embedded value, but using an "embedded reference" instead.
Is this possible with GLORP? Has anybody done this before?
I did this before with another Smalltalk ORM and because its use was light, there was no visible performance impact.


Regards!









--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

Esteban A. Maringolo
Thank you Joachim.

What yo propose is the reification of the relation, implemented as an embedded object. which is what I was trying to avoid. :)
It seems there is no other way to deal with it in ORMs in general.

El sábado, 11 de octubre de 2014 10:54:40 UTC-3, jtuchel escribió:
Esteban,

I am a bit late ( ;-) ) to the topic, but maybe this is still of interest...

I'm not aware of a ready-made embedded reference implementation, but I have used the pattern of an embedded value for such a thing. Only I had to implement a class for the "embedded reference" myself.
I implemented a superclass for all possible kinds of references and concrete subclasses for all the possible link types. The link objects use a 1:1 relationship to a well-defined table.

So there is something like

               1:1
OwnerClass <-------> AbstractLinkClass
                     

AbstractLink has subclasses:

                1:1
FooLinkClass <------> Foo


                1:1
BarLinkClass <------> Bar

                1:1
BazLinkClass <------> Baz



Since the link back from Foo/Bar/Baz is always back to the same OwnerClass/table, this is very much like a simple link table, just that the linking objects are mapped as embedded objects.

I've used this pattern in both TopLink and Glorp and this works quite nicely. The only negative is that there is a bunch of tiny objects that needs to be mapped, cached and maintained and the code sometimes just reads a bit shaky. You wouldn't implement a Class for such a use case in pure OO, so this is a bit weird. But you can hide a lot of that behind a nice API. The most challenging thing here was proper naming for the link objects, because they server no real purpose other than making your objects compatible to relational theory ;-) So you end up with "...Manager" or "...Link" or such crappy names.

I hope my explanation is clear and this is helpful for somebody, even if too late for you.

A completely different picture is if Foo, Bar and Baz are subclasses of a common abstract superclass. In that case you could use a HorizontalTypeResolver and forget about the REF_CLASS attribute as a whole. You just have to make sure you provide a Join on the Foo/Bar/Baz side of the descriptor system, because there is no forward pointer that could say which table to join to ;-)



Joachim
 
    



 

Am Samstag, 16. August 2014 03:48:08 UTC+2 schrieb Esteban A. Maringolo:
Let's suppose I want to have a "abstract" reference to any other object which is persisted, but that have different descriptor and different tables

Ej. OwnerClass will have a reference (instVar) holding an instance of Foo, Bar or Baz.

OWNERCLASS_TABLE will be as follows:

OWNER_ID | REF_CLASS | REF_ID
1        | Foo       | 100

2        | Bar       | 101
3        | Bar       | 100
4        | Baz       | 102

From the RDBMS point of view it will break relationships, because I can't define a FK on REF_ID because Foo, Bar, and Baz could be stored in different tables (otherwise I wouldn't need the REF_CLASS).

But I could still join tables given the proper filtering.


It's like an Embedded value, but using an "embedded reference" instead.
Is this possible with GLORP? Has anybody done this before?
I did this before with another Smalltalk ORM and because its use was light, there was no visible performance impact.


Regards!









--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

jtuchel
Esteban,

sure, you need a new Class that's not there for any business purpose. That is neither nice nor desirable. OTOH, it is a very shallow class, and form my point of view it is the one thing with the lowest PITA index ;-)

I guess you've seen my other post(s) on Sequences and HorizontalTypeResolvers. There, I had to solve a very similar problem, but I came form another direction: I had to add a new sibling class/table to an existing one and make them accessible through a "general" 1:n relationship from existing classes. This works very well now. And I could get away without a field that indicates the class of the associated objects in the 1-sided table.
The only requirement: the classes on the :n-side of the relationship must be treated as if they were subclasses of a common superclass in Glorp (I don't think a real inheritance relationship on the Smalltalk class is needed, in my case it was also the case that the two classes are "of the same kind" and inherit from the same superclass - I think Glorp doesn't really care about inheritance).
The downside: looking at the id on the 1-side of the relationship in the db, I cannot tell in which table the referenced object resides. So for SQL users, this relationship is hard to follow, but HorizontalTypeResolver can do this very elegantly.

Joachim


Am Donnerstag, 16. Oktober 2014 21:45:22 UTC+2 schrieb Esteban A. Maringolo:
Thank you Joachim.

What yo propose is the reification of the relation, implemented as an embedded object. which is what I was trying to avoid. :)
It seems there is no other way to deal with it in ORMs in general.

El sábado, 11 de octubre de 2014 10:54:40 UTC-3, jtuchel escribió:
Esteban,

I am a bit late ( ;-) ) to the topic, but maybe this is still of interest...

I'm not aware of a ready-made embedded reference implementation, but I have used the pattern of an embedded value for such a thing. Only I had to implement a class for the "embedded reference" myself.
I implemented a superclass for all possible kinds of references and concrete subclasses for all the possible link types. The link objects use a 1:1 relationship to a well-defined table.

So there is something like

               1:1
OwnerClass <-------> AbstractLinkClass
                     

AbstractLink has subclasses:

                1:1
FooLinkClass <------> Foo


                1:1
BarLinkClass <------> Bar

                1:1
BazLinkClass <------> Baz



Since the link back from Foo/Bar/Baz is always back to the same OwnerClass/table, this is very much like a simple link table, just that the linking objects are mapped as embedded objects.

I've used this pattern in both TopLink and Glorp and this works quite nicely. The only negative is that there is a bunch of tiny objects that needs to be mapped, cached and maintained and the code sometimes just reads a bit shaky. You wouldn't implement a Class for such a use case in pure OO, so this is a bit weird. But you can hide a lot of that behind a nice API. The most challenging thing here was proper naming for the link objects, because they server no real purpose other than making your objects compatible to relational theory ;-) So you end up with "...Manager" or "...Link" or such crappy names.

I hope my explanation is clear and this is helpful for somebody, even if too late for you.

A completely different picture is if Foo, Bar and Baz are subclasses of a common abstract superclass. In that case you could use a HorizontalTypeResolver and forget about the REF_CLASS attribute as a whole. You just have to make sure you provide a Join on the Foo/Bar/Baz side of the descriptor system, because there is no forward pointer that could say which table to join to ;-)



Joachim
 
    



 

Am Samstag, 16. August 2014 03:48:08 UTC+2 schrieb Esteban A. Maringolo:
Let's suppose I want to have a "abstract" reference to any other object which is persisted, but that have different descriptor and different tables

Ej. OwnerClass will have a reference (instVar) holding an instance of Foo, Bar or Baz.

OWNERCLASS_TABLE will be as follows:

OWNER_ID | REF_CLASS | REF_ID
1        | Foo       | 100

2        | Bar       | 101
3        | Bar       | 100
4        | Baz       | 102

From the RDBMS point of view it will break relationships, because I can't define a FK on REF_ID because Foo, Bar, and Baz could be stored in different tables (otherwise I wouldn't need the REF_CLASS).

But I could still join tables given the proper filtering.


It's like an Embedded value, but using an "embedded reference" instead.
Is this possible with GLORP? Has anybody done this before?
I did this before with another Smalltalk ORM and because its use was light, there was no visible performance impact.


Regards!









--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

Esteban A. Maringolo
Hi Joachim,

2014-10-17 3:44 GMT-03:00 jtuchel <[hidden email]>:
> Esteban,
>
> sure, you need a new Class that's not there for any business purpose. That
> is neither nice nor desirable. OTOH, it is a very shallow class, and form my
> point of view it is the one thing with the lowest PITA index ;-)

Sure it is. :)
I'm not using EmbeddedObjects yet, but they seem to be a powerful feature.

> The only requirement: the classes on the :n-side of the relationship must be
> treated as if they were subclasses of a common superclass in Glorp (I don't
> think a real inheritance relationship on the Smalltalk class is needed, in
> my case it was also the case that the two classes are "of the same kind" and
> inherit from the same superclass - I think Glorp doesn't really care about
> inheritance).

Mmm... this might be really helpful.
So you're saying I can have a common abstract object as the root of
the TypeResolver, and all the children of such resolver can be of
different class hierarchies, as long as they share a common
protocol/inteface as well as a set of common column names.

Particularly what I want to store is a set of "roles" (instances of
different classes) associated with aPersona (identity).
Not from the context of a role-based security model, but instead from
the "business model" of a role.

Not all roles share the same hierarchy and some have few columns, and
other have lot's of them.

I might give this approach a try, it seems to solve my needs.

> The downside: looking at the id on the 1-side of the relationship in the db,
> I cannot tell in which table the referenced object resides. So for SQL
> users, this relationship is hard to follow, but HorizontalTypeResolver can
> do this very elegantly.

Well, you can add an extra "hint" field, with no glorp practical use,
for those accessing the DB directly.
I've done stuff like that with other ORMs adding the extra "class"
field, together with an i), and even when it works perfectly from the
ORM side, it feels to me that it also somehow "breaks" the relational
model, and requires row filtering using that hint column before
joining, nothing terrible though.

Regards!

Esteban A. Maringolo

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

Alan Knight-2
There are also some variations of this kind of thing that you can model in different ways with Glorp. A conditional mapping will let you map in completely different ways based on some attribute of the object/tuple.  You can also use a link table in which you map part of the link to a constant. There's an example of this in Store where something might be a link to either a package or a bundle, which are stored in separate tables, and which one you're connected to is determined by the letter 'P' or 'B' in the link table. #descriptorForStorePackage: , blessingMapping.

If you have types where it makes sense for them to be in a hierarchy with an abstract root, that might be the simplest approach.

And of course these things make good sense in an object model, but not so much in a relational model, and performance might be an issue if these are heavily used. Somebody once told me not to bother with such things, make one big table with the union of all the columns, that's what relational databases are good at.



On 17 October 2014 06:41, Esteban A. Maringolo <[hidden email]> wrote:
Hi Joachim,

2014-10-17 3:44 GMT-03:00 jtuchel <[hidden email]>:
> Esteban,
>
> sure, you need a new Class that's not there for any business purpose. That
> is neither nice nor desirable. OTOH, it is a very shallow class, and form my
> point of view it is the one thing with the lowest PITA index ;-)

Sure it is. :)
I'm not using EmbeddedObjects yet, but they seem to be a powerful feature.

> The only requirement: the classes on the :n-side of the relationship must be
> treated as if they were subclasses of a common superclass in Glorp (I don't
> think a real inheritance relationship on the Smalltalk class is needed, in
> my case it was also the case that the two classes are "of the same kind" and
> inherit from the same superclass - I think Glorp doesn't really care about
> inheritance).

Mmm... this might be really helpful.
So you're saying I can have a common abstract object as the root of
the TypeResolver, and all the children of such resolver can be of
different class hierarchies, as long as they share a common
protocol/inteface as well as a set of common column names.

Particularly what I want to store is a set of "roles" (instances of
different classes) associated with aPersona (identity).
Not from the context of a role-based security model, but instead from
the "business model" of a role.

Not all roles share the same hierarchy and some have few columns, and
other have lot's of them.

I might give this approach a try, it seems to solve my needs.

> The downside: looking at the id on the 1-side of the relationship in the db,
> I cannot tell in which table the referenced object resides. So for SQL
> users, this relationship is hard to follow, but HorizontalTypeResolver can
> do this very elegantly.

Well, you can add an extra "hint" field, with no glorp practical use,
for those accessing the DB directly.
I've done stuff like that with other ORMs adding the extra "class"
field, together with an i), and even when it works perfectly from the
ORM side, it feels to me that it also somehow "breaks" the relational
model, and requires row filtering using that hint column before
joining, nothing terrible though.

Regards!

Esteban A. Maringolo

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Referencing more than one class using the same mapping

jtuchel
In reply to this post by Esteban A. Maringolo
Esteban,

Am Freitag, 17. Oktober 2014 15:42:33 UTC+2 schrieb Esteban A. Maringolo:
Hi Joachim,

2014-10-17 3:44 GMT-03:00 jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="OTdI3FOPfPYJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">jtu...@...>:
> Esteban,
>
> sure, you need a new Class that's not there for any business purpose. That
> is neither nice nor desirable. OTOH, it is a very shallow class, and form my
> point of view it is the one thing with the lowest PITA index ;-)

Sure it is. :)
I'm not using EmbeddedObjects yet, but they seem to be a powerful feature.


They are. I use them a lot, e.g. for Monetary Amounts, Timespans and many more things that reappear over and over again throughout the object model. Setting up a "virtual table" in the Descriptor feels a bit different and I always have to look into existing examples to remember how to do it, but this is an extremely handy feature.
 
> The only requirement: the classes on the :n-side of the relationship must be
> treated as if they were subclasses of a common superclass in Glorp (I don't
> think a real inheritance relationship on the Smalltalk class is needed, in
> my case it was also the case that the two classes are "of the same kind" and
> inherit from the same superclass - I think Glorp doesn't really care about
> inheritance).

Mmm... this might be really helpful.
So you're saying I can have a common abstract object as the root of
the TypeResolver, and all the children of such resolver can be of
different class hierarchies, as long as they share a common
protocol/inteface as well as a set of common column names.

Well, in my case, this really is a class hierarchy, but I think for Glorp, this is not necessary. The only required commonality in attributes/columns is the primary key.
 

Particularly what I want to store is a set of "roles" (instances of
different classes) associated with aPersona (identity).
Not from the context of a role-based security model, but instead from
the "business model" of a role.

Sounds like a clear inheritance hierarchy to me. There is an abstract class "Role" that does not map to any table, and a bunch of subclasses that each resides in a different table. As long as they all share the same primary key (which they obviously do, because the Person holds a collection of roleIds, right?), this sounds like a perfect candidate for HorizontalTypeResolver and horizontal inheritance to me.
 

Not all roles share the same hierarchy and some have few columns, and
other have lot's of them.

Sure, that is exactly why you may want to distribute the classes over a bunch of tables. 
 

I might give this approach a try, it seems to solve my needs.

Sounds like a perfect match to me. 
 

> The downside: looking at the id on the 1-side of the relationship in the db,
> I cannot tell in which table the referenced object resides. So for SQL
> users, this relationship is hard to follow, but HorizontalTypeResolver can
> do this very elegantly.

Well, you can add an extra "hint" field, with no glorp practical use,
for those accessing the DB directly.

Never thought about it, but it sounds like you could even solve this by some kind of pseudoVariable and a foreign key constraint (either in the db or only on the Glorp layer). But somehow doesn't really feel good to my stomach...
 

I've done stuff like that with other ORMs adding the extra "class"
field, together with an i), and even when it works perfectly from the
ORM side, it feels to me that it also somehow "breaks" the relational
model, and requires row filtering using that hint column before
joining, nothing terrible though.

Probably much better than not having any hint as to what table to look at. And the filtering you mention is not necessary in the application, just for access from outside the Glorp universe. So depending on whether the database is more like exclusive to your Smalltalk Application or is shared with other applications, this may or may not be of concern.
 

Joachim 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.