Constraints and indexes declarations
KittyORM supports indexes and constraints declaration by using annotations. Right now KittyORM offers you functionality to define seven supported by SQLite constraints without any need to define them in raw SQL code. Also in such way you can define table indexes. KittyORM is capable to define database schema with nearly all features that are supported by SQLite (SQL As Understood By SQLite) with usage only of annotations. In demo you can play with form for creating and inserting entity that declares all constraints and index.
Table of contents
NOT NULL
constraint declarationDEFAULT
constraint declarationUNIQUE
constraint declarationCHECK
constraint declarationCOLLATE
constraint declarationPRIMARY KEY
constraint declarationFOREIGN KEY
constraint declaration- Indexes declaration
NOT NULL
constraint declaration
To declare NOT NULL
constraint just annotate corresponding model field with @NOT_NULL
annotation. Example:
1@KITTY_COLUMN(columnOrder = 0)
2@PRIMARY_KEY
3@NOT_NULL // NOT NULL constraint declaration
4public Long id;
DEFAULT
constraint declaration
To declare DEFAULT
constraint just annotate corresponding model field with @DEFAULT
annotation. Example:
1@KITTY_COLUMN(columnOrder = 3)
2@DEFAULT(signedInteger = 28) // You can choose for options for default declaration, if nothing set than 0 value would be used
3@NOT_NULL
4public Integer defaultNumber;
@DEFAULT
annotation then default value for annotated field would be 0 (int, zero). KittyORM provide you some options on declaring default constraints, for example, you can set as a default value for field predefined LiteralValues
enum element, signed integer, literal value or expression. Example of declaring DEFAULT
constraint from predefined literals:
1@KITTY_COLUMN(columnOrder = 4)
2@DEFAULT(
3 predefinedLiteralValue = LiteralValues.CURRENT_DATE
4)
5@NOT_NULL
6public String creationDate;
DEFAULT
constraint before inserting model you have to invoke on this model KittyModel.setFieldExclusion("modelFieldName")
method. Example:
1IndexesAndConstraintsModel model = new IndexesAndConstraintsModel();
2model.animal = someAnimal;
3...
4model.setFieldExclusion("creationDate"); // Forces KittyORM to exclude this field at insertion so DEFAULT constraint would be triggered
5...
6KittyMapper mapper = getDatabase().getMapper(IndexesAndConstraintsModel.class);
7mapper.save(model);
8mapper.close();
UNIQUE
constraint declaration
You can declare UNIQUE
constraint in two ways:
To declare
UNIQUE
constraint only on one column than just annotate model corresponding field with@UNIQUE
annotation. Example:In order to set conflict clause just set1@KITTY_COLUMN(columnOrder = 1) 2@NOT_NULL 3@UNIQUE 4public Long rndId;
@UNIQUE.onConflict
field with any suitable value fromConflictClauses
enum.To declare
UNIQUE
constraint on more than one column annotate model with@UNIQUE_T
annotation. Example:In order to set conflict clause just set1@KITTY_TABLE(tableName = "cai") 2@FOREIGN_KEY_T( 3 name = "CAI_FK", 4 columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME}, 5 reference = @FOREIGN_KEY_REFERENCE( 6 foreignTableName = "random", 7 foreignTableColumns = {"id"}, 8 onUpdate = OnUpdateDeleteActions.CASCADE, 9 onDelete = OnUpdateDeleteActions.CASCADE 10 ) 11) 12@INDEX(indexColumns = {"creation_date"}) 13@UNIQUE_T(columns = {"rnd_id, animal"}) // Declaring unique constraint on more than two columns 14public class IndexesAndConstraintsModel extends KittyModel { 15 ... 16}
@UNIQUE_T.onConflict
field with any suitable value fromConflictClauses
enum.
In order to setUNIQUE
constraint name set@UNIQUE_T.name
otherwise it would be generated automatically.
If you need more than oneUNIQUE
constraint declaration defined with usage of@UNIQUE_T
annotation, annotate model withUNIQUE_T_ARRAY
.
CHECK
constraint declaration
To declare CHECK
constraint just annotate corresponding model field with @CHECK
annotation and specify check expression. Example:
1@KITTY_COLUMN(columnOrder = 2)
2@CHECK(checkExpression = "animal IN (\"CAT\", \"TIGER\", \"LION\")") // only cats allowed to this party
3public Animals animal;
COLLATE
constraint declaration
To declare COLLATE
constraint just annotate corresponding model field with @COLLATE
annotation and specify built-in collation. Example:
1@KITTY_COLUMN(columnOrder = 2)
2@COLLATE(collation = BuiltInCollations.NOCASE) // Collation example
3@CHECK(checkExpression = "animal IN (\"CAT\", \"TIGER\", \"LION\")")
4public Animals animal;
PRIMARY KEY
constraint declaration
You can declare PRIMARY KEY
constraint in three ways:
To define
INTEGER PRIMARY KEY
just set@KITTY_COLUMN.isIPK
field value totrue
of corresponding model field. Example:1@KITTY_COLUMN( 2 columnOrder = 0, 3 isIPK = true 4) 5public Long id;
Second way to define
PRIMARY KEY
is to annotate corresponding model field with@PRIMARY_KEY
annotation. Example:In order to set order just set1@KITTY_COLUMN(columnOrder = 0) 2@PRIMARY_KEY 3@NOT_NULL 4public Long id;
PRIMARY_KEY.orderAscDesc
field with any suitable value fromAscDesc
enum.
In order to setAUTOIMCREMENT
flag set@PRIMARY_KEY.autoincrement
field to true (default false).
In order to set conflict clause just set@PRIMARY_KEY.onConflict
field with any suitable value fromConflictClauses
enum.Third way to define
PRIMARY KEY
is to annotate model implementation with@PRIMARY_KEY_T
annotation and specify@PRIMARY_KEY_T.columns
array. Example:In order to set1@KITTY_TABLE(tableName = "cpk_test") 2@PRIMARY_KEY_T( 3 columns = {"user_name", "email"} 4) 5public class CPKModel extends KittyModel { 6 7 @KITTY_COLUMN(columnOrder = 0) 8 public String userName; 9 10 @KITTY_COLUMN(columnOrder = 1) 11 @UNIQUE 12 public String email; 13 14 ... 15}
PRIMARY KEY
constraint name set@PRIMARY_KEY_T.name
otherwise it would be generated automatically.
In order to set conflict clause just set@PRIMARY_KEY_T.onConflict
field with any suitable value fromConflictClauses
enum.
FOREIGN KEY
constraint declaration
You can declare FOREIGN KEY
constraint in two ways:
If you have only one column at table that refer to another table column you can just annotate corresponding model field with
@FOREIGN_KEY
annotation and specify@FOREIGN_KEY.reference
with@FOREIGN_KEY_REFERENCE
. Example:1@KITTY_COLUMN(columnOrder = 1) 2@NOT_NULL 3@UNIQUE 4@FOREIGN_KEY( 5 reference = @FOREIGN_KEY_REFERENCE( 6 foreignTableName = "random", 7 foreignTableColumns = {"id"}, 8 onUpdate = OnUpdateDeleteActions.CASCADE, 9 onDelete = OnUpdateDeleteActions.CASCADE 10 ) 11) 12public Long rndId;
If you have more than one reference column at
FOREIGN KEY
declaration, annotate model with@FOREIGN_KEY_T
annotation and specify@FOREIGN_KEY_T.reference
with@FOREIGN_KEY_REFERENCE
and@FOREIGN_KEY_T.columns
with string array of reference columns. Example:In order to set1@KITTY_TABLE(tableName = "cai") 2@FOREIGN_KEY_T( 3 name = "CAI_FK", 4 columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME}, 5 reference = @FOREIGN_KEY_REFERENCE( 6 foreignTableName = "random", 7 foreignTableColumns = {"id"}, 8 onUpdate = OnUpdateDeleteActions.CASCADE, 9 onDelete = OnUpdateDeleteActions.CASCADE 10 ) 11) 12@INDEX(indexColumns = {"creation_date"}) 13public class IndexesAndConstraintsModel extends KittyModel { 14 ... 15 16 @KITTY_COLUMN(columnOrder = 1) 17 @NOT_NULL 18 @UNIQUE 19 public Long rndId; 20 21 ... 22}
FOREIGN KEY
constraint name set@FOREIGN_KEY_T.name
otherwise it would be generated automatically.
If you need more than one FK that can be declared only with @FOREIGN_KEY_T
you can annotate model implementation @FOREIGN_KEY_T_ARRAY
and specify at @FOREIGN_KEY_T_ARRAY.foreignKeys
all foreign keys you need.
At @FOREIGN_KEY_REFERENCE
annotation you have to specify reference table and columns by setting @FOREIGN_KEY_REFERENCE.foreignTableName
and @FOREIGN_KEY_REFERENCE.foreignTableColumns
. Optionally you can specify ON UPDATE
and ON DELETE
actions by setting @FOREIGN_KEY_REFERENCE.onUpdate
and @FOREIGN_KEY_REFERENCE.onDelete
with enum element from OnUpdateDeleteActions
. Also, you can specify defferable option by setting @FOREIGN_KEY_REFERENCE.deferrableOption
with some value DeferrableOptions
enumeration.
Do not forget to turn on foreign keys supports by setting @KITTY_DATABASE.isPragmaOn
to true at your KittyORM database implementation if you want to use them!
Indexes declaration
In KittyORM indexes declarations stored at same POJO classes that are used for schema generation. To declare an index just annotate model implementation with columns that would be indexed with @INDEX
annotation and set @INDEX.indexColumns
with array of those indexed columns or in case when there is only one indexed column for one index declaration just annotate corresponding nodel implementation field with @ONE_COLUMN_INDEX
. Example:
Index declaration with
@INDEX
annotation:1@KITTY_TABLE(tableName = "cai") 2@FOREIGN_KEY_T( 3 name = "CAI_FK", 4 columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME}, 5 reference = @FOREIGN_KEY_REFERENCE( 6 foreignTableName = "random", 7 foreignTableColumns = {"id"}, 8 onUpdate = OnUpdateDeleteActions.CASCADE, 9 onDelete = OnUpdateDeleteActions.CASCADE 10 ) 11) 12@INDEX(indexColumns = {"creation_date"}) // index declaration 13public class IndexesAndConstraintsModel extends KittyModel { 14 ... 15 16 @KITTY_COLUMN(columnOrder = 4) 17 @DEFAULT( 18 predefinedLiteralValue = LiteralValues.CURRENT_DATE 19 ) 20 @NOT_NULL 21 public String creationDate; // indexed column 22 23 ... 24}
Index declaration with
@ONE_COLUMN_INDEX
annotation:1@KITTY_TABLE(tableName = "cai") 2... 3public class IndexesAndConstraintsModel extends KittyModel { 4 ... 5 6 @KITTY_COLUMN(columnOrder = 5) 7 @DEFAULT( 8 predefinedLiteralValue = LiteralValues.CURRENT_TIMESTAMP 9 ) 10 // One column indexe declaration example 11 @ONE_COLUMN_INDEX(unique = true, indexName = "IAC_unique_index_creation_timestamp") 12 @NOT_NULL 13 public Timestamp creationTmstmp; 14 15 ... 16}
For both @INDEX
and @ONE_COLUMN_INDEX
index declaration you can specify index uniqueness (@INDEX.unique
and @ONE_COLUMN_INDEX.unique
fields), IF NOT EXISTS
flag (@INDEX.ifNotExists
and @ONE_COLUMN_INDEX.ifNotExists
fields), where expression (@INDEX.whereExpression
and @ONE_COLUMN_INDEX.whereExpression
fields) and index name (@INDEX.indexName
and @ONE_COLUMN_INDEX.indexName
fields).
If you need more than one index declaration with more than one indexed columns than annotate model implementation with @INDEX_ARRAY
annotation and define your indexes there.