I was thinking lately on what kind of API i'd like too see in OM. Here are
some thoughts:

there will be a pair of mapping objects for each table (need not be a
physical table, may be a combination of them) - the Object itself and Object
Criteria serving as some combination of Peer and existing Criteria.

the Object:

class Foo implements ...


contains getters/setters for fields:

public Integer getA();

public int getAAsInt();

public void setA(int);

public void setA(Integer);
 
related objects - collections & master records. distinguish dependencies vs.
non-dependencies, different cardinalities.

"save" methods:

public void save();

public void save(Transaction); (as discussed)

I think the best way to represent primary keys(and unique and foreign too)
is by creating inner interfaces or classes (not sure here):

public class PrimaryKey
{
        public Integer getA();
        ...
        public int hashCode();
        public boolean equals(Object);
        ...
}

complementary criteria objects. gets some functions from current criteria
but implements them in type-safe manner.

class FooCriteria implements ...

contains setters for all fields which would be used to specify selection
criteria:

public FooCriteria setA(int);

public FooCriteria setALessThan(int);

public FooCriteria setAGreaterEqual(int);

etc..

prolly by-name methods would also be helpful:

public FooCriteria setA(int val, Comparison comparison);

and

public FooCriteria setByName(String fieldName, Object val);

and something like:

public FooCriteria setARaw(String val);
which would use val as-is and can be used for some not-quite-standard SQL
hack should they be needed.

also, for the purposes of joining (see below) there should be methods like

public Field getA(); // returns Field object (sublass of it? IntField?)
representing field A. used for joins.

then criteria object would have following methods:

public List find(); //fetches list of objects satisfying the criteria. Maybe
it should return Iterator instead, or typed array?

public int update(Foo object); // updatetes all records matching these
criteria with values from Foo object.

public int delete(); //deletes matching records.


right now the objects are updated using their current PK value. This is not
quite good, because if pk is changed (which is allowed) save() will not work
properly.
in fact there are several correct ways to do update. i guess they should be
generation option.
different update modes are:
 - read-only objects (no update at all). this is useful for static tables
which you are never going to update.
 - update by PK - use _original_ PK (when object was retrieved) and not the
one of the modified object. So initial PK value needs to be preserved. this
will allow for identity change to be performed correctly. In this scenario
if two concurrent processes modify non-pk fields of the same record the one
who was the last wins and others lose their changes and do not know anything
about it "last-one-wins". A sub-option here is not to allow identity change.
in this case initial PK need not be preserved.
 - update by all columns - use original values of _all_ columns. same as
above, but if any field was changed the record will not be updated and
rowcount will be 0 so you can throw an exception. This can be useful if you
are really concerned about concurrent updates.


(by default) Foo & FooCriteria would not _extend_ any object, only implement
interface(s). The advantage is that you then can have Foo extend any class
you want - currently you have to have them extend BaseObject either directly
or indirectly. 

Here is how the usage would look like:

<code>
//construct criteria:

FooCriteria fc = new FooCriteria();
fc.setA(5);
fc.setBLess(10);

List foos = fc.find();

..iterate the list...

Foo foo = ... //get it from the list

a = foo.getA();

foo.setB(123);

foo.save();
</code>

etc...

Joins:

here is what API i envision for joins:

Criteria would have following methods for ech field:

public Field getA();

public FooCriteria setA(Field);


so "SELECT foo.* from foo,bar where foo.a=bar.a and foo.b=10 and bar.c>15"
will look like this:

FooCriteria fc = new FooCriteria();
BarCriteria bc = new BarCriteria();
fc.setB(10);
bc.setCMoreThan(15);
fc.setA(bc.getA());

List result = fc.find();

Complex criteria:

have some ideas here... will expand on this later...

Underlyng API:

I do not see much point in using village in the generated code. When
generating the db access code we have an opportunity to do maximum work and
leave the minimum to be done at run-time, so I do not see a hoge need for
abstraction and better API village provides. Plain JDBC would do just fine
and we would save some overhead... It made sense to use velocity with
handcoded Peers but not with generated...

Some time this millenium I will probably get to implementing this, but for
now I am just looking for feedback on the ideas themselves...

fedor.

-------------------------------
The Joy of CVS

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to