-->
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.  [ 7 posts ] 
Author Message
 Post subject: use of factories -- architecture problem with inheritence
PostPosted: Wed Apr 05, 2006 2:41 pm 
Beginner
Beginner

Joined: Mon May 09, 2005 5:26 pm
Posts: 21
Hello,

One class, two interfaces and a boatload of implementing classes. Class A is a 1-to-0-or-1 mapping to interface B which potentially has a great many implementing classes. Bimpl has a 1-to-many mapping to interface C, again with potentially many implementing classes.

Using <subclass> and table-per-class-hierarchy seems straightforward, but bulky. I have a factory class capable of creating instances of Bimpl and would prefer to use that. Further, instances of Bimpl are smart enough to create the necessary Cimpl instances, but just need the properties set properly.

I'd like to do something like create a class BMock which also implements B. Map it within A as just:
Code:
<many-to-one name="B" column="bID" class="BMock" unique="true"/>


within class A :
Code:
private B b;

// methods only used by Hibernate.  business methods use getB and setB directly.
private B getBMock() { return b; }
private void setBMock(B b) { this.b = BFactory.getB(b); }


which I *think* would be ok, except for the fact that the instance of B that I'm keeping track of is different than that which Hibernate is keeping track of. So hibernate will (?) call setCs(Collection<C> cs) on the wrong object.

so, is there any way to sort of tell Hibernate "I know you gave me *that* object in the setX method, but I want you to use *this* object instead"? Or something like that.

Is there a better way of doing this? Should I just shut up and use <subclass>?

thanks,

-don.
Code:


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 05, 2006 5:51 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Hello Don,

I do not understand what makes your factory class more useful than the "Hibernate factory" saving your objects.

Could you explain this.

Best Regards

Sebastian

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 05, 2006 6:44 pm 
Beginner
Beginner

Joined: Mon May 09, 2005 5:26 pm
Posts: 21
Hello Sebastian,

The Factory has meaning on the business side. The implementing classes are easily distinguishable (and buildable) based on a single string which has real user meaning. It's what the client code is presently using. So, as it stands, the Factory is already there and I'd hoped to be able to reuse it rather than maintaining the (effectively same) information in a mapping file.

However, I'm certainly open to coaching/insults that point another direction. (Possibly there's a way to use the Hibernate factory in place of mine? Was your comment intended to imply this?)

thanks again,

-don.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 05, 2006 6:55 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Hello Don,

I feel that I got some details, to give a first answer but I feel as well that I did not get the full concept of your approach.

When your factories knows which concrete class B to generate when it gets a class A than I still would use Hibernate to save all the stuff. My factory would just generate B, create the relation between A and B and save A and B using Hibernate.

Regards Sebastian

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 05, 2006 10:01 pm 
Beginner
Beginner

Joined: Mon May 09, 2005 5:26 pm
Posts: 21
Hello Sebastian,

The problem, if there is one, is not with creating a transient object and persisting it -- I can certainly use the factory and normal object relations for that. It's when Hibernate reads back a persisted instance.

Hibernate will call the default constructor of whatever class it's told to use. I'd like to only tell it about one class (BMock in the above post), and be able to create the *real* class on my own. I think if B is the end of the object graph that this will work, but since B contains a collecion of persisted stuff, Hibernate will want to "own" that collection (for "merge" to work). Again, I know I can use <subclass> with a discriminator-value for each instance and let Hibernate "just handle it", but that means a pretty big mapping file that needs to be maintained.

thanks again for your thoughts,

-don.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 06, 2006 8:08 am 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Just an idea,

may be you can encapsulate your "special class" in your mapped class.
The constructor of your mapped class calls the factory to create the internal class from the allready mapped fields.

Regards Sebastian

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 8:27 pm 
Beginner
Beginner

Joined: Mon May 09, 2005 5:26 pm
Posts: 21
Hello Sebastian,

and a fine idea at that. That will certainly work. I was messing around with this for a really simple test case and decided it's not worth the hassle. It turns out that using <subclass> is a lot less painful. (I expect many here could have told me that). Yes, it's two places to keep track of one thing, but to do the encapsulation requires that the mapped class not only call the factory constructor, but also pass through all the various setter/getters.

What complicates this even further is that since the default constructor of the mapped class doesn't yet know enough to use the factory, the factory call has to wait until Hibernate calls the mapped class's setDescriminator (for want of a better name) method. I have no way of telling what order Hibernate will call the setXXX methods, and so must maintain a local copy of *each* parameter the subclasses uses, then call the subclass's setXXX after instantiation. setters/getters in the mapped class end up looking like:
Code:
getXXX() {
  if (subClassInstance != null) return subClassInstance.getXXX();
  return XXX;
}
setXXX(Thing thing) {
  this.thing = thing;
  if (subClassInstance != null) subClassInstance.setXXX(thing);
}


Then, for the special "discriminator" field that tells the factory how to work, we have:

Code:
setDescriminator(String d) {
  descriminator = d;
  subClassInstance = Factory.create(d);
  subClassInstance.setXXX1(xxx1);
  subClassInstance.setXXX2(xxx2);
  // etc.
}


it just starts to all smell a bit rotten. So, as I say, I'm back to jsut using <subclass> and letting Hibernate worry about it all. I overthink things too often I suppose.

Thanks for the input, I'm sending you a credit.

-don.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.