To answer your question directly about itemClass. You set the itemClass on
the SQLStatement class (see DataAccessObject.execute()). You won't be able
to use just any object. You'll need that to be your Product class.
Whatever holds the Product class will have to be rebuilt outside your DAO by
something else, or you'll have to persist that as well. Sounds like you
have to thinking that needs to be done about how you use your database and
persistence.
As for how you are operating I think I'm going to try and help you by
showing you some of my code for working with databases. Hopefully, this
might help you clean up your code and work more inline with how SQLite
works. Of course you can always go for the quicky and serialize data, but I
think you'll find out down the road serializing is not flexible enough for
maintenance issues.
For each object I plan on writing to the database I create a corresponding
DAO class. One DAO manages a single table in the database, and handles a
single object class in the system. It knows how to read and write objects
into and out of that table. These DAO classes are long living so when I
create my SQL Connection I pass that connection to these DAO classes, and
they live as long as the SQL Connection. If I drop or close it then I will
destroy these DAO classes and recreate them. This class is my base class
for all of my DAOs, and should be considered an abstract class in the java
sense. It may use other DAOs to save or retrieve data from other tables.
In fact the subclasses of this DAO will define more concrete operations for
the data they are handling. Think special queries, any table joins,
updates, saves (i.e. details like when I save a Book, I will also save the
Author). This would be an example where BookDao might use AuthorDao to save
the Author when the Book is saved. Those details are encapsulated in the
DAO layer.
Each DAO needs a sql connection, a class that will be used to hold the data
coming from this table, and the name of the table. For example:
var bookDao : BookDao = new BookDao( sqlConnection, Book, "books" );
Where BookDao extends DataAccessObject. Once you have that you get out of
the box some simple query methods like:
// fetch a book from the database by it's primary ID
var warAndPeace : Book = bookDao.findById( bookId ) as Book;
// fetch all books where the author_id = the ID of the author of War and
Peace
var books : Array = bookDao.findAll( "author_id=?", [ warAndPeace.author.id] );
Bear in mind these are just some simple examples. The real trick is loading
book doesn't fully load it's author since that would be in another table.
This is where your subclasses might need to specialize some loading methods,
etc.
Saving and updating objects must be provided by you in your subclasses, but
that's easy by overriding update and insert methods. Here's a quick
example:
public override function insert( object : PersistableObject ) :
PersistableObject {
var result : SQLResult = execute( "INSERT INTO Books ( " +
"title, author_id, year) values (?, ?, ?),
[ book.title, book.author_id, book.year ] );
book.id = result.lastInsertRowID;
return book;
}
So in your case you'd create a ProductDao since you want to save Product to
the database. ProductDao will load a Product back. Remember you must have
property functions (set/get) for each property in the database. These are
not optional. AIR will fail with an exception if you have a field in your
database that doesn't correspond to your object's properties. So the names
of your properties in your database must be the same as your object.
Here it is:
public class DataAccessObject {
private var connection : SQLConnection;
private var itemClass : Class;
private var table : String;
public function DataAccessObject( sql : SQLConnection, anItemClass :
Class, aTable : String ) {
this.connection = sql;
this.itemClass = anItemClass;
this.table = aTable;
}
public function loadSingleObject( itemClass : Class, table : String,
whereClause : String = null, params : Array = null ) : Object {
var query : String = "select * from " + table;
if( whereClause ) {
query += " where " + whereClause;
}
var result : SQLResult = execute( query, params, itemClass );
if( result.data ) {
if( result.data.length == 1 ) {
return result.data[0];
} else {
throw new SQLError( "Multiple instances returned for " +
table + " " + whereClause );
}
} else {
return null;
}
}
public function loadObject( itemClass : Class, table : String,
whereClause : String = null, params : Array = null ) : Array {
var query : String = "select * from " + table;
if( whereClause ) {
query += " where " + whereClause;
}
var result : SQLResult = execute( query, params, itemClass );
return result.data ? result.data : null;
}
public function collectBy( field : String, results : Object ) :
Object {
var collection : Object = {};
for each( var result : Object in results ) {
collection[ result[ field ] ] = result;
}
return collection;
}
public function execute( query : String, params : Array = null,
itemClass : Class = null ) : SQLResult {
var sql : SQLStatement = new SQLStatement();
sql.sqlConnection = connection;
sql.text = query;
if( params ) {
for( var i : int = 0; i < params.length; i++ ) {
sql.parameters[i] = params[i];
}
}
if( itemClass ) {
sql.itemClass = itemClass;
}
sql.execute();
return sql.getResult();
}
public function findById( id : Number ) : SyncableObject {
return loadSingleObject( itemClass, table, "internal_id=?", [ id
] ) as SyncableObject;
}
public function findByField( syncableField : Object, field : String
) : SyncableObject {
return loadSingleObject( itemClass, table, field + "=?", [
syncableField ] ) as SyncableObject;
}
public function findAll( whereClause : String = null, params : Array
= null ) : Array {
return loadObject( this.itemClass, this.table, whereClause,
params );
}
public function update( syncable : PersistableObject ) :
PersistableObject {
return null;
}
public function insert( syncable : PersistableObject ) :
PersistableObject {
return null;
}
}
On Wed, Aug 19, 2009 at 3:09 PM, Hepp, Michael W.
<[email protected]>wrote:
> Charlie,
>
> I wasn't aware of the itemClass property (not a database or sql guy) and I
> think you may be right that that is what I need to use, but I might have to
> change how I am storing the Product object...
>
> Currently, since the user can configure multiple products I add the
> configured Product object to an array
>
> private function addCurrentToMaster():void{
> quoteMaster[0] = cartDP;
> if ( quoteMaster.length == 0 ){
> quoteMaster[1] = addProduct;
> } else {
> quoteMaster[cartDP.length] = addProduct;
> }
>
> // Clear Previous Product
> productOptionsVS.removeAllChildren();
> } // END addCurrentToMaster()
>
> Then I clear out my viewStack and wait for the user to select another
> product to configure with options. (You will note that I use the first slot
> in the array to hold my dataGrid dataProvider.)
>
> When I write the object (which is actually an array with several Product
> Objects in it) to my database, it is sent along with other data:
>
> private function saveRecord( name:String ):void{
> // ADD EVENT LISTENER
> sqlQuoteConnection.addEventListener(
> SimpleSQLConnectionEvent.ITEM_ADDED, addRecordComplete );
> // EXECUTE SQL ACTION
> sqlQuoteConnection.create( quoteName, quoteMaster, getDate() );
> } // END saveRecord()
>
> When I read the data back into my app I call my SimpleSQLConnection class
> (quotedata is the array of Products),
>
> public function readOpenQuotes(event:SimpleSQLConnectionEvent = null):void
> {
> // This sql command retrieves OPEN quotes from our Table in the
> database and orders it by DATE
> var sqlStatement:String = "SELECT id, status, date, name,
> quotedata " +
> "FROM productQuote
> WHERE status='1'
> ORDER BY date DESC";
> // Add EVENT LISTENER
>
> sqlQuoteConnection.addEventListener(SimpleSQLConnectionEvent.READ_COMPLETE,
>
> parentDocument.openQuoteReadComplete);
> // EXECUTE SQL ACTION
> sqlQuoteConnection.read(sqlStatement);
> trace("GET OPEN");
> } // END readOpenQuotes()
>
> The read() function in my SimpleSQLConnection class is where I assume the
> itemClass would be added
>
> private function select(stmt:String):void{
> var selectStatement:SQLStatement = new SQLStatement();
> selectStatement.text = stmt;
> selectStatement.sqlConnection = sqlConnection;
>
> selectStatement.addEventListener(SQLEvent.RESULT, onSelect);
> selectStatement.addEventListener(SQLErrorEvent.ERROR, errorHandler);
>
> selectStatement.text = stmt;
> selectStatement.execute();
> } // END select()
>
> However since the results data is not a Product, rather the quotedata is
> part that contains the array containing the products selected, I am not sure
> how to identify the quotedata as the itemClass. I am afraid that I may have
> to go back to the example I got the SimpleSQLConnection class from and
> rework my class... in the example (now that I am looking back on it) they
> created a ItemTO class and typed all the data being added to the database
> with that class and then used the itemClass in their call for data.
>
> I will see if I can rework it and get it on the right track... thanks so
> much you heading me in the right direction.
>
> Mike
>
>
> -----Original Message-----
> From: [email protected] on behalf of Charlie Hubbard
> Sent: Wed 8/19/2009 11:41 AM
> To: [email protected]
> Subject: Re: [AFFUG Discuss] Saving and retrieving objects in AIr
>
> It just sounds like you have a bug in the layer that saves your object to
> the database. How are you saving and retrieving the object? What does
> your
> DAO look like? SQL?
> Rereading your post I think maybe you have a class called Product and
> you're
> wanting to get back a Product object from sql when you query the database.
> You need to set the itemClass in order to get AIR to instantiate your
> specific object. Otherwise it just comes back as a plain Object in which
> case you'd get a NULL when casting to your user defined Product type.
>
> Still seeing your code (simplified) could help.
>
> Charlie
>
> On Wed, Aug 19, 2009 at 11:32 AM, Hepp, Michael W.
> <[email protected]>wrote:
>
> > Greetings All,
> >
> > I am wondering if it is possible to save generated Objects and then
> > retrieve them in the state they were saved in... e.g. I have a product
> quote
> > generator app created in AIR. Based on the product the user selects a
> number
> > of options on seperate pages with radio buttons are created and added to
> a
> > ViewStack via my AddProduct() class and the user goes through and selects
> > the various options he wants for that particular product. This
> configuration
> > can then be saved to a pdf and a local SQLite database.
> >
> > I am writing the AddProduct() object directly to the database, but when I
> > retrieve it, is comes back in a slightly different form... an Object with
> > two properties and when I try to type it to an AddProduct() I get a null
> > value.
> >
> > I don't know if I am explaining this well enough, but any input/ideas on
> > how to get this data back in the same form as the Object was save would
> be
> > greatly appreciated.
> >
> > Mike
> >
> > -------------------------------------------------------------
> > To unsubscribe from this list, simply email the list with unsubscribe in
> > the subject line
> >
> > For more info, see http://www.affug.com
> > Archive @ http://www.mail-archive.com/discussion%40affug.com/
> > List hosted by FusionLink <http://www.fusionlink.com>
> > -------------------------------------------------------------
>
>
>
>
> -------------------------------------------------------------
>
> To unsubscribe from this list, simply email the list with unsubscribe in
> the subject line
>
>
>
> For more info, see http://www.affug.com
>
> Archive @ http://www.mail-archive.com/discussion%40affug.com/
>
> List hosted by http://www.fusionlink.com
>
> -------------------------------------------------------------
>
>