Source code
Tip №1: Avoid using generating data model from packages
-
Click to view static registry initialization via annotations example:
1@KITTY_DATABASE( 2 databaseName = "basic_database", 3 domainPackageNames = {"net.akaish.kittyormdemo.sqlite.basicdb"}, 4 logTag = LOG_TAG, 5 isLoggingOn = true, 6 isProductionOn = true, 7 isPragmaOn = true 8) 9@KITTY_DATABASE_REGISTRY( 10 // You can just define set of domain models and extended crud controllers (mappers) would 11 // be added only if those models are annotated with KITTY_EXTENDED_CRUD annotation. 12 // For example, for ComplexRandom.class it would be 13 // @KITTY_EXTENDED_CRUD(extendedCrudController = ComplexRandomMapper.class) 14 domainModels = { 15 ComplexRandomModel.class, 16 IndexesAndConstraintsModel.class, 17 RandomModel.class 18 }, 19 // Or you can provide explicit assignment of model->mapper pairs by defining domainPais 20 domainPairs = { 21 @KITTY_REGISTRY_PAIR(model = ComplexRandomModel.class, mapper = ComplexRandomMapper.class), 22 @KITTY_REGISTRY_PAIR(model = IndexesAndConstraintsModel.class), 23 @KITTY_REGISTRY_PAIR(model = RandomModel.class, mapper = RandomMapper.class) 24 } 25) 26public class BasicDatabase extends KittyDatabase { 27 ... 28} 29
-
Click to view static registry initialization via overloading
getStaticRegistry()
method example:1@KITTY_DATABASE( 2 databaseName = "basic_database", 3 logTag = LOG_TAG, 4 isLoggingOn = true, 5 isProductionOn = true, 6 isPragmaOn = true 7) 8public class BasicDatabase extends KittyDatabase { 9 10 public static final Map<Class<? extends KittyModel>, Class<? extends KittyMapper>> staticRegistry = new HashMap<>(); 11 12 static { 13 staticRegistry.put(ComplexRandomModel.class, ComplexRandomMapper.class); 14 staticRegistry.put(IndexesAndConstraintsModel.class, KittyMapper.class); 15 staticRegistry.put(RandomModel.class, RandomMapper.class); 16 } 17 18 public static final String LOG_TAG = "BASIC DB DEMO"; 19 20 /** 21 * KittyORM main database class that represents bootstrap and holder for all related with database 22 * components. 23 * <br> See {@link KittyDatabase#KittyDatabase(Context, String)} for more info. 24 * 25 * @param ctx 26 */ 27 public BasicDatabase(Context ctx) { 28 super(ctx); 29 } 30 31 @Override 32 protected Map<Class, Class<KittyMapper>> getStaticRegistry() { 33 return (Map) staticRegistry; 34 } 35} 36
Tip №2: Avoid multiply initialization of KittyDatabase
-
Click to view KittyDatabase implementation static initialization at
Application
implementation example:1public class AwesomeApplication extends Application { 2 3 private static AwesomeKittyDatabaseImplementation database; 4 5 public void onCreate() { 6 super.onCreate(); 7 AwesomeApplication.database = new AwesomeKittyDatabaseImplementation(getApplicationContext()); 8 } 9 10 public static AwesomeKittyDatabaseImplementation getAwesomeDB() { 11 return database; 12 } 13} 14
Tip №3: Optimize your data model and statements
-
Click to view
INDEX
declaration with KittyORM example:1@KITTY_TABLE(tableName = "cai") 2@INDEX(indexColumns = {"creation_date"}) // Index declaration example №1 3public class IndexesAndConstraintsModel extends KittyModel { 4 5 6 ... 7 8 @KITTY_COLUMN(columnOrder = 5) 9 @DEFAULT( 10 predefinedLiteralValue = LiteralValues.CURRENT_TIMESTAMP 11 ) 12 // Index declaration example №2 13 @ONE_COLUMN_INDEX(unique = true, indexName = "IAC_unique_index_creation_timestamp") 14 @NOT_NULL 15 public Timestamp creationTmstmp; 16 17 ... 18} 19
-
Click to view bulk insert operation in transaction mode with KittyORM example:
1void insertIntoDB() { 2 // Getting mapper instance and filling model collection with random models 3 RNDRandomModelFactory rndFactory = new RNDRandomModelFactory(Lesson2Tab5Random.this.getContext()); 4 RandomMapper mapper = (RandomMapper) getDatabase().getMapper(RandomModel.class); 5 List<RandomModel> toInsert = new ArrayList<>(); 6 for(int i = 0; i < 50000; i++) 7 toInsert.add(rndFactory.newRandomModel()); 8 9 // Saving list of 50k models in transaction mode 10 mapper.insertInTransaction(toInsert); 11 12 // Closing mapper 13 mapper.close(); 14} 15
Tip №6: Turn off logging at production
-
Click to view logging settings example:
1@KITTY_DATABASE( 2 isLoggingOn = false, // By default false, bootstrap and error logging 3 isProductionOn = true, // By default true, when false - query logging 4 isKittyDexUtilLoggingEnabled = false, // By default false, when true - a lot of logging about classes in app namespace at initialization 5 databaseName = "mig", 6 domainPackageNames = {"net.akaish.kittyormdemo.sqlite.migrations.migv4"}, 7 databaseVersion = 4, 8 logTag = MigrationDBv4.LTAG 9) 10public class MigrationDBv4 extends KittyDatabase { 11 ... 12} 13
Tip №7: Run expensive operations not in UI thread
-
Click to view example of KittyORM in
AsyncTask
:1 static final int INSERT_AMOUNT = 25; 2 3 static final String ERR_INSERT_RND = "Lesson5tab1InsertRNDDataError, see exception details!"; 4 5 class InsertRandomAsync extends AsyncTask<Long, Long, InsertRandomResults> { 6 ProgressDialog dialog; 7 8 @Override 9 protected void onPreExecute() { 10 dialog = ProgressDialog.show( 11 getLessonActivity(), 12 getString(R.string._l5_t1_running_requested_operation_pg_title), 13 getString(R.string._l5_t1_running_requested_operation_pg_body) 14 ); 15 dialog.setCancelable(false); 16 } 17 18 @Override 19 protected InsertRandomResults doInBackground(Long... strings) { 20 if(getSf().currentMigDBVersion() > DB_IMPLEMENTATION_VERSION) { 21 return new InsertRandomResults( 22 null, 23 -1l, 24 -1l, 25 -1l, 26 false, 27 getSf().currentMigDBVersion() 28 ); 29 } else { 30 try { 31 KittyMapper mapper = getDatabase().getMapper(MigOneModel.class); 32 long recordsCount = mapper.countAll(); 33 long affected = mapper.deleteAll(); 34 LinkedList<MigOneModel> modelsToInsert = new LinkedList<>(); 35 getSf().setDatabaseCreated(true); 36 getSf().setCurrentMigDBVersion(DB_IMPLEMENTATION_VERSION); 37 getSf().setDatabaseDeletedManually(false); 38 MigV1RandomModelFactory factory = new MigV1RandomModelFactory(getContext()); 39 for (int i = 0; i < INSERT_AMOUNT; i++) { 40 MigOneModel m = factory.newM1RndModel(); 41 modelsToInsert.addLast(m); 42 } 43 mapper.insertInTransaction(modelsToInsert); 44 List<MigOneModel> models = mapper.findAll(); 45 long recordsCountAfter = mapper.countAll(); 46 mapper.close(); 47 Iterator<MigOneModel> mI = models.iterator(); 48 LinkedList<String> out = new LinkedList<>(); 49 while (mI.hasNext()) { 50 out.addLast(mI.next().toString()); 51 } 52 return new InsertRandomResults(out, affected, recordsCount, recordsCountAfter, true, getSf().currentMigDBVersion()); 53 } catch (Exception e) { 54 Log.e(MigrationDBv1.LTAG, ERR_INSERT_RND, e); 55 if (e instanceof KittyRuntimeException) { 56 if (((KittyRuntimeException) e).getNestedException() != null) { 57 Log.e(MigrationDBv1.LTAG, ERR_INSERT_RND, ((KittyRuntimeException) e).getNestedException()); 58 } 59 } 60 return new InsertRandomResults( 61 null, 62 -1l, 63 -1l, 64 -1l, 65 false, 66 getSf().currentMigDBVersion() 67 ); 68 } 69 } 70 } 71 72 @Override 73 protected void onPostExecute(InsertRandomResults result) { 74 dialog.cancel(); 75 if (eventsListView != null) { 76 eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>())); 77 eventsListView.setOnTouchListener(new View.OnTouchListener() { 78 79 // Setting on Touch Listener for handling the touch inside ScrollView 80 @Override 81 public boolean onTouch(View v, MotionEvent event) { 82 // Disallow the touch request for parent scroll on touch of child view 83 v.getParent().requestDisallowInterceptTouchEvent(true); 84 return false; 85 } 86 }); 87 if (result.operationSuccess) { 88 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t1_count_to_events), result.modelsCountBefore)); 89 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t1_deleted_to_events), result.deletedModelsAffectedRows)); 90 for (String modelString : result.modelInsertions) { 91 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t1_inserted_to_events), M1M1TN, modelString)); 92 } 93 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t1_count_to_events), result.modelsCountAfter)); 94 } else { 95 if(getSf().currentMigDBVersion() > DB_IMPLEMENTATION_VERSION) { 96 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_op_mig_version_is_higher), result.dbVersion, DB_IMPLEMENTATION_VERSION)); 97 } else { 98 ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l5_t1_error_event)); 99 } 100 } 101 ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged(); 102 reloadTableExpandedList(); 103 reloadStatus(); 104 } 105 } 106 107 108 } 109 110 class InsertRandomResults { 111 List<String> modelInsertions; 112 long deletedModelsAffectedRows; 113 long modelsCountBefore; 114 long modelsCountAfter; 115 boolean operationSuccess; 116 int dbVersion; 117 118 public InsertRandomResults(List<String> modelInsertions, long deletedModelsAffectedRows, 119 long modelsCountBefore, long modelsCountAfter, boolean opSuccess, 120 int dbVersion) { 121 this.modelInsertions = modelInsertions; 122 this.deletedModelsAffectedRows = deletedModelsAffectedRows; 123 this.modelsCountBefore = modelsCountBefore; 124 this.modelsCountAfter = modelsCountAfter; 125 this.operationSuccess = opSuccess; 126 this.dbVersion = dbVersion; 127 } 128 } 129