ORMLite when query foreign object, it gives null values to its fields except id - android

I have two model class one is foreign key in another. While persisting data in ormlite, data gets inserted correctly, but when querying data from dao foreign object fields has null values except its id.
Home.class
#DatabaseTable(tableName = "Home")
class Home: Serializable {
#DatabaseField(id = true)
var id: Long? = null
#DatabaseField(columnName = "name")
var name: String? = null
#DatabaseField(columnName = "dateCreated")
var dateCreated: String? = null
#DatabaseField(columnName = "lastUpdated")
var lastUpdated: String? = null
}
Flat.class
#DatabaseTable(tableName = "Flat")
class Flat: Serializable {
#DatabaseField(id = true)
var id: Long? = null
#DatabaseField(canBeNull = false, foreign = true, columnName = "homeId", foreignAutoRefresh = true)
var home: Home? = null
#DatabaseField
var districtCode: String? = null
#DatabaseField
var name: String? = null
#DatabaseField
var dateCreated: String? = null
#DatabaseField
var lastUpdated: String? = null
}
when i fetch Flat row from ormlite db, then i get values of flat model and its foreign object model i.e Home feilds are null except its id

Related

Android Room FOREIGN KEY constraint failed (code 787) when insert new row

I followed this post Android Room FOREIGN KEY constraint failed (code 787). Unfortunately, it not works in my case.
I always get the error when trying to insert a new Note. Of course, there is a Topic existed in Database.
Do you guys have any idea?
Please take a look at my code below.
Topic:
#Entity(tableName = "topic")
data class Topic(#PrimaryKey var id: Long? = null,
#ColumnInfo(name = "name") var name: String,
#ColumnInfo(name = "note_count") var noteCount: Int = 0,
#ColumnInfo(name = "view_count") var viewCount: Long = 0) : Serializable {
#Ignore
var notes: List<Note>? = null
}
Note:
#Entity(tableName = "note",
foreignKeys = arrayOf(ForeignKey(entity = Topic::class,
parentColumns = arrayOf("id"), childColumns = arrayOf("topic_id"), onDelete = ForeignKey.CASCADE)))
#TypeConverters(TimestampConverter::class)
data class Note(#PrimaryKey(autoGenerate = true) var noteId: Long? = null,
#ColumnInfo(name = "topic_id") var topicId: Long? = null,
#ColumnInfo(name = "title") var title: String,
#ColumnInfo(name = "caption") var caption: String? = "",
#ColumnInfo(name = "created_at") var createdAt: Date? = null) : Serializable {
}
NoteDao:
#Dao
interface NoteDao {
#Query("SELECT * from note")
fun getAll(): LiveData<List<Note>>
#Insert(onConflict = REPLACE)
fun insert(note: Note)
#Query("DELETE from note")
fun deleteAll()
#Delete
fun delete(category: Note)
#Query("SELECT * FROM note WHERE title = :title COLLATE NOCASE LIMIT 1")
fun findNoteByTitle(title: String): Note?
#Query("SELECT * FROM note WHERE topic_id = :topicId")
fun findNotesByTopicId(topicId: Long): LiveData<List<Note>>
#Query("SELECT count(*) FROM note WHERE topic_id = :topicId")
fun countNotesByTopicId(topicId: Long): Long
#Update(onConflict = IGNORE)
fun update(category: Note)
}
I found the problem. Because I have been created 2 different Databases: TopicDataBase and NoteDataBase.
So I just need to remove 1 of them.
My bad >"<
(#PrimaryKey var id: Long? = null, looks like a problem. Primary key can't be null

Android Room FOREIGN KEY constraint failed (code 787)

I'm tying to create a database in Android Room with two foreign keys. Every time I try to insert a track into the database the program chrashes and says that the "foreign key costraint failed(code 787)". Maybe someone of you knows why and can help me.
#Entity(foreignKeys = {#ForeignKey(
entity = Kategorie.class,
childColumns = "kategorieFremdschluessel",
parentColumns = "kategorieID",
onUpdate = ForeignKey.CASCADE,
onDelete = ForeignKey.CASCADE
),
#ForeignKey(
entity = Playlist.class,
childColumns = "playlistFremdschluessel",
parentColumns = "uuid",
onUpdate = ForeignKey.CASCADE,
onDelete = ForeignKey.CASCADE
)
})
public class Track {
#PrimaryKey(autoGenerate = true)
private int uid;
private String trackTitel;
private String playlistName;
private String jsonObjectString;
private int kategorieFremdschluessel;
private int playlistFremdschluessel;
#Ignore
public Track(String trackTitel, String playlistName, String jsonObjectString) {
this.trackTitel = trackTitel;
this.playlistName = playlistName;
this.jsonObjectString = jsonObjectString;
}
public Track(String trackTitel, String jsonObjectString) {
this.trackTitel = trackTitel;
this.jsonObjectString = jsonObjectString;
}
//Getter and Setter
#Dao
TrackDao
public interface TrackDao {
#Query("SELECT * FROM Track WHERE playlistName LIKE :playlist")
List<Track> getAllTracks(String playlist);
#Query("SELECT * FROM Track WHERE kategorieFremdschluessel = :kategorieFremdschluessel")
List<Track> loadAllKategorieTracks(int kategorieFremdschluessel);
#Query("SELECT * FROM Track WHERE playlistFremdschluessel = :playlistFremdschluessel")
List<Track> loadAllPlaylistTracks(int playlistFremdschluessel);
#Insert
void insertAll(List<Track> trackList);
#Insert
void insertOne(Track track);
#Update
void updateOne(Track track);
#Delete
void delete(Track track);
}
"Kategorie" and "Playlist" are also tables in the database.
#Entity
public class Playlist{
#PrimaryKey(autoGenerate = true)
private int uuid;
#ColumnInfo(name = "name")
private String name;
Kategorie
#Entity
public class Kategorie {
#PrimaryKey(autoGenerate = true)
private int kategorieID;
#ColumnInfo(name = "name")
private String name;
You need to have rows in tables Kategorie and Playlist with a same foreign key as has Track that you are inserting.
There's another reason why this error occurs which consumed a lot of my time since every possible solution available on the internet seemed futile in my case.
If you use rowId of the parent table as the parentColumn key, the Foreign key constraint CANNOT be used.
As per the SQLite documentation on Foreign Keys:
The parent key is the column or set of columns in the parent table
that the foreign key constraint refers to. This is normally, but not
always, the primary key of the parent table. The parent key must be a
named column or columns in the parent table, not the rowid.

add unique constraint in room database to multiple column

I have one entity in room
#Entity(foreignKeys ={
#ForeignKey(entity = Label.class, parentColumns = "_id", childColumns = "labelId", onDelete = CASCADE),
#ForeignKey(entity = Task.class, parentColumns = "_id", childColumns = "taskId", onDelete = CASCADE)
})
public class LabelOfTask extends Data{
#ColumnInfo(name = "labelId")
private Integer labelId;
#ColumnInfo(name = "taskId")
private Integer taskId;
}
sql syntax of this entity is as below
CREATE TABLE `LabelOfTask` (
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`labelId` INTEGER,
`taskId` INTEGER,
FOREIGN KEY(`labelId`) REFERENCES `Label`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE ,
FOREIGN KEY(`taskId`) REFERENCES `Task`(`_id`) ON UPDATE NO ACTION ON DELETE CASCADE
);
but what change or annotation I need to add in entity class if I want to append below constraint to the auto generated sql schema of the table
unique (labelId, taskId)
Ultimately I want to make combination of labelId and taskId unique in a table(or entity of room) using room library.
A plain UNIQUE constraint on a column, other than via an index, is not supported.
You can enforce this uniqueness property by setting the unique property of an #Index annotation to true. The following code sample (Java) prevents a table from having two rows that contain the same set of values for the firstName and lastName columns:
#Entity(indices = {#Index(value = {"first_name", "last_name"},
unique = true)})
class User {
#PrimaryKey
public int id;
#ColumnInfo(name = "first_name")
public String firstName;
#ColumnInfo(name = "last_name")
public String lastName;
#Ignore
Bitmap picture;
}
The Kotlin equivalent of the annotation is given below:
#Entity(indices = arrayOf(Index(value = ["first_name", "last_name"], unique = true)))
In your code you can do the following changes to have UNIQUE constraints
#Entity(foreignKeys ={
#ForeignKey(entity = Label.class, parentColumns = "_id", childColumns = "labelId", onDelete = CASCADE),
#ForeignKey(entity = Task.class, parentColumns = "_id", childColumns = "taskId", onDelete = CASCADE)},
indices = {#Index(value = {"labelId", "taskId"},
unique = true)}
)
public class LabelOfTask extends Data{
#ColumnInfo(name = "labelId")
private Integer labelId;
#ColumnInfo(name = "taskId")
private Integer taskId;
}
If you wonder to make a single column to be unique, only need to write
#Entity(indices = {#Index(value = "name", unique = true)})

Nullable predicate in android ROOM

I have Dao and Query to load all Item by parentId
#Entity(
indices = #Index("parent_id"),
foreignKeys = #ForeignKey(entity = Parent.class, parentColumns = "id", childColumns = "parent_id")
)
public class Item extends BaseEntity {
#ColumnInfo(name = "parent_id")
private String parentId;
private String name;
...
}
#Dao
public interface ItemDao {
Item #Query("SELECT * FROM Item WHERE parent_id = :parentId")
LiveData<List<Item>> loadByParentId(String parentId);
}
This works while parentId != null. Query with parentId = null return 0 Items. But I want to load all Item where parentId equal null too.
I find this solution:
#Query("SELECT * FROM Item WHERE parent_id = :parentId OR (:parentId IS NULL AND parent_id IS NULL)")
LiveData<List<Item>> loadByParentId(String parentId);
Can there be a better solution?
Can you try using conditional query, something like this:SELECT * FROM product WHERE parent_id = #ParentID OR ISNULL(#ParentID, '') = ''

OrmLite foreign key exists from Json

I've never used OrmLite before but I need to edit an existing project that uses it.
I have two classes : Person and Office.
I'm using gson to parse, with the person an office Id is provided, for example office_id: "4456".
I was hoping it would be possible to link the two together from my Person class so I can easily get a office for a person.
For example:
#SerializedName("id")
#DatabaseField(id = true, columnName = ID)
private int mId;
#SerializedName("full_name")
#DatabaseField(columnName = FULL_NAME)
private String mFullName = null;
#DatabaseField(columnName = POSITION)
private String mPosition = null;
#SerializedName("email")
#DatabaseField(columnName = EMAIL)
private String mEmail = null;
private Office office = null;
#SerializedName("office_id")
private String officeId = null;
So I have the officeId from Json which is stored in the Person table. I would like to automatically load the Office into the Person object whenever it is loaded.
To automatically fetch a referenced object upon querying you can use foreignAutoRefresh = true in your #DatabaseField. You reference the Object and not the id itself. In the table, the id of the referenced row will be stored.
To clarify for your project:
Office must look something like this:
#SerializedName("id")
#DatabaseField(id = true, columnName = ID)
private int mId;
...
And your Person (database-wise) like this:
#DatabaseField(id = true, columnName = ID)
private int mId;
#DatabaseField(columnName = FULL_NAME)
private String mFullName = null;
#DatabaseField(columnName = POSITION)
private String mPosition = null;
#DatabaseField(columnName = EMAIL)
private String mEmail = null;
#DatabaseField(foreign = true, foreignAutoRefresh = true)
private Office office = null;
The Office column in the Person table will hold the id of the Office.
foreignAutoRefresh tells ORMLite to fetch the full Office upon querying the Person
http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/DatabaseField.html#foreignAutoRefresh()
Hope this helps

Resources