Association enhancement

85 views
Skip to first unread message

Andrey Markhel

unread,
May 7, 2012, 10:51:05 AM5/7/12
to ActiveJDBC Group
Hi, Igor.

As I talk earlier I'd encountered some problems with AJ associations
in real-world relatively complex mappings. Let me explain by example.

1) There is entity Article in database, that entity should have 2
associations as one-to-one to table USER(author, editor). AJ can do it
by one-to-many association, but the problem there that both
associations has same type(User.class)

It is not possible for now to select right association via
Article.get(User.class), .include(User.class) etc..

It isn't rare case I think, for example in my project I have relations
- User - home adrress, billing address, etc.. or User - friends,
childs, parents, married, ignored users(self-referenced tables)

Yes, I saw your comments at 'One-to-many associations' page, and I
agree that there exist workaround - User author =
User.findByid(article.get("author_id")),
But I disagree with you, that this feature is complicated and not-
needed. Furthermore, I had implement this at local computer, but
unfortunatelly right after that computer was died:) Main point - is
add to all association one additional field -
"association_name"(optional), if that one isn't specified, "default"
association name is used. After that I rewrite a couple of methods
(include, get... ) and add to it one additional parameter
'association_name', for example

@BelongsToParents({
@BelongsTo(foreignKeyName="author_id",parent=User.class, name
="author"),
@BelongsTo(foreignKeyName="editor_id",parent=User.class, name =
"editor")
})
public class Article extends Model {}

and then author = Article.getAll(User.class, "author") editor =
Article.getAll(User.class, "editor"). My changes isn't break
compatibility, because getAll(User.class) is still worked (just
delegate to getAll(User.class, 'default')).

I think AJ will be only more powerful with that. I see one drawback -
there are need to add ~10 methods to Model.java and relatively
complicate API, but for me, additional power will outweight drawbacks.
Users will can map any associations in any way they want. Also, there
are no many effort with caching, cascade deletes etc.. because
associations has same type, if cache will be purged for one
association, it will be purged for second too. But, however, decision
by you. Also, I can commit my proposal and we can review. But at the
moment I want to know your thoughts about it, and if you completely
dislike it, I save big amount of time :)


2) Self-referenced tables, for example User has childs and has
parents, what this call will return? - User.include(User.class) :)

ipolevoy

unread,
May 7, 2012, 12:08:43 PM5/7/12
to activejd...@googlegroups.com
Andrey, I still stand by my opinion. You will have to agree that this is an edge case, and probably can be easily covered
by application level logic without much fuss.
You write:
"I think AJ will be only more powerful with that. I see one drawback -
there are need to add ~10 methods to Model.java and relatively
complicate API,"

which is a red flag for me. If I have to implement 10 methods in a class, for a case that is needed by very few people, and at the same time complicate the
framework, I'd vote to keep it lightweight.
ActiveJDBC implements ~80% of mundane tasks developers do, and I think this is a great balance. It helps it keep it 10- 20 times smaller than Hibernate, and at the same time twice as fast:
Please, see this:
http://igorpolevoy.blogspot.com/2012/04/just-how-thin-can-framework-be.html

Besides, if you have two users of article, why not simply use one to many association?

thanks
igor

Andrey Markhel

unread,
May 7, 2012, 12:47:04 PM5/7/12
to ActiveJDBC Group
Hi, Igor your words is reasonable enough. I agree with you that
simplicity is corner case for AJ+AW stack, and AJ is very attractive
in that 80%, but as usual man I want to give all 100% right here and
right now :) But I understand your position and didn't want that AJ
will grow like Hibernate monster :) I just think, that my addition
will be helpful for some percent of users, and if in future you decide
to change your mind - I can share my solution with you. Probably, you
can write separate page with some examples(like mine).

>>>>>>>>>>>
Besides, if you have two users of article, why not simply use one to
many
association?
>>>>>>>>>>>>

Because, it is different associations and handled by two separate
foreign keys. Yes, that can be looked as edge case, but I see that is
possible in RoR.. But, I understand that many things aren't possible
in Java.
Thanks for Aj anyway, great library.

ipolevoy

unread,
May 7, 2012, 1:03:47 PM5/7/12
to activejd...@googlegroups.com
Andrey, ActiveJDBC and ActiveWeb do not provide 100% functionality not because they do not have enough features, but because there is no such thing as 100% framework.
The 80% functionality of an ORM is more or less clearly defined, but the rest 20% is unlimited fuzziness that comes out of projects.
Requirements differ wildly from one project to another, and as a product developer, I need to see what will really make the core framework better and what not.
In other words, this is a simple cost-benefit analysis (...or gut feeling :)).

So far, from thousands of people using the frameworks, only two wanted this feature.

As far as your situation, maybe this can be solved with polymorphic associations?

If you say that RoR supports this situation, can you point to their docs?
BWT, does Hibernate has it?

thanks
igor

Andrey Markhel

unread,
May 7, 2012, 1:19:22 PM5/7/12
to ActiveJDBC Group
Igor I understand you, and your opinion is really reasonable.

About Hibernate and rors -
Hibernate support this situation, because mapping wroted on field
levels, not calss-level, And you should to define a lot of
info(valuable or not), but it is possible. But productivity when using
AJ is very high(in relation to Hibernate), so I think you are right.
RoR also support that, I didn't found exactly docs(but I remember that
I saw), maybe will lookup later. But there are post from stackoverflow
about it - http://stackoverflow.com/questions/4948766/multiple-associations-in-same-table-with-multiple-potential-foreign-keys
and
http://stackoverflow.com/questions/2530715/active-record-two-belongs-to-calls-or-single-table-inheritance

Smth like:
class MiniWizard < ActiveRecord::Base
has_one :bought_order_wizard, :foreign_key =>
'buyer_wizard_id', :class_name => 'MiniWizard'
has_one :sold_order_wizard, :foreign_key =>
'seller_wizard_id', :class_name => 'MiniWizard'
end


But I agree there are workarounds, polymorphic associations is one of.
But IMHO such mapping is little counter-intuitive and dirty. But it is
really not show stopper for me, maybe there are just my taste.

ipolevoy

unread,
May 7, 2012, 2:17:38 PM5/7/12
to activejd...@googlegroups.com
understand, ActiveJDBC I think supports this when you override one to many association with annotations like this:

@BelongsToParents({ 
@BelongsTo(foreignKeyName="key_id",parent=Keyboard.class),
@BelongsTo(foreignKeyName="mother_id",parent=Motherboard.class)
})

Have you tried to see if this works for you?

thanks
Igor

Andrey Markhel

unread,
May 8, 2012, 4:53:53 AM5/8/12
to ActiveJDBC Group
Certainly, I tried this, moreover its work perfectly.
Issue not in mapping, with AJ I can map all I want(maybe 2 many-to-
many on some table will be tricky, but I haven't tried yet).
Issue(or corner-case?) is when I use methods include(), getAll() and
parent(). For example, class Article

@BelongsToParents({
@BelongsTo(foreignKeyName="author_id",parent=User.class),
@BelongsTo(foreignKeyName="editor_id",parent=User.class)

})
Article extends Model
//........

So, when I call article.getAll(User.class) - ALL objects form ALL
associations for class User will be returned, in particular case there
will be Author and Editor. The same with include() and getAll(). I
mean there are no way to adjust what exactly I want to load - only
Author or only Editor, or both. That's little confusing. And that's
why I propose enhancement, it will be more pleasure to users, but as
you state earlier - there is workaround - write methods like User
author = User.find("id = ?", article.get("author_id"))

And 2 case, table User, that mapped like a tree, I mean User has
parent and childs

@BelongsTo(foreignKeyName="parent_id",parent=User.class)
User extends Model
//...
User user = User.findAll().include(User.class); ------------ What
there will be included and why? Only childs, only parents or both?

ipolevoy

unread,
May 8, 2012, 12:12:34 PM5/8/12
to activejd...@googlegroups.com


On Tuesday, May 8, 2012 3:53:53 AM UTC-5, Andrey Markhel wrote:
Certainly, I tried this, moreover its work perfectly.
Issue not in mapping, with AJ I can map all I want(maybe 2 many-to-
many on some table will be tricky, but I haven't tried yet).
Issue(or corner-case?) is when I use methods include(), getAll() and
parent(). For example, class Article

@BelongsToParents({
@BelongsTo(foreignKeyName="author_id",parent=User.class),
@BelongsTo(foreignKeyName="editor_id",parent=User.class)

})
Article extends Model
//........



I think that

 
So, when I call article.getAll(User.class) - ALL objects form ALL
associations for class User will be returned, in particular case there
will be Author and Editor. The same with include() and getAll(). I
mean there are no way to adjust what exactly I want to load - only
Author or only Editor, or both. That's little confusing. And that's
why I propose enhancement, it will be more pleasure to users, but as
you state earlier - there is workaround - write methods like User
author = User.find("id = ?", article.get("author_id"))

As you say, there is a workaround here, that is easy to understand. The problem I face when I see proposals like this is such that even if this functionality existed in AJ,
try writing documentation for it such that anyone can understand. Remember, while you are dealing with a specific problem in your application, this problem is clear to you,
but AJ is a general purpose ORM, and trying to explain behavior of some methods in JavaDoc is far from trivial, especially in cases like this.
Martin Fowler published this a few days ago: http://martinfowler.com/bliki/OrmHate.html, quote from this article:
"Essentially the ORM can handle about 80-90% of the mapping problems, but that last chunk always needs careful work by somebody who really understands how a relational database works."

Essentially you want this:

Model.parent(Model.class, "additional criteria");

Adding this should not be that difficult though.

 

And 2 case, table User, that mapped like a tree, I mean User has
parent and childs

@BelongsTo(foreignKeyName="parent_id",parent=User.class)
User extends Model
//...
User user = User.findAll().include(User.class); ------------ What
there will be included and why? Only childs, only parents or both?

Both will be returned  in this case
Reply all
Reply to author
Forward
0 new messages