You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by to...@apache.org on 2004/05/09 15:50:30 UTC
cvs commit: db-ojb/forrest/src/documentation/content/xdocs/docu advanced-technique.xml basic-technique.xml
tomdz 2004/05/09 06:50:30
Modified: forrest/src/documentation/content/xdocs site.xml
forrest/src/documentation/content/xdocs/docu
advanced-technique.xml basic-technique.xml
Log:
Added section about using mapping interfaces
Revision Changes Path
1.11 +5 -2 db-ojb/forrest/src/documentation/content/xdocs/site.xml
Index: site.xml
===================================================================
RCS file: /home/cvs/db-ojb/forrest/src/documentation/content/xdocs/site.xml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- site.xml 9 May 2004 11:08:08 -0000 1.10
+++ site.xml 9 May 2004 13:50:29 -0000 1.11
@@ -109,11 +109,14 @@
<cascading href="#cascading"/>
<auto-retrieve href="#auto-retrieve"/>
<using-proxy href="#using-proxy"/>
- <single-proxy href="#single-proxy"/>
+ <collection-proxy href="#collection-proxy"/>
+ <reference-proxy href="#reference-proxy"/>
+ <proxy-customization href="#proxy-customization"/>
</basic-technique>
<advanced-technique label="Advanced Technique" href="advanced-technique.html" description="">
<anonymous-keys href="#anonymous-keys"/>
<polymorphism href="#polymorhism"/>
+ <interfaces href="#interfaces"/>
<using-rowreader href="#using-rowreader"/>
<rowreader-example href="#rowreader-example"/>
<nested-objects href="#nested-objects"/>
1.6 +252 -1 db-ojb/forrest/src/documentation/content/xdocs/docu/advanced-technique.xml
Index: advanced-technique.xml
===================================================================
RCS file: /home/cvs/db-ojb/forrest/src/documentation/content/xdocs/docu/advanced-technique.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- advanced-technique.xml 28 Apr 2004 08:03:52 -0000 1.5
+++ advanced-technique.xml 9 May 2004 13:50:29 -0000 1.6
@@ -687,6 +687,257 @@
</section>
</section>
+ <anchor id="interfaces"/>
+ <section>
+ <title>Using interfaces with OJB</title>
+ <p>
+ Sometimes you may want to declare class descriptors for interfaces rather
+ than for concrete classes. With OJB this is no problem, but there are a
+ couple of things to be aware of, which are detailed in this section.
+ </p>
+ <p>
+ Consider this example hierarchy :
+ </p>
+ <source><![CDATA[
+public interface A
+{
+ String getDesc();
+}
+
+public class B implements A
+{
+ /** primary key */
+ private Integer id;
+ /** sample attribute */
+ private String desc;
+
+ public String getDesc()
+ {
+ return desc;
+ }
+ public void setDesc(String desc)
+ {
+ this.desc = desc;
+ }
+}
+
+public class C
+{
+ /** primary key */
+ private Integer id;
+ /** foreign key */
+ private Integer aId;
+ /** reference */
+ private A obj;
+
+ public void test()
+ {
+ String desc = obj.getDesc();
+ }
+}]]></source>
+ <p>
+ Here, class <code>C</code> references the interface <code>A</code> rather than <code>B</code>.
+ In order to make this work with OJB, four things must be done:
+ </p>
+ <ul>
+ <li>All features common to all implementations of <code>A</code> are declared in the
+ class descriptor of <code>A</code>. This includes references (with their foreignkeys)
+ and collections.</li>
+ <li>Since interfaces cannot have instance fields, it is necessary to use bean properties instead.
+ This means that for every field (including collection fields), there must be accessors
+ (a get method and, if the field is not marked as <code>access="readonly"</code>, a set
+ method) declared in the interface.</li>
+ <li>Since we're using bean properties, the appropriate
+ <code>org.apache.ojb.broker.metadata.fieldaccess.PersistentField</code>
+ implementation must be used (see <link href="#persistent-field">below</link>).
+ This class is used by OJB to access the fields when storing/loading objects. Per default,
+ OJB uses a direct access implementation
+ (<code>org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectAccessImpl</code>) which
+ requires actual fields to be present.<br/>
+ In our case, we need an implementation that rather uses the accessor methods. Since the
+ <code>PersistentField</code> setting is (currently) global, you have to check whether
+ there are accessors defined for every field in the metadata. If yes, then you can use the
+ <code>org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldIntrospectorImpl</code>,
+ otherwise you'll have to resort to the
+ <code>org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldAutoProxyImpl</code>, which
+ determines for every field what type of field it is and then uses the appropriate
+ strategy.</li>
+ <li>If at some place OJB has to create an object of the interface, say as the result type of
+ a query, then you have to specify <code>factory-class</code> and <code>factory-method</code>
+ for the interface. OJB then uses the specified class and (static) method to create an
+ uninitialized instance of the interface.</li>
+ </ul>
+ <p>
+ In our example, this would result in:
+ </p>
+ <source><![CDATA[
+public interface A
+{
+ void setId(Integer id);
+ Integer getId();
+ void setDesc(String desc);
+ String getDesc();
+}
+
+public class B implements A
+{
+ /** primary key */
+ private Integer id;
+ /** sample attribute */
+ private String desc;
+
+ public String getId()
+ {
+ return id;
+ }
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+ public String getDesc()
+ {
+ return desc;
+ }
+ public void setDesc(String desc)
+ {
+ this.desc = desc;
+ }
+}
+
+public class C
+{
+ /** primary key */
+ private Integer id;
+ /** foreign key */
+ private Integer aId;
+ /** reference */
+ private A obj;
+
+ public void test()
+ {
+ String desc = obj.getDesc();
+ }
+}
+
+public class AFactory
+{
+ public static A createA()
+ {
+ return new B();
+ }
+}]]></source>
+ <p>
+ The class descriptors would look like:
+ </p>
+ <source><![CDATA[
+<class-descriptor
+ class="A"
+ table="A_TABLE"
+ factory-class="AFactory"
+ factory-method="createA"
+>
+ <extent-class class-ref="B"/>
+ <field-descriptor
+ name="id"
+ column="ID"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+ <field-descriptor
+ name="desc"
+ column="DESC"
+ jdbc-type="VARCHAR"
+ length="100"
+ />
+</class-descriptor>
+
+<class-descriptor
+ class="B"
+ table="B_TABLE"
+>
+ <field-descriptor
+ name="id"
+ column="ID"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+ <field-descriptor
+ name="desc"
+ column="DESC"
+ jdbc-type="VARCHAR"
+ length="100"
+ />
+</class-descriptor>
+
+<class-descriptor
+ class="C"
+ table="C_TABLE"
+>
+ <field-descriptor
+ name="id"
+ column="ID"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+ <field-descriptor
+ name="aId"
+ column="A_ID"
+ jdbc-type="INTEGER"
+ />
+ <reference-descriptor name="obj"
+ class-ref="A">
+ <foreignkey field-ref="aId" />
+ </reference-descriptor>
+</class-descriptor>
+]]></source>
+ <p>
+ One scenario where you might run into problems is the use of interfaces for
+ <link href="#nested-objects">nested objects</link>. In the above example, we could
+ construct such a scenario if we remove the descriptors for <code>A</code> and
+ <code>B</code>, as well as the foreign key field <code>aId</code> from
+ class <code>C</code> and change its class descriptor to:
+ </p>
+ <source><![CDATA[
+<class-descriptor
+ class="C"
+ table="C_TABLE"
+>
+ <field-descriptor
+ name="id"
+ column="ID"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+ <field-descriptor
+ name="obj::desc"
+ column="DESC"
+ jdbc-type="VARCHAR"
+ length="100"
+ />
+</class-descriptor>
+]]></source>
+ <p>
+ The access to <code>desc</code> will work because of the usage of bean properties,
+ but you will get into trouble when using
+ <link href="site:basic-technique/dynamic-proxy">dynamic proxies</link> for <code>C</code>.
+ Upon materializing an object of type <code>C</code>, OJB will try to create
+ the instance for the field <code>obj</code> which is of type <code>A</code>.
+ Of course, this is an interface but OJB won't check whether there is class
+ descriptor for the type of <code>obj</code> (in fact there does not have to
+ be one, and usually there isn't) because <code>obj</code> is not defined as
+ a reference. As a result, OJB tries to instantiate an interface, which of
+ course fails.<br/>
+ Currently, the only way to handle this is to write a
+ <link href="site:basic-technique/proxy-customization">custom invocation handler</link>
+ that knows how to create an object of type <code>A</code>.
+ </p>
+ </section>
+
+
<anchor id="persistent-field"/>
<section>
<title>Change PersistentField Class</title>
1.6 +2 -2 db-ojb/forrest/src/documentation/content/xdocs/docu/basic-technique.xml
Index: basic-technique.xml
===================================================================
RCS file: /home/cvs/db-ojb/forrest/src/documentation/content/xdocs/docu/basic-technique.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- basic-technique.xml 9 May 2004 11:10:07 -0000 1.5
+++ basic-technique.xml 9 May 2004 13:50:30 -0000 1.6
@@ -426,7 +426,7 @@
</ul>
<p>
Further down a third solution
- <link href="#single-proxy">using a single proxy for a whole collection</link> will be
+ <link href="#collection-proxy">using a single proxy for a whole collection</link> will be
presented to circumvent the described drawbacks.
</p>
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org