Using the framework

It is really simple! All you have to do is to implement the empty interface net.sourceforge.floggy.persistence.Persistable or extend a class that implements it.

IMPORTANT: All concrete classes which implement this interface must have a public default constructor like any other POJO.

import net.sourceforge.floggy.persistence.Persistable;

public class Person implements Persistable {

        // Static fields aren't persisted
        public static int SOME_STATIC_FIELD = 1;
        
        private String name;
        private Date birthday;
        private char gender;
        private Phone[] phones;
        
        // Transient fields aren't persisted 
        private transient int age;
        
        // Each persistable class must have a public default constructor.
        public Person() {
                // Do something ...
        }
        
        ...
}

... 

public class Phone implements Persistable {

        private String number;
        private String extension;
        private int type; // Mobile, Home, Work, etc
        
        public Phone() {
                // Do something ...
        }
        
        ...
}

PersistableManager

All operations, such as saving, loading, deleting and finding objects are made through a single class called net.sourceforge.floggy.persistence.PersistableManager.

The basic operations are explained in the following examples:

Saving a new object

Person p = new Person();
p.setName(...);
p.setBirthday(...);
p.setGender(...);
p.setPhones(...);

try {
        PersistableManager pm = PersistableManager.getInstance();
        // A new object ID is generated.
        // You can use it in future operations.
        int id = pm.save(p);
} catch (FloggyException e) {
        ...
}

Loading a stored object

Person person = new Person();

try {
        PersistableManager pm = PersistableManager.getInstance();

        /* To load an object, use the object ID 
         * generated previously by the save() operation.
         */
        pm.load(person, id);
} catch (FloggyException e) {
        ...
}

Lazy loading a tree of objects

try {
        PersistableManager pm = PersistableManager.getInstance();

        /* Passing the lazy parameter with value true will avoid the
         * load of the Phone object associated to the Person instance.
         */
        pm.load(person, id, true);
} catch (FloggyException e) {
        ...
}

Changing the name of the RecordStore where the Persistable will be stored

public class Person implements Persistable, Nameable {

        ...
        
        public String getRecordStoreName() {
                return "NOSREP";
        }
        
}

Deleting a previously saved object

Person person = ...

try {
        PersistableManager pm = PersistableManager.getInstance();

        // Delete the object.
        pm.delete(person);
} catch (FloggyException e) {
        ...
}

Deleting all entities based on its class.

try {
        PersistableManager pm = PersistableManager.getInstance();

        // Delete all objects based on its class.
        pm.deleteAll(Person.class);
} catch (FloggyException e) {
        ...
}

Deleting all entities stored by the midlet.

try {
        PersistableManager pm = PersistableManager.getInstance();

        // Delete all objetcs.
        pm.deleteAll();
} catch (FloggyException e) {
        ...
}

Listing all objects

PersistableManager pm = PersistableManager.getInstance();

ObjectSet persons = pm.find(Person.class, null, null);
for (int i = 0; i < persons.size(); i++) {
        Person p = (Person) persons.get(i);
        ...
}

Listing all objects (fast version)

PersistableManager pm = PersistableManager.getInstance();

Person person = new Person();

ObjectSet persons = pm.find(Person.class, null, null);
for (int i = 0; i < persons.size(); i++) {
        /* The same instance is used to load the data. This avoid 
         * the creation of persons.size()-1 objects.  
         */
        persons.get(i, person);

        // Don't use the person reference outside the loop, only its data.
        //BAD
        list.add(person);
        //GOOD
        list.add(person.getName());
        ...
}

Using a filter to find specific objects

PersistableManager pm = PersistableManager.getInstance();

// Filtering persons by gender
ObjectSet persons = pm.find(Person.class, new MaleFilter(), null);
for (int i = 0; i < persons.size(); i++) {
        Person p = (Person) persons.get(i);
        ...
}

... 

public class MaleFilter implements net.sourceforge.floggy.persistence.Filter {

        public boolean matches(Persistable persistable) {
                Person p = (Person) persistable;
                return p.getGender() == 'M';
        }
        
} 

Using a comparator to sort the results of a search

PersistableManager pm = PersistableManager.getInstance();

// Sorting persons by age (younger first)
ObjectSet persons = pm.find(Person.class, null, new AgeCompator());

... 

public class AgeComparator implements net.sourceforge.floggy.persistence.Comparator {

        public int compare(Persistable o1, Persistable o2) {
                Person p1 = (Person) o1;
                Person p2 = (Person) o2;
                
                if (p1.getBirthday().getTime() < p2.getBirthday().getTime()) {
                        return PRECEDES;
                } 
                if (p1.getBirthday().getTime() > p2.getBirthday().getTime()) {
                        return FOLLOWS; 
                } 
                
                return EQUIVALENT;
        }

}

Checking if the object is already persisted.

Person person = new Person();

try {
        PersistableManager pm = PersistableManager.getInstance();
        
        // Checks if the object is persisted. This will return false
        boolean persisted = pm.isPersisted(person);

        // To load an object, use the object ID 
        // generated previously by a save() operation.
        pm.load(person, id);

        //This will return true
        persisted = pm.isPersisted(person);
} catch (FloggyException e) {
        ...
}

Getting the object id.

Person person = new Person();

try {
        PersistableManager pm = PersistableManager.getInstance();
        
        // Gets the object id. This will return -1
        int id = pm.getId(person);

        // saving the object
        pm.save(person);

        //This will return a value greater than 0
        id = pm.getId(person);
} catch (FloggyException e) {
        ...
}

Indexing fields.

First of all, you must create a floggy.xml file containing the following definitions:

<?xml version="1.0" encoding="UTF-8"?>
<floggy xmlns:tns="http://floggy.sourceforge.net/floggy-persistence-1.4.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://floggy.sourceforge.net/floggy-persistence-1.4.0 http://floggy.sourceforge.net/schema/floggy-persistence-1.4.0.xsd" generate-source="true">
        <persistables>
                <persistable class-name="net.sourceforge.floggy.persistence.Person" record-store-name="Person">
                        <indexes>
                                <index name="byName">
                                        <field>name</field>
                                </index>
                        </indexes>
                </persistable>
        </persistables>
</floggy>

This XML instance refer to a class called "Person" that contains a field named "name" that is configured as an index to our Person persistable class. You have to add the parameter configurationFile pointing to the file above.

Person person = new Person();
person.setName("Floggy");

try {
        PersistableManager pm = PersistableManager.getInstance();
        
        // saving the object
        pm.save(person);

        IndexFilter indexFilter = new IndexFilter("byName", "Floggy");
        ObjectSet os = manager.find(Person.class, indexFilter, false);
} catch (FloggyException e) {
        ...
}

Storing the index after a save operation.

Person person = new Person();
person.setName("Floggy");

PersistableManager pm = PersistableManager.getInstance();

try {

        // turn on the store of indexes after a save operations
        pm.setProperty(PersistableManager.STORE_INDEX_AFTER_SAVE_OPERATION, Boolean.TRUE);

        // saving the objects
        pm.save(person); 

} catch (FloggyException e) {
        ...
}

Persistence strategy.

The release 1.4.0 brought a new feature that enable the devoloper to change the persistence strategy for objects hierarchy. There are three types supported:

  • PerClass: all properties of all super and subclasses are mapped into subclasse's RecordStores. The properties of the objects hierarchy are handled as if not having hierarchy.
    import net.sourceforge.floggy.persistence.Persistable;
    import net.sourceforge.floggy.persistence.strategy.PerClassStrategy;
    
    public class Person implements Persistable, PerClassStrategy {
    
            private String name;
            private Date birthday;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Employee extends Person {
    
            protected long employeeId;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Customer extends Person {
    
            protected long favoriteProductId;
            ...
    }
    

    For the usecase above Floggy will end up with two RecordStores one called Employee and another Customer. Employee will contain the data for name, birthday and employeeId. Customer will contain the data for name, birthday and favoriteProductId.

  • Single: all properties of all super and subclasses are mapped into the same RecordStore, the super class RecordStore.
    import net.sourceforge.floggy.persistence.Persistable;
    import net.sourceforge.floggy.persistence.strategy.SingleStrategy;
    
    public class Person implements Persistable, SingleStrategy {
    
            private String name;
            private Date birthday;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Employee extends Person {
    
            protected long employeeId;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Customer extends Person {
    
            protected long favoriteProductId;
            ...
    }
    

    For the usecase above Floggy will end up with only one RecordStore called Person. All the object for Employee and Customer will be save on the same RecordStore.

  • Joined: the properties for each super and sublclasses are mapped to different RecordStores. Default.
    import net.sourceforge.floggy.persistence.Persistable;
    import net.sourceforge.floggy.persistence.strategy.SingleStrategy;
    
    public class Person implements Persistable, JoinedStrategy {
    
            private String name;
            private Date birthday;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Employee extends Person {
    
            protected long employeeId;
            ...
    }
    
    ...
    import net.sourceforge.floggy.persistence.Persistable;
    
    public class Customer extends Person {
    
            protected long favoriteProductId;
            ...
    }
    

    For the usecase above Floggy will end up with three RecordStores, called Person, Employee and Customer. Person will contain the data for name and birthday. Employee will contain the data for an entry on Person RecordStore and for employeeId. Customer will contain the data for an entry on Person RecordStore and for favoriteProductId.

Opening a shared Record Store.

If you need to open a shared Record Store you can configure the floggy.xml file with the information about it. Keep in mind that both application must use the exactly same Persistable classes

<?xml version="1.0" encoding="UTF-8"?>
<floggy xmlns:tns="http://floggy.sourceforge.net/floggy-persistence-1.4.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://floggy.sourceforge.net/floggy-persistence-1.4.0 http://floggy.sourceforge.net/schema/floggy-persistence-1.4.0.xsd" generate-source="true">
        <persistables>
                <persistable class-name="net.sourceforge.floggy.persistence.Person" record-store-name="Person" suite-name="BarbecueCalculator" vendor-name="Floggy" />
        </persistables>
</floggy>

Working with batch operations.

PersistableManager pm = PersistableManager.getInstance();

try {
        
        // turn on the batch operation
        pm.setProperty(PersistableManager.BATCH_MODE, Boolean.TRUE);

        // Run the heavy load/save operation
        myLoadSaveHeavyOperation(); 

} catch (FloggyException e) {
        ...
} finally {
        // turn off the batch operation
        pm.setProperty(PersistableManager.BATCH_MODE, Boolean.FALSE);
}