Wednesday, November 05, 2008

Re-inventing ORM, annotations re-invented for databases!

I am working on a web application where one of the requirements is that I use an in-house Java database access framework. Personally I would prefer to use something that complements Spring and that makes my life easier such as Hibernate Annotations, iBATIS or even Spring JDBCTemplates but requirements are requirements.

One of the problems I face is that I need to re-invent a lot of ORM wheels. The framework is very similar in essence to iBATIS.All the SQL is stored in external XML configuration files. The framework conducts the mappings conversion from ResultSets to lists of beans (using commons-beanutils). As such, like iBATIS there is plenty of scope to generate most of the repetitive Java code (interfaces, implementations, facades) and configuration files (SQL CRUD). I have previously experimented with the Middlegen code generation with iBATIS. Middlegen code is a little long in the tooth, as a project it seems to have stagnated back in 2005 (I suppose iBATOR and Hibernate Tools have long since superseded it). That said, because Middlegen is based on Velocity templates it is very flexible and perfect for this kind of thing. I was able to port my previous iBATIS code generating templates to produce suitable Java code for use with the in-house framework.

I have managed to get some quite sophisticated code generated. Apparently "Lazy Loading is easy", so I am attempting to implement that using CGLIB in my DAO. I have also produced a method that is similar to Hibernates's SaveOrUpdate method. A given entity may have two kinds of relationship; target one (OneToOne, ManyToOne) or target many (OneToMany). I have no ManyToMany relationships and this is deliberate!

How my SaveOrUpdate works is derived from some code I found in iBATIS in Action (By Clinton Begin, Brandon Goodin and Larry Meadors, Published by Manning). In section 5.3.2 Updating or deleting child records the following method is suggested:

public void saveOrder(SqlMapClient sqlMapClient, Order order)
throws SQLException {
if (null == order.getOrderId()) {
sqlMapClient.insert("Order.insert", order);
} else {
sqlMapClient.update("Order.update", order);
sqlMapClient.delete("Order.deleteDetails", order);
for(int i=0;i<order.getOrderItems().size();i++) {
OrderItem oi = (OrderItem) order.getOrderItems().get(i);
sqlMapClient.insert("OrderItem.insert", oi);

The above method addresses the target many relationships but does not address the target one relationships. My method works more like this:

  1. Iterate through all the target one entities and SaveOrUpdate these. Inserting any generated ids into the current entity.
  2. Save the current entity data fields
  3. Iterate through all the target many relationships and SaveOrUpdate these.

At this point I got a little stuck. I found that relatively often my target one relationships should not be the subject of further SaveOrUpdates. The characteristic of these relationships is when the data is fairly static and mostly provides the conent of drop-down lists. When you make a selection from a such a list you do not usually need to update the list itself!

Essentially, Middlegen generates everything based on the contents of the database. For these relationships I needed some way to designate the code generation behaviour for certain database columns.

In Java Persistence API implementations, like Hibernate Annotations, this kind of behaviour is very easily represented by using @Column(insertable=false, updatable=false). I needed a way for Middlegen to acquire this information from the database. Then I had a brainwave, in the most recent version of Middlegen (from the CVS) you can "getRemarks" for tables and columns. Database remarks can be acquired from DatabaseMetaData. The unfortunate thing is that I am using an Oracle database which AFAICT uses a non-standard treatment of "remarks". It turns out that the default behaviour of Oracle drivers is not to populate the DatabaseMetaData with remarks. In Oracle remarks are contained inside two special tables; user_tab_comments and user_col_comments. You can override the default behaviour of Oracle driver to populate remarks, this can be done at the BasicDataSource (using addConnectionProperty("remarksReporting", "true")) or on a OracleConnection (using setRemarksReporting(true)).

Armed with this information I can "annotate" database columns, so I can use something like this:

COMMENT ON COLUMN <table>.<column> IS 'insertable=false, updatable=false';

I tweaked MiddlegenPopulator to allow it to acquire remarks for Oracle from the DatabaseMetaData. The database now contains all the information I need to generate my DAO code. I can now tweak my DAO generation templates to miss out the SaveOrUpdate code for target one relationships which match the column comment of 'insertable=false, updatable=false'.

Simple huh? Or maybe just plain scary... annotations with databases!


ismjml said...

Have you mentioned to your company's powers that be that most likely over time you guys having to maintain your own ORM-like framework is costing way more in terms of development time, increasing development complexity, taking you away from actually writing business logic, and hampering your company's ability to hire people and get them up to speed since no one outside your company will know the framework? I assume you have mentioned those things, but if not, you might consider doing that. Otherwise I don't know what to say. I guess if you're Amazon or eBay you can make an argument for rolling your own everything but most companies aren't in that boat and shouldn't be rolling their own data access framework, web framework, etc. On the other hand, writing infrastructure code is usually more fun than doing business logic (to me anyway) so maybe it won't be too bad unless you get stuck doing nothing but maintaining that framework, eh?
Note: Comment imported. Original by Scott Leberknight website: at 2008-11-05 22:29

ismjml said...

No comment! ;)
Note: Comment imported. Original by markmc website: at 2008-11-05 22:44

ismjml said...

Your smart enough to know that keeping your mouth shut and doing what your told means keeping your job.

Also as long as the problems are there, and the longer they are there, the longer you get to keep your job as you have not finished your job.

Also its better if its only you who understands the code then its more difficult for them to hire new people to take your job.

Thats just reality.
Note: Comment imported. Original by philip at 2008-11-06 02:00

for ict 99 said...

The effectiveness of IEEE Project Domains depends very much on the situation in which they are applied. In order to further improve IEEE Final Year Project Domains practices we need to explicitly describe and utilise our knowledge about software domains of software engineering Final Year Project Domains for CSE technologies. This paper suggests a modelling formalism for supporting systematic reuse of software engineering technologies during planning of software projects and improvement programmes in Final Year Project Centers in Chennai.

Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai

madin said...

The Audemars Piguet Jules Audemarsreplica watchescollection commemorates one of the brand’s founders. The line is characterized by its traditional and timeless round cases and overall minimalist design. replica audemars piguet watchesHowever, behind the simplicity of these watches is an array of impressive functions, such as tourbillons, moon phases, and chronographs. Designed with both men and women in mind, the Jules Audemars collection fully embodies both the range and restraint of the brand.

madin said...

Cartier is the renowned French jeweller and watchmaker with swiss replica watches a history of pioneering design and a drive for excellence. replica rolex watches The first references to Cartier wristwatches date back to 1888. Late in the 19th century it was pocket and chatelaine watches that were most popular, but Louis Cartier saw a future in timepieces that could be worn on the wrist.

madin said...

The AAA cheap cartier watches uk sale at are best quality cheap fake watch from China,The replica ronde solo de cartier watches high end Cartier replica watches include Ballon Bleu De Cartier, Calibre De Cartier,Cartier La Dona,Cartier Love Watch,Cartier Pasha,Cartier Roadster,Cartier Santos,Cartier Tank replica watches,We can shipp to Uk,USA,canada,australia,and almost all country worldwide

madin said...

Gli orologi Longines sono stati un punto di riferimento del settore da quando il loro marchio è iniziato nel 1832 a Saint-Imier.repliche longines orologi Oggi il marchio offre una vasta gamma di orologi da uomo e da donna. repliche longines 1832 Gli orologi prodotti da Longines sono stati utilizzati nel corso della storia per tutto, dalle esplorazioni all'espressione dell'eleganza. Oltre ad essere famosi per i loro legami con il mondo delle corse e dei cavalli, gli orologi Longines sono riconosciuti a livello globale per la loro raffinatezza senza tempo e chic. abbiamo una varietà di orologi Longines in vendita, tutti nuovi, belli e garantiti per essere genuini. Ancora meglio, quando acquisti i nostri orologi Longines online, sai che stai ottenendo il miglior valore. Sfoglia la nostra selezione per trovare il miglior prezzo dell'orologio Longines su Internet.

madin said...

OMEGA has been a world leader in advanced watch design since 1848. Over the years, cheap replica watchesthe brand has been widely celebrated for their durability and precision. replica omega watches has served as the official timekeepers of the Olympic Games for nearly a century. They also created the official watch of the space program and first watch to land on the moon. Buying an OMEGA watch is an excellent way to invest in a piece of history.

madin said...

repliche nike air max 90 Scarpe da ginnastica Nike, repliche air max 1 dalla corsa e il basket all'allenamento e agli stili casual Le scarpe Nike ti hanno coperto. Acquista tutte le ultime novità in negozio o online su | City Gear.

madin said...

Expect tough heels and flat styles in the Alexander McQueen women's shoe line.Cheap ALEXANDER MCQUEEN uk Discover rich and replica mens ALEXANDER MCQUEEN boot detailed decorations, such as fine embroidery on stiletto heel designs, while chunky buckles and metal studs bring discerning edges to flats. This British brand pays tribute to the trend of sports and leisure through clever sneakers with contrasting pop balls, and masculine style with open shadow loafers with striking shadows.

madin said...

fake rolex watches offers a wide range of models ranging from professional to classic watches to suit any wrist. fake rolex cellini watches Explore the Rolex collection by selecting your favourite models, materials, bezels, dials and bracelets to find the watch that was made for you.