View Full Version : Save Custom Class to database
cjke.7777
December 8th, 2009, 12:31 AM
Hey guys,
I have a complex custom class which contains custom subclasses and so on. I want to save the state of an instance of this class to a database.
Currently I'm using a ByteArray.writeObject which seems to work well as I am using registerClassAlias, so all custom classes are being picked up and serialised correctly.
writeObject uses the AMF standard to "flatten" classes, but is AMF the best way to go to store the entire state of a class into a database?
Any tips/suggestions would be welcome.
Krilnon
December 8th, 2009, 01:21 AM
Are you just using the database as storage or are you going to want to be able to search the state of your objects from a database query?
cjke.7777
December 8th, 2009, 02:20 AM
Thats a great question, because i understand that would make a massive difference. I just need to store it, it won't be accessed while in the database.
Krilnon
December 8th, 2009, 03:08 AM
AMF seems fine, then. As far as I can remember right now, AMF doesn't compress its contents very much, other than to use variable length encoding for a few things. So, you might want to compress the objects you're sending before or after you send them if space is a concern.
Shaedo
December 8th, 2009, 08:44 AM
If I may ask, from reading the above, does this mean I can save a class in say a MySQL database as opposed to say loading a swf and extracting it from the library ?
Krilnon
December 8th, 2009, 12:22 PM
You can save/load class instances, not classes themselves. (I wasn't sure if that's what you meant) There are also some limitations around exactly what sort of data in an instance can be serialized.
cjke.7777
December 8th, 2009, 04:25 PM
Thanks Krilnon, I will continue to use AMF through the ByteArray write object method. I will also investigate the sizes, as the bytearray has a compress() method that might make some difference.
The only disadvantages I can see so far with AMF is that there has to be get/set methods for each property that needs to be saved and that AMF is undocumented by Adobe and the information available is through people around the net reverse engineering the standard.
Krilnon
December 8th, 2009, 04:36 PM
AMF is undocumented by Adobe and the information available is through people around the net reverse engineering the standard.
That's not completely true: http://opensource.adobe.com/wiki/download/attachments/1114283/amf3_spec_05_05_08.pdf
cjke.7777
December 8th, 2009, 04:51 PM
Ah true, I'm too dependent on the livedocs/help system within flash, which doesn't go into any detail on AMF.
As for the other point I made about get/set methods, I'm looking at my classes implementing the IExternalizable interface which means I can specifically state what properties should be saved. I'm still testing but I will put up some sample code later today to demonstrate how it works.
cjke.7777
December 8th, 2009, 10:13 PM
As mentioned earlier I said I would put up what I could find out. To protect your private variables without having to give them get/set methods you can implement IExternalizable which means that you will implement readExternal and writeExternal in your class.
You can then pass in your bytearray to these functions and add all the information about the class you want.
This bytearray can then be compressed and converted into a hex string and sent to the database. This can later be retrieved from the database and converted back into bytes and stored in a byte array. The byte array can then be used to create a class based on the fact you registered the class alias's earlier.
Note that the classes in the example below don't have constructor and are instead init'ed. Also note that all my private variables are kept private but the class is still created from the database.
Also note that the database is just a string for the sake of a simple example, in reality you could just have a database table with two fields, id and data, where data was a LONGBLOB or LONGTEXT and store the hex string there.
The code is below:
package {
import flash.display.Sprite;
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
public class SerialExample extends Sprite {
// A local represenation of what could be a database with a LONGTEXT field
private var db:String = "";
public function SerialExample():void {
// Send the data to the 'database'
setData();
// Get the data from the 'database'
getData();
}
public function setData():void {
// Register the names of these two classes
registerClassAlias("Person", Person);
registerClassAlias("Car", Car);
// Create an instance of two seperate classes, where one 'has' the other
var car:Car = new Car();
car.init(2009, "Ford Mustang", true);
var person1:Person = new Person();
person1.init("Chris", 25, car);
// Write to the ByteArray and compress
var ba:ByteArray = new ByteArray();
person1.writeExternal(ba);
ba.compress();
// Convert the ByteArray into a series of 2 digit hex values
var s:String;
ba.position = 0;
for (var i:int = 0; i < ba.length; i++) {
s = ba.readUnsignedByte().toString(16);
s = s.length < 2 ? "0" + s : s;
db += s;
}
}
public function getData():void {
var ba:ByteArray = new ByteArray();
// Get the data from the 'database' and place into array
var data:Array = db.split("");
// Currently the array looks like:
// data = [2, 2, 3, 4, 5, 3] Or something similar,
// which should be in groups of 2 like:
// data = [(22), (34), (53)]
for (var i:int = 0; i < data.length; i += 2) {
ba[int(i * 0.5)] = "0x" + data[i] + data[i+1];
}
ba.position = 0;
ba.uncompress();
var person2:Person = new Person();
// Copy data to new Person
person2.readExternal(ba);
// Output data to confirm
person2.output();
}
}
}
import flash.utils.*;
class Person implements IExternalizable {
private var o_name:String;
private var o_age:int;
private var o_car:Car;
public function Person() {
//do nothing
}
public function init(a_name:String, a_age:int, a_car:Car):void {
o_name = a_name;
o_age = a_age;
o_car = a_car;
}
public function output():void {
trace(o_name);
trace(o_age);
o_car.output();
}
// The items that should be read and written to the database
public function readExternal(input:IDataInput):void {
o_name = input.readUTF();
o_age = input.readInt();
o_car = input.readObject();
}
public function writeExternal(output:IDataOutput):void {
output.writeUTF(o_name);
output.writeInt(o_age);
output.writeObject(o_car);
}
}
class Car implements IExternalizable {
private var o_model:String;
private var o_year:Number;
private var o_automatic:Boolean;
public function Car() {
// do nothing
}
public function init(a_year:Number, a_model:String, a_automatic:Boolean):void {
o_year = a_year;
o_model = a_model;
o_automatic = a_automatic;
}
public function output():void {
trace(o_model);
trace(o_year);
trace(o_automatic);
}
// The items that should be read and written to the database
public function readExternal(input:IDataInput):void {
o_model = input.readUTF();
o_year = input.readDouble();
o_automatic = input.readBoolean();
}
public function writeExternal(output:IDataOutput):void {
output.writeUTF(o_model);
output.writeDouble(o_year);
output.writeBoolean(o_automatic);
}
}
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.