by Ido Ran 19 Feb 18:22
Where can I find information about BeanController and BeanListener

Hi,
I need to be able to control exactly the SQL which is generated for newly, updated and deleted bean before it is execute in the database.
I read that it is not possible with JPA but it is possible using BeanListener or BeanController of eBean.

Where can I find documentation and sample code about this?

Thank you very much,
Ido.

19 Feb 20:54
by Rob

Hmmm... the javadoc is the only place this is documented at the moment (its not in the user guide yet).

http://www.avaje.org/static/javadoc/pub/com/avaje/ebean/bean/BeanController.html

To replace the Update and Delete logic (with your own code) you want to use the BeanController.

Specifically you put your code into the preUpdate() and preDelete() methods and make sure you return false. Returning false tells Ebean that you have taken full control of the update/delete and you do NOT want Ebean to perform its normal update/delete logic.

I'm pretty sure there is not an example of this at the moment (sorry).

Let me know how that goes or if it is not working for you etc.

Cheers, Rob.

19 Feb 21:03
by Rob

There is a very simple BeanController example (in the example app) so that might be worth a look.

The BeanController doesn't do anything apart from send output to system out ... but perhaps useful.

20 Feb 21:04
by Ido Ran

Hi,
Thanks for the help. I'll try it out.
I'm working on building a version or temporal database so I'll need to take control over all of the sql building parts under the assumption that I always select data when I have a "current version" number at hand so after I'll alter the select statement quite a bit it will produce result set as if there is no other versions and objects could be constructed normally.
Also I need that both logical update and delete will be translated to physical insert so that previous version will be preserved in the database.
I'll be glad to send you more details about it, it can be great if I'll be able to use ebean framework to off-load the object building and persisting from me, otherwise I'll have to do it all myself.

Thanks again,
Ido.

20 Feb 21:11
by Ido Ran

I think I wasn't clear:
Is there an easy way to override the select statements used by ebean?
I saw you have BeanFinder but it looks like I'll have to build the objects myself.

Thanks again.

22 Feb 04:32
by Rob

Caution/Warning:
----------------
There are a number of design approaches to Temporal DB Design. One I have seen (and was forced to use) meant no foreign keys could be used. IMO life was made very very difficult by that DB design (and I would not recommend it).


Q: Is there an easy way to override the select statements used by ebean?
------------
For what you want ... right now no!! BeanFinder was designed to find/build objects from other data sources such as external files and in memory objects etc.

What I can add to Ebean was something that gets the QueryRequest object ... where you can manipulate the query object prior to execution. This does not exist yet. If it did, specifically what would you want to modify on the query (aka: add a predicate would be easy... what other change to the query do you need?).

"Current Version"
-------------------
For interest are you determining this via Timestamps? (effectiveStartDate effectiveEndDate etc) or using a DB trigger to maintain a version counter?

The queries you want are:
- find the "current" Customer where id = ? ..
- find the Customer where id = ? as at {timestamp}

How do you intend to differentiate between the "current" and the "as at" queries? Aka use a ThreadLocal?


Q: .. Also I need that both logical update and delete ...
------------
BeanController with preUpdate and preDelete does the trick here (perform your insert and return false). Note that if you use partial objects you may not have ALL the properties you need for an insert though.

Obviously a DB trigger is another approach...

Cheers, Rob.

23 Feb 06:39
by Ido Ran

Hi,
Thanks for the answer again.

I understand your warning, and yet I think I'll go with design close to that.
I have several related entity (I'm not saying tables - I'll get to that). I want to preserve the history of each entity - but not only by itself but also as whole to others. Meaning I will be able to put all changes on a timeline (one timeline) and see the changes.
Also I need to be able to work online with the history - not only manual revert to previous version but also selecting in the UI an entity with previous version and compare the current version with the old one.
It will create something like svn - single version numerator to all repository.

I understand that I will not be able to use foreign keys as regular database but than again it is not a regular database - it is temporal database implemented over relational database.

Since my version numerator is the single most unique thing across the database I'll also use it as primary key for each table - meaning the real primary key (which will not be unique in the table) will not be marked as primary key.
This is the key issue why ebean and other ORM are not well suited for this database design.
Let me expand that - if I have a student and classroom database - each student belong to single classroom.
First I add eddy(id=1,v=1) to student table. Then I add ClassA(id=1,v=2) to classroom. Now I assign eddy to ClassA which make new copy of eddy(id=1,v=3,class=1).
If I now select students and class in version 3 I get ClassA(v=2) with eddy(v=3).
Now, if I update eddy's name to eddy rock(id=1,v=4) I only update student table without touching classroom table - but now if I select version 4 I'll get new eddy's name, if I select version 3 I'll get the old eddy's name.

So foreign keys are still only column, now composed, and also I can update each table by itself without go over all other tables and update the referenced version.

The down side is that selecting the data become harder.

What do you think? :)

Thanks.

23 Feb 10:17
by Rob

Which DB are you planning on using (aka not Oracle)?

Firstly if you are/could use Oracle DB then you could look to use "flash back" query... (you can get the scn number from oracle and then execute a query like: select * from your_table as of scn 1048820473

I'm not aware of any other MVCC databases that expose their 'mvcc timestamp' like Oracle does ... but they maybe looking to do so and it might be worth a quick investigation. (Oracle SCN = System Change Number ... effectively a timestamp)

Personally I believe the complexity/costs involved in losing your primary and foreign keys is very high... but that is only based on my one time experience. I was not 'there' at the time of this DB design (that I later had to use) ... but I would suggest the desire for everything to have history overshadowed the reality that history was only needed on some tables and only on some queries ... AKA most queries where still 'as at now' queries ... and so IMO it was a poor DB design given the usage (it was very painful to use).

Can you have you cake and eat it too?
If you have not already ... I'd suggest investigating using history tables and DB triggers... (and maybe views with union's for history based queries). This way you get to:
- Keep normal primary and foreign keys
- Its really easy to use for 'as at now' queries
- You get a historical view of the data as required

I believe this approach would also do everything you want.

As a note... it looks to me like the global version number will become a 'hot point/contention point' for concurrent activity... so this could be a problem if you want to handle highly concurrent DB inserts/updates/deletes.

Hmmm... there was a "Temporal DB Design" pdf document I read a long time ago... I'll see if I can find it...

Cheers, Rob.

23 Feb 10:31
by Rob

FYI: A versioning extension for Hibernate ... http://www.jboss.org/envers/

Creates version tables... not sure if it generated DB triggers.

Hmmm... interesting.

28 Feb 00:18
by Ido Ran

Hi Rob,
I would like to thank you very much for point me to Envers project.
It is just what I was looking for, exact match :)

I'll keep on watching for eBean, I never know when I'll find another thing I need here.

Thank you again,
Ido.

28 Feb 03:21
by Rob

It can't be an exact match... because it uses Hibernate and not Ebean :)

... Ha, ha!!

Seriously, that's not a problem... hopefully I can get some functionality to match "envers" in the future ... and drag you back into the Ebean fold :)

Cheers, Rob.

Create a New Topic

Title:
Body:
 
Introduction User Guide (pdf) Install/Configure Public JavaDoc Whitepapers
General Database Specific Byte Code Deployment Annotations Features
Top Bugs Top Enhancements
woResponse