Getting started with KittyORM

Gradle setup

First step is to add KittyORM via Gradle to your app build.gradle:

1dependencies {
2    implementation 'net.akaish.kitty.orm:kitty-orm:$latest_version'
3}

KittyORM configuration and implementation

Create package for storing your POJO models, KittyORM database class, KittyORM helper class (if necessary) and KittyORM extended mappers (if necessary).

First step: extend KittyDatabase class, implement default constructor and annotate it with @KITTY_DATABASE annotation (and, if necessary, with @KITTY_DATABASE_HELPER).

Second step: create your first POJO model by extending KittyModel class, implement default constructor and annotate it with @KITTY_TABLE annotation. Each model field of KittyModel POJO implementation that corresponds database table column also has to be annotated with @KITTY_COLUMN annotation.

Third step (optional): create extended CRUD controller by extending KittyMapper class, implementing default constructor and adding business logic. To make what CRUD controller you want to use with given POJO model you can just use default naming rules (SomeModel.class, Somemodel.class and even Some.class POJO would use SomeMapper.class extended controller if found) or (better choice) annotate model POJO with @EXTENDED_CRUD linked to actual extended CRUD controller class implementation.

Fourth step (optional): create extended database helper by extending KittyDatabaseHelper class and make sure that your KittyDatabase class implementation would return new instance of your extended database helper via KittyDatabase.newDatabaseHelper() method.

In this lesson we create simple database that contains only one table and would interact with it using default CRUD controller. This demo contains many database domains, so database domain was set in @KITTY_DATABASE. Also it is better to set this value if your application uses a lot of libraries so KittyORM would seek POJO and CRUD classes related to KittyORM only in specified location(s).

Working with entities

alt text alt text alt text

This example shows basic KittyORM usage when you just want to store some information in your database. Just very simple database to go. Database would be created at first call of getMapper(Class<M> recordClass) method of SimpleDatabase.class instance, it would be named simple_database and would contain only one table called simple_example. This database would have version 1 by default.

SimpleDatabase.class:

 1package net.akaish.kittyormdemo.sqlite.introductiondb;
 2
 3import android.content.Context;
 4
 5import net.akaish.kitty.orm.KittyDatabase;
 6import net.akaish.kitty.orm.annotations.KITTY_DATABASE;
 7
 8@KITTY_DATABASE(
 9        domainPackageNames = {"net.akaish.kittyormdemo.sqlite.introductiondb"}
10)
11public class SimpleDatabase extends KittyDatabase {
12
13    public SimpleDatabase(Context ctx) {
14        super(ctx);
15    }
16}

SimpleExampleModel.class:

 1package net.akaish.kittyormdemo.sqlite.introductiondb;
 2
 3import net.akaish.kitty.orm.KittyModel;
 4import net.akaish.kitty.orm.annotations.column.KITTY_COLUMN;
 5import net.akaish.kitty.orm.annotations.table.KITTY_TABLE;
 6
 7@KITTY_TABLE
 8public class SimpleExampleModel extends KittyModel {
 9    public SimpleExampleModel() {
10        super();
11    }
12
13    @KITTY_COLUMN(
14            isIPK = true,
15            columnOrder = 0
16    )
17    public Long id;
18
19    @KITTY_COLUMN(columnOrder = 1)
20    public int randomInteger;
21
22    @KITTY_COLUMN(columnOrder = 2)
23    public String firstName;
24}

By default, all names in KittyORM if they weren’t specified explicitly in annotations would be generated from class names and field names. For database name it would be used KittyUtils.fieldNameToLowerCaseUnderScore(String fieldName) method where fieldName is database implementation class name. For table names would be used KittyUtils.fieldNameToLowerCaseUnderScore(String fieldName) where fieldName is POJO class name without Model\model ending (if ending exists) and for column names would be used KittyUtils.fieldNameToLowerCaseUnderScore(String fieldName).

Click to view KittyUtils.fieldNameToLowerCaseUnderScore(String fieldName)
 1/**
 2 * Converts input string (designed for camel case variable names)
 3 * into lower case underscored string
 4 * @param fieldName
 5 * @return
 6 */
 7public static String fieldNameToLowerCaseUnderScore(String fieldName) {
 8	return fieldName.replaceAll("[^a-zA-Z0-9]","")
 9			.replaceAll("(?=[A-Z])","_")
10			.replaceAll("^_","")
11			.toLowerCase();
12}

Do not use primitives for PrimaryKeys, because uninitialized primitive field returns 0 not NULL via reflection calls and KittyORM wouldn’t know what to do with such POJO.

CRUD Usage

We are ready to go, just get KittyMapper from instance of SimpleDatabase with getMapper(SimpleExampleModel.class) and perform any basic RW operations.

Do not forget to call KittyMapper.close() method on your KittyMapper instance after you did all database operations you wanted.

 1SimpleExampleModel alex = new SimpleExampleModel();
 2
 3alex.randomInteger = 545141;
 4alex.firstName = "Alex";
 5
 6SimpleExampleModel marina = new SimpleExampleModel();
 7
 8marina.randomInteger = 228;
 9marina.firstName = "Marina";
10
11// save model with save method
12mapper.save(alex);
13// or use insert method if you want to get rowid
14long marinaRowid = mapper.insert(marina);
 1// find with row id
 2SimpleExampleModel model1 = mapper.findByRowID(0l);
 3
 4// find with INTEGER PRIMARY KEY
 5SimpleExampleModel model2 = mapper.findByIPK(0l);
 6
 7// find with KittyPrimaryKey
 8KittyPrimaryKeyBuilder pkBuilder = new KittyPrimaryKeyBuilder();
 9pkBuilder.addKeyColumnValue("id", "0");
10SimpleExampleModel model3 = mapper.findByPK(pkBuilder.build());
11
12List<SimpleExampleModel> marinas;
13
14// find with condition
15SQLiteConditionBuilder builder = new SQLiteConditionBuilder();
16builder.addColumn("first_name")
17       .addSQLOperator(SQLiteOperator.EQUAL)
18       .addValue("Marina");
19marinas = mapper.findWhere(builder.build());
20
21// find with condition (you may use shorter syntax)
22SQLiteConditionBuilder builder = new SQLiteConditionBuilder();
23builder.addColumn("first_name")
24       .addSQLOperator("=") // You may use string operators instead SQLiteOperator enum element
25       .addValue("Marina");
26marinas = mapper.findWhere(builder.build());
27
28// find with condition (without query builder)
29marinas = mapper.findWhere("first_name = ?", "Marina");
30
31// find with condition (pass POJO field name as parameter, in #?fieldName form)
32marinas = mapper.findWhere("#?firstName = ?", "Marina");
33
34List<SimpleExampleModel> randModels = new LinkedList<>();
35for(int i = 0; i < 10; i++)
36    randModels.add(RandomSimpleExampleModelUtil.randomSEModel());
37mapper.save(randModels);
1List<SimpleExampleModel> randModels = new LinkedList<>();
2for(int i = 0; i < 10; i++)
3    randModels.add(RandomSimpleExampleModelUtil.randomSEModel());
4mapper.save(randModels);
1// deleting entity
2mapper.delete(alex);
3
4// deleting from database with condition
5mapper.deleteWhere("first_name = ?", "Alex");
 1// updating current model
 2// if model has RowId or IPK or PrimaryKey values set (3 is slowest) just
 3marina.randomInteger = 1337;
 4mapper.update(marina);
 5
 6// or just
 7mapper.save(marina)
 8
 9// another option is updating with query-like method
10SimpleExampleModel update = new SimpleExampleModel();
11update.randomInteger = 121212;
12builder = new SQLiteConditionBuilder();
13builder.addColumn("first_name")
14       .addSQLOperator("=")
15       .addColumn("Marina");
16mapper.update(update, builder.build(), new String[]{"randomInteger"}, CVUtils.INCLUDE_ONLY_SELECTED_FIELDS);
1randModels = new LinkedList<>();
2for(int i = 0; i < 10; i++)
3    randModels.add(RandomSimpleExampleModelUtil.randomSEModel());
4mapper.saveInTransaction(randModels);

Do not forget to call KittyMapper.close() method on your KittyMapper instance after you did all database operations you wanted.