Friday, February 26, 2010

Version 1.2 - Full Support of GAE Types

AuDAO now supports all Google App Engine types including Lists. Although Lists appeared in the version 1.1, it was only a limited solution. Now Lists can contain all types as normal single properties including the new types - GAE core types like Key, Geopt or User.

Let's look how it is easy to work with generated classes:
CREATE:
  OfficeDao dao = DaoFactory.createOfficeDao();

Office off = new Office();
off.setLocation( new GeoPt( latitude, longitude ));
off.setManager( new User( managerMail, "gmail.com" ));
off.setOnSite( Arrays.asList( off.getManager(), myself ));

dao.insert( off );

FIND (and also COUNT and DELETE):
  // location = geopt
dao.findByLocation( new GeoPt( latitude, longitude ));
...
// location IN (loc1, loc2, loc3)
dao.findByLocations( Arrays.asList( loc1, loc2, loc3 ));
...
// manager = user
dao.findByManager( new User( managerMail, "gmail.com" ));
...
// onSite IN (john, jack, myself)
dao.findBySomeOnSite( Arrays.asList( john, jack, myself ));
...
// onSite = manager AND onSite = myself
dao.findByAllOnSite( Arrays.asList( manager, myself ));

The last finder is one of the most interesting one - it automatically expands simple equality condition into several conditions concatenated by "AND" operator.

And all these DTO and DAO classes can be generated automatically from a source config XML file which can have less than 100 lines and 2KB of size! Learn more...

Well, if you need to create conditions dynamically, the DAO can be generated to allow it as well. GQL queries are supported:
  // find the office where the manager is on-site
// 0=offset, 1=maxRecords
dao.findDynamic("manager=USER(:1) AND onSite=USER(:1)", 0, 1, managerEmail);

You can create dynamic queries on keys as well:
  dao.findDynamic("__key__ IN :1", Arrays.asList( id1, id2, id3 ));

More information about GQL Parser you can find at here.

Happy generating !

Tuesday, February 2, 2010

Version 1.0 is out !

Yesterday we launched version 1.0 at http://audao.spoledge.com

And what is it ?

AuDAO is a tool for Java developers.

AuDAO let's you to generate Data Access Objects (DAO) layer for Java. So instead of using directly JDBC, JDO or other database access APIs, you can easily call abstract DAO layer methods like findByPrimaryKey(), insert(), update() or delete().

Simple Example ?

Certainly. First you must configure a source file to tell AuDAO how the DAO layer should look like. The source file is a well-formed XML (see also XSD):
<?xml version="1.0" encoding="utf-8"?>
<database xmlns="http://www.spoledge.com/audao" version="1.0">
<tables>
<table name="users">
<columns>
<column name="user_id">
<type>long</type>
<auto/>
<pk/>
</column>
<column name="user_name">
<type max-length="32">String</type>
<not-null/>
</column>
<column name="full_name">
<type max-length="128">String</type>
</column>
<column name="created_date">
<type>Date</type>
<auto/>
<not-null/>
</column>
<column name="last_login_date">
<type>Timestamp</type>
<auto/>
<not-null/>
<edit/>
</column>
</columns>
<indexes>
<index name="inx_user_name">
<unique/>
<columns>
<column name="user_name"/>
</columns>
</index>
</indexes>
<methods>
<count>
<all/>
</count>
<find>
<pk/>
</find>
<find>
<index name="inx_user_name"/>
</find>
<find name="latestLoggedIn">
<condition>
<query><![CDATA[last_login_date > ?]]></query>
<query dbtype="gae"><![CDATA[lastLoginDate > :1]]></query>
<params>
<column name="last_login_date"/>
</params>
</condition>
</find>
<delete>
<dynamic/>
</delete>
</methods>
</table>
</tables>
</database>


Then you use AuDAO tool to generate DAO layer - source Java files. You can either user the online generator or purchase a standalone version.

The generated DAO layer contains Data Transfer Object (DTO) - class User.java, abstract DAO interface UserDao.java and its hidden implementation UserDaoImpl.java. It also contains DaoFactory.java class which helps you to instantiate the DAO class.

The implementation classes vary by the target database type (Oracle, MySQL or Google App Engine), but the DTO and abstract DAO interface is still the same:

public long insert( User dto ) throws DaoException;
public void update( long userId, User dto) throws DaoException;
public int countAll();
public User findByPrimaryKey( long userId );
public User findByUserName( String userName );
public User[] findLatestLoggedIn( java.sql.Timestamp lastLoginDate )
public int deleteDynamic( String condition, Object... params )


How the generated DAO layer is used ?

To instantiate DAO interface just call DaoFactory methods. DaoFactory finds the right implementation class for you:
UserDao dao = DaoFactory.createUsedDao();

After that you can insert new records:
User dto = new User();
dto.setUserName("vaclav");
dto.setFullName("Vaclav Bartacek");
long userId = dao.insert( dto );

count or find one or more records:
int total = dao.countAll();
User user1 = dao.findByPrimaryKey( userId );
User user2 = dao.findByUserName( "vaclav" );
User[] lastHourUsers = dao.findByLatestLoggedIn( new Timestamp(System.currentTimeMillis()-3600000);

update records:
User dto2 = new User();
dto2.setLastLoginDate(new Timestamp(System.currentTimeMillis());
dao.update( userId, dto2 );

delete records (not logged within 90 days):
int totalDeleted = dao.deleteDynamic( "last_login_date < ?", new Timestamp(System.currentTimeMillis()-3600000L*24*90));


You can see that no JDBC or other database API calls are visible to you. The abstract layer allows you to develop for multiple database platforms.