Realm field not found exception - android

I am trying to implement Realm into a project of mine. I keep running into this
java.lang.IllegalArgumentException: Invalid query: field '_id' not found in class 'messages'.
Note: MESSAGE.COLUMN_ID = "_id"
Query
The Logcat prints true for hasField.
Model
The same thing works for other tables fine.

Typed Realm queries use the field name as the argument, and are mapped over internally to the internal schema field name.
Therefore, your query ought to look like this:
MessageDto messageDto = realmInstance.where(MessageDto.class)
.equalTo("mLocalId", query.getMessageId())
.findFirst();

Related

firebase document some fields are showing as null when map and array exist in the document

I am having documents with array and map fields. When I try to get this in the data class some other fields are getting null.
for example - orderQty is getting as null.
At first glance, I can see that the names of the fields in your Orders class are different than the names that exist in the database. In your class, the fields start with an upper-case letter, while in the database start with a lower-case letter. And this is not correct, the names must match. The simplest solution would be to change the names of the fields in the class. So a field called OrderNo should be changed to orderNo. See the lower-case o?
Alternatively, you can use an annotation like this:
#get:PropertyName("orderNo")
#set:PropertyName("orderNo")
var OrderNo: String? = null,

Flutter Drift library inconsistency found while naming table and doing migration

I want my table names to be specific as I am migrating from Native Android Room database to Flutter using Drift library for database.
Room take a table name i.e. class name and creates a table:
e.g. the following will create table 'User' with field names as 'firstName' and lastName' in native Android using Room database support
#Entity
data class User(
#PrimaryKey val id: Int,
val firstName: String?,
val lastName: String?
)
When I try to replicate this in Flutter, I write:
#DataClassName('User') // To avoid drift changing it to 'user'
data class User(
TextColumn get firstName => text().named('firstName')();
TextColumn get lastName => text().named('lastName')();
// The above '.named()' makes sure drift does not change names to 'first_name' & 'last_name'
)
By doing above I am making sure the databases match exactly! (please correct me if I am wrong here)
Now when I try to replicate the migration statements in drift I am writing:
...
if (from < 4) await m.addColumn(Note, Note.path);
if (from < 5) await m.addColumn(Profile, Profile.squarePicture);
...
As you can see that I am writing note as a 'Note' because I have defined my table name as 'Note' and not 'note' same goes with profile! But the code is highlighting the following error:
The argument type 'Type' can't be assigned to the parameter type
'TableInfo<Table, dynamic>'
When I change table names to small alphabets i.e. 'n' and 'p' the error goes away but I do not understand WHY? My table names are explicitly with capital letters in the start.
I do not want to change anything in the database when my users will upgrade their app which was previously made in Native Android using Kotlin and Room database to the Flutter version. I want them to have a seamless experience with no loss of data!
The #DataClassName() annotation is used to change the name of the class which is generated by the drift. This generated class is what the drift will use when querying the database and getting the result.
By default, the generated class name will be the same as the class name except the drift will strip any last 's' character. For example, if your class name is "Users" the drift will generate a class with the name "User" with the 's' at the end stripped.
Coming to your question #DataClassName() has nothing to do with the table name in your database or any migration strategy. If you want to change the table name you can do something like this,
class User extends Table {
///This property will change the table name.
String get tableName => 'User';
...
}
Official Documentation - Dart table Names
Drift also generates a class that has an identical name to our table class. In your case, there will be a class generated $User which extends our table class, and a mixin TableInfo. This class's object is automatically created by the drift in the database generated code.
So drift will generate a variable named user which will be object of class $User. This variable needs to be used inside migration stregeies so that drift can successfully migrate a table.

ormlite dao delete function not taking parameters

Trying to delete all records from table on a already built app. I has ormlite dao and the function seems very simple
allUsers have a collection of objects to be deleted but i get an Exception :-
SQLException
"java.sql.SQLException: Unable to run delete collection stmt: DELETE FROM user WHERE PIN IN ?,?,?,?,?,)
I tried creating a list of ids and using another option "deleteById" same error
Collection<UserModel> allUsers = helper.getUserDao().queryForAll();
helper.getUserDao().delete(allUsers);
I just need the table to be wiped out.
try it
helper.getUserDao().deleteBuilder().where().eq($yourKey, $yourValue).delete()
I tried creating a list of ids and using another option "deleteById" same error
Collection<UserModel> allUsers = helper.getUserDao().queryForAll();
helper.getUserDao().delete(allUsers);
I'm not sure why this didn't work. If you show more of the exception there may be Caused by sections of the exception that provided more details. It could be that the UserModel doesn't have an ID field?
I just need the table to be wiped out.
There are a couple of ways to do this. The most efficient is use TableUtils.clearTable(...):
TableUtils.clearTable(header.getUserDao().getConnectionSource(), UserModel.class);
Deleting all of the elements can also be done with the DeleteBuilder:
helper.getUserDao().deleteBuilder().delete();

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

ORMLite and adding an existing persisted entity to a foreign field collection

I have a Language entity with a ForeignCollection of Country entities:
#ForeignCollectionField(eager = false, foreignFieldName = "language")
public ForeignCollection<Country> countries;
I create a country, say representing France, in my database. Later, I retrieve it by querying for its id and I want to add this to a Language's foreign collection of countries:
Country country = dbHelper.getCountryDao().queryForId(countryId);
if (country != null) {
country.language = language;
ForeignCollection<Country> countries = language.countries;
if (countries == null) {
countries = dbHelper.getLanguageDao().getEmptyForeignCollection("countries");
}
countries.add(country); // Illegal state exception thrown here
language.countries = countries;
dbHelper.getLanguageDao().create(language);
}
However, the marked line countries.add(country) causes an illegal state exception to be thrown:
01-27 13:39:19.112: E/AndroidRuntime(15614): Caused by:
java.sql.SQLException: inserting to database failed: INSERT INTO
countries (identifier ,name ,language_id ) VALUES (?,?,?)
01-27 13:39:19.112: E/AndroidRuntime(15614): at
com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
Why does .add() trigger the recreation of an entity existing in the database and the internal DAO? And what should I be doing instead?
Why does .add() trigger the recreation of an entity existing in the database and the internal DAO?
It does this because that is how it was designed. To quote the javadocs for EagerForeignCollection#add():
Add an element to the collection. This will also add the item to the associated database table.
The country already exists in the table so an exception is thrown. You can associate an existing country with a language by doing something like the following:
country.language = language;
dbHelper.getCountryDao().update(country);
Then if you want to refresh your eager collection in the language you do:
dbHelper.getLanguageDao().refresh(language);
Right now I get an SQL Exception, if I add an already created element to the collection, because of the dao.create() in the add() of the collection realization. But for a quite some time we got a dao.createOrUpdate() method, which is better for this situation because it would do an update or simply nothing if we have an already created entity in collection. Is it possible to change this in the source code?
By the way there is an already done and closed ticket (#31) with changes that should automatically set the parent field value on the collection element. But even in the 4.45 I still have to do this manually. Did I miss something or probably do something wrong?

Categories

Resources