Very Cool Charlie... Thanks so much, even though I am not a database guy I think I am following this and I see some of the errors I made if creating this database and therefore my app... I will rethink (and rewrite) how I am approaching this... I will try to post updates as I get individual sections to work to make sure I am on the right track... thanks again for all your input.
Mike -----Original Message----- From: [email protected] on behalf of Charlie Hubbard Sent: Wed 8/19/2009 4:21 PM To: [email protected] Subject: Re: [AFFUG Discuss] Saving and retrieving objects in AIr 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 > > ------------------------------------------------------------- > > ------------------------------------------------------------- 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 -------------------------------------------------------------
<<winmail.dat>>
