Android Room: auto Increment field - android

Is there any way to set a field auto increment with android Room?
There is a table which contains 3 fields: id, name, order. And I want the field order to be an auto increment field.
#PrimaryKey(autoGenerate = true)
private long id;
private String name;
private int order;
Set field as primary key can achieve this, but there is already one id.
I can handle the order by myself, maybe set the field order as unique is much safer. But I prefer letting the db do it automatically. How can I do that?

Currently, Android doesn't support auto increment. Even for primary key, its not auto-increment, its auto-generate. It won't be serial numbers. It will generate a random hash numbers.
Auto generate is supported only for primary key but not for any normal column

#PrimaryKey(autoGenerate = true)
Annotate your Entity class with the code above.

Related

Migrating auto generate primary key

How can I migrate a primary key field, which was not set to Auto generate before?
From
#PrimaryKey
private int id;
To
#PrimaryKey(autoGenerate=true)
private int id;
Since Sqlite does not support altering columns, my only guess is to migrate the whole table as is and resetting the constraints.
Do I even have to migrate the database during the development process or can I just rebuild it, since my database will change rapidly, so I don't have to migrate every time?
I suggest you to change your approach: add an unique identifier (UID) as alternative way to identify records.
You can define a UID with annotation Entity on your POJO.
#Entity(indices={#Index(value="uid", unique=true)})
publi class Pojo {
..
public String uid;
..
}
When you insert a record in your database, you can define uid field using:
String uuid = UUID.randomUUID().toString();
You can use the UUID field to identify your records, in absolute way. When you migrate to a version to another, you don't work with the old ids, you can always work with UID.

Incrementing a value in a database

I am using android room to store my records. Each record contains main 2 fields: date presented as String and corresponding number of phone unlocks for that day as integer.
I was wondering what is the best way to increment that number in database each time the user unlocks the phone.
Is there a better way than query for current number of unlocks in database, increment it by 1 and update the field?
Is there some clever way to just increment value without making a query first to know exact value?
Try with a simple update query:
#Query("UPDATE TableName SET FieldToIncrement = FieldToIncrement + 1 WHERE ID = :id")
public abstract void incrementValue(long id);
Just annotate field , that you want increment this annotation
#PrimaryKey(autoGenerate = true) private final int id;
And when user unlock phone , just create a new instance of your #Entity.
For the id in constructor of your #Entity pass 0 , Room automatically generate the next value.

No "NOT NULL" and "UNIQUE" constraint on Room Persistence Library

While playing with the Room Persistence Library I came to know that there is no methodology to set a data class field with NOT NULL and also UNIQUE constraints. whether SQLite supports those constraints. Isn't it a problem to migrate old database where those constraints are used? Can anyone give a suggestion for this issue?
I came to know that there is no methodology to set a data class field with NOT NULL and also UNIQUE constraints
A #NonNull annotation on an #Entity field will cause that field's column to have NOT NULL applied to it.
unique=true on an #Index will enforce a uniqueness constraint (e.g., #Entity(indices={#Index(value="something", unique=true)}). However, you are correct that a plain UNIQUE constraint on a column, other than via an index, is not supported.
Isn't it a problem to migrate old database where those constraints are used?
Room is not designed to support existing database structures, particularly in the now-current alpha state. Over time, I would expect Room to support a higher percentage of SQLite features, though I will be stunned if it ever reaches 100%.
Complementary answer about NOT NULL for those using Kotlin:
please note that marking a type as non optional will automatically make it not null (and an optional type will not do that).
You can check it in the schema generated by room with #Database(exportSchema = true) on your database.
For example I have something like that:
#Entity(tableName = "messages")
data class Message (
#PrimaryKey
val messageId: UUID = UUID.randomUUID(),
val date: Date = Date(),
val receivedDate: Date? = null
)
And in the generated schema I can read:
"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `date` INTEGER NOT NULL, `receivedDate` INTEGER, PRIMARY KEY(`messageId`))"
(Note: the Date type is here an Int and the UUID a string due to converters I use elsewhere)
If you have multiple item that is to be marked unique & based on that you want to insert in db then you can use composite primary key.
For Not null, Room has provided "#NonNull" annotation that is added over the field that cannot be null.
In the below mentioned eg. roll number is unique in each class but 2 different class can have same roll number. So we can use class & rollNumber as composite primary key & insert in db uniquely.
Example:
#Entity(primaryKeys = {"rollNumber", "class"})
class Student {
#NonNull
private int rollNumber;
private String firstName;
private String lastName;
private int class;
}
for a null able field you can use wrapper primitive type java. for example use Integer instance int in your Room Table.
as in wrapper primitive type java this can bee null but primitive type class cant bee null. and in generation of this SQL code for primitive field that use notNull=true but when use Integer in generayion SQL code use notNull=false

How to design primary key for DynamoDB with 3 attributes

I am new to DDB, but from what I understand, The DynamoDBHashKey is the same as the partition key, and the DynamoDBRangeKey is the same as the sort key. However, I have 3 values that I need to make a unique key. This is for a mobile application. The use case is storing records. See below:
#DynamoDBTable(tableName = "foo")
public class Foo {
private String userID; // Set on a per-device basis by AWS Cognito
private String name; // The user's name. There can be many users on a device
private long time; // The time the record is created
}
So my original though was to make userId the partition/hash key and name the sort/range key, but each of those combinations will have multiple records, thus the addition of the time attribute. Is there a solution here that I am missing?
Here you go..
Parttionkey userid-name
rangekey time
Key point here is that partition key is a concatenated key consisting of two identifiers

ORMLite not loading child foreign fields

I'm using ORMLite 4.42 for an Android app. I have an entity which has foreign fields. These fields have foreign fields too. The problem is that when I get an element of the root entity, only the first level of foreign fields are loaded. The others levels are null.
On the database every seems ok. The id is correct. Any help?
Edit with models.
The Equipment model is always null when I query by ID. But if I query the whole table, then it gives me access to everything.
TABLE INCIDENT
#DatabaseField(generatedId=true)
private UUID id;
#DatabaseField(foreign=true, foreignAutoRefresh=true, canBeNull=false)
private UserEntity user;
#DatabaseField(dataType = DataType.DATE, canBeNull=true)
private Date date;
#DatabaseField(foreign=true, foreignAutoRefresh=true, canBeNull=true)
private EquipmentEntity equipment;
TABLE EQUIPMENT
#DatabaseField(generatedId=true)
private UUID id;
#DatabaseField(canBeNull=false, unique=true)
private String serial;
#DatabaseField(foreign=true, foreignAutoRefresh=true, canBeNull=false)
private EquipmentTypeEntity type;
TABLE EQUIPMENT TYPE
#DatabaseField(generatedId=true)
private UUID id;
#DatabaseField(canBeNull=true)
private String type;
#DatabaseField(foreign=true, foreignAutoRefresh=true, canBeNull=false)
private EquipmentModelEntity model;
TABLE EQUIPMENT MODEL
#DatabaseField(generatedId=true)
private UUID id;
#DatabaseField(canBeNull=false)
private String model;
I'm using ORMLite 4.42 for an Android app. I have an entity which has foreign fields. These fields have foreign fields too. The problem is that when i get an element of the root entity, only the first level of foreign fields are loaded. The others levels are null.
Right, this is by design. ORMLite specifically limits the number of times it auto-refreshes a sub-element. This was done to protect against huge object trees swallowing memory and against self referential objects.
To quote the docs for foreignAutoRefresh:
NOTE: To protect against recursion, there are a couple of places were auto-refreshing has been limited. If you are auto-refreshing a class that itself has field with foreignAutoRefresh set to true or if you are auto-refreshing a class with a foreign collection, in both cases the resulting field will be set to null and not auto-refreshed. You can always call refresh on the field directly if you need it.
NOTE: If you have an auto-refreshed field that is an object that also has an auto-refreshed field, you may want to tune the maxForeignAutoRefreshLevel value. See below.
To quote from the docs for maxForeignAutoRefreshLevel:
This can be used to set the maximum number of levels to configure foreign objects. For example, if you have a Question which has an foreign field of the best Answer, and the Answer has an foreign field to the corresponding question, then the configuration back and forth can get large. This is especially a problem with auto-refreshed fields when you lookup the Question it could cause an infinite loop. By default, ORMLite only goes through 2 levels but you can decrease it to 1 (0 is not valid) or increase it. The higher the number the more database transactions happen when you load in your Question.
If you increase the maxForeignAutoRefreshLevel to be more then it will issue the extra queries to refresh the elements.
#DatabaseField(foreign=true, foreignAutoRefresh=true, canBeNull=true,
maxForeignAutoRefreshLevel=3)
private EquipmentEntity equipment;

Categories

Resources