Overview

RushOrm for Android replaces the need for SQL by mapping java classes to SQL tables.


What is the aim?

The aim is to abstract away all SQLite interaction under a very simple interface to make object storage incredibly quick to implement.

What projects is it right for?

  • Projects with complex data structures
  • Projects that want to implement database storage in the minimum amount of time
  • Projects that talk to a rest api

Why was RushOrm written?

  • Complex relationships - RushObjects support Lists of other RushObjects
  • SQL free migration
  • Easily extendable
  • No dependencies
  • Support asynchronous call
  • Be fast through compound inserts and selects
  • Support importing and exporting data to and from JSON
  • Unique ids to support merging databases
  • Supports conflict resolution when importing data
While there are a number of other ORMs, the areas many seem to fall short is the support of 'one to many' relationships, migration and extensions. While claiming all the same basic feature of most other ORMs RushOrm supports 'List' properties without having to add the parent object to it's children. It also handles migrating the class structure without any SQL scripts being required by the developer. Finally it is designed with the understanding that not every situation can be anticipated so instead it can be easily customized.


Setup

RushOrm needs to be initialized before use. The best place to do this is in the Application class.

              	
    public class ExampleApplication extends Application {

        @Override
        public void onCreate() {
            super.onCreate();

            // Rush is initialized asynchronously to recieve a callback after it initialized
            // set an InitializeListener on the config object

            // All classes that extent RushObject or implement Rush must be added to the config
            // this is new to v1.3.0 to fix issues introduced in android 6, 
            // this is far more efficient that searching for classes like in pervious versions
            List<Class<? extends Rush>> classes = new ArrayList<>();			
            classes.add(MyRushObject1.class);
            classes.add(MyRushObject2.class);
        	...

            AndroidInitializeConfig config 
                                    = new AndroidInitializeConfig(getApplicationContext(), classes);
            RushCore.initialize(config);
        }
    }
					
				

Extra information can be optionally added to the Manifest the defaults are specified below.

              	
              	
   <application
              	
              	...
              	
      <!-- Updating this will cause a database upgrade -->
      <meta-data android:name="Rush_db_version" android:value="1" />
   
      <!-- Database name -->
      <meta-data android:name="Rush_db_name" android:value="rush.db" />
   
      <!-- Setting this to true will cause a migration to happen every launch, 
      this is very handy during development although could cause data loss -->
      <meta-data android:name="Rush_debug" android:value="false" />
   
      <!-- Turning on logging can be done by settings this value to true -->
      <meta-data android:name="Rush_log" android:value="false" />

   </application>
					
				

Tables

Simply extend RushObject

              	
    public class ExampleObject extends RushObject {
        private String stringField;
        private double doubleField;
        private int intField;
        private long longField;
        private short shortField;
        private boolean booleanField;
        private Date dateField;
    
    	/* Use @RushIgnore annotation on fields you do not want to be saved */
    	@RushIgnore
    	public String ignoredField;
    
        /* Classes must include an empty constructer */
        public ExampleObject(){}
    }

    /* Create and save */
    ExampleObject object = new ExampleObject();
    
    /* Calling save will create or update table */
    
    /* Save synchronously */
    object.save();

    /* Save asynchronously */
    object.save(new RushCallback() {
        @Override
        public void complete() {
            /* Callback is on the thread objects where saved on, 
                not thread that called save */
        }
    });
					
				

If you class hierarchy means you can't extend RushObject, you can instead implement Rush interface and copy in the methods below.

              	
    public class ExampleObject implements Rush {
        @Override
        public void save() { RushCore.getInstance().save(this); }
        @Override
        public void save(RushCallback callback) { RushCore.getInstance().save(this, callback); }
        @Override
        public void delete() { RushCore.getInstance().delete(this); }
        @Override
        public void delete(RushCallback callback) { RushCore.getInstance().delete(this, callback); }
        @Override
        public String getId() { return RushCore.getInstance().getId(this); }
    }
					
				

Children

Classes can save other RushObject fields or lists.

              	
    public class ExampleObject extends RushObject {

        private ExampleObject otherObject;  
    
        /* By default all children are deleted when the parent is deleted,
            there are many reasons why this might not be wanted,
            to disable this add the annotation @RushDisableAutodelete */
    	@RushDisableAutodelete
    	private ExampleObject multiplyReferencedObject;  
    
        /* Lists must have @RushList annotation with classType,
        	listType can also be added the default is ArrayList */
        @RushList(classType = ExampleObject.class)
        private List<ExampleObject> otherObjects;
    
        /* Classes must include an empty constructer */
        public ExampleObject(){}
    }

    ExampleObject object = new ExampleObject();
    /* Saving will also save all children */
    object.save();
					
				

Select

Retrieving saved objects is as powerful as raw SQL.

              	
    /* Get all objects */
    List<ExampleObject> objects = new RushSearch().find(ExampleObject.class);
              	
    /* getId() will return object id or null if it has not been saved */
    ExampleObject table = new RushSearch().whereId("1").findSingle(ExampleObject.class);
    
    /* Get all objects with id 1 or intField greater than 5 */
    List<ExampleObject> objects = new RushSearch()
    					.whereId("1")
    					.or()
    					.whereGreaterThan("intField", 5)
    					.find(ExampleObject.class);
    
    /* Get all objects with id 1 or 
    	stringField equal "Hello world" and intField greater than 5 */
    List<ExampleObject> objects = new RushSearch()
    					.whereId("1")
    					.or()
    					.startGroup()
    					.whereEqual("stringField", "Hello world")
    					.and()
    					.whereGreaterThan("intField", 5)
    					.endGroup()
    					.find(ExampleObject.class);
    									
    /* Get all objects with id 1 or
    	stringField equal "Hello world" and intField greater than 5 
    	order ascending by intField */
    List<ExampleObject> objects = new RushSearch()
    					.whereId("1")
    					.or()
    					.startGroup()
    					.whereEqual("stringField", "Hello world")
    					.and()
    					.whereGreaterThan("intField", 5)
    					.endGroup()
    					.orderAsc("intField")
    					.find(ExampleObject.class);

					
				

See RushSearch javadoc for full further details.


Files

To handle long string, image or other data RushOrm has RushFile an extension to RushObject which writes data to disk.

              	
    RushTextFile file = new RushTextFile(getContext().getFilesDir().getAbsolutePath());
    file.setText("Hello world"); /* Set text saves table and write text to file */
    String text = file.getText();
    
    RushJSONFile file = new RushJSONFile(getContext().getFilesDir().getAbsolutePath());
    file.setJSON(object); /* Set JSON saves table and write text to file */
    JSONObject jsonObject = file.getJSON():
    
    RushBitmapFile file = new RushBitmapFile(getContext().getFilesDir().getAbsolutePath());
    file.setImage(bitmap); /* Set image saves table and write image to file */
    Bitmap bitmap = file.getBitmap();
				
			


Proguard

To use with progaurd you must exluce all classes than implement Rush

              	
    # Add this to the 'proguard-rules.pro' file
    -keep public class * implements co.uk.rushorm.core.Rush { *; }
				
			

Licence

Apache License, Version 2.0

              	
    Copyright (C) 2015 Stuart Campbell

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
					
				

Contributing

Please get in touch with any feedback or bugs, it is very much appreciated. Its also great to know if you found the project useful.

Author
Stuart Campbell | @stu_cams