Pass parameter for #DatabaseView in Room Database Android - android

I m having a databaseView code like this.
#DatabaseView("SELECT * FROM Product")
data class ProductDatabaseView(
var productCode: String? = "",
var productName: String? = "",
var longDescription: String? = "",
var productUom: String? = "",
var customerCode: String? = "",
var price: String? = ""
)
And I wanna pass some value as we do in our DAO like this.
#DatabaseView("SELECT * FROM Product WHERE priceListCode = :priceListCode")
data class ProductDatabaseView(
var productCode: String? = "",
var productName: String? = "",
var longDescription: String? = "",
var productUom: String? = "",
var customerCode: String? = "",
var price: String? = ""
)
Is it able to pass value like this or is there any other option available with the help of View.

To my knowledge, no you can't pass argument to #DatabaseView. They work the same way as in sqlite which doesn't allow parameters in views.

Related

Firebase RealtimeDatabase retrieve snapshot object exception

This is my model class
#Parcel
data class ClientModel(
var name: String? = "",
var phone: String? = "",
var princpalAddresse: String? = "",
var homeAddresse: String? = "",
var travailleAddresse: String? = "",
var email: String? = "",
var userToken: String? = "",
var principalAddresseCoords: Pair<Double, Double>? = null,
var homeAddresseCoords: Pair<Double, Double>?= null,
var workAddresseCoords: Pair<Double, Double>? = null,
)
My proGuard file keep the class :
-keep class com.olivier.oplivre.models.ClientModel
But! when I try to get the snapshot with a singleValueEventListener I got exception because of the Pair<Double,Double> variables
val utilisationInfo = snapshot.getValue(ClientModel::class.java) //todo CRASH
Exception :
com.google.firebase.database.DatabaseException: Class kotlin.Pair does not define a no-argument constructor. If you are using ProGuard, make sure these constructors are not stripped.
Database Structure :
I think firebase Realtime database treat your principalAddresseCoords as a list of long so in your ClientModel change the value of principalAddresseCoords to emptyList() and the type List
As #Sami Shorman said , firebase took my Pair instance and transform it but not as list, as Hashmap<,> ! so I changed my class model like that :
var principalAddresseCoords: HashMap<String,Double>? = null,
var homeAddresseCoords: HashMap<String,Double >? = null,
var workAddresseCoords: HashMap<String,Double >? = null,
To put the data as Hashmap I just had to do :
clientModel.workAddresseCoords = HashMap<String,Double>().apply {
put("lat",lat)
put("long",long)
}

SQLite Select Query returning null

Following SQLite query (with room database library) returning null result. Which is incorrect, as you can see in the attached image.
#Query("SELECT * FROM REPOSITORY_DATABASE_TABLE WHERE item_category LIKE :key")
fun getItemByCategory(key: String) : LiveData<List<Item>>?
#Query("SELECT * FROM REPOSITORY_DATABASE_TABLE WHERE item_storage_type = :key ORDER BY item_name")
fun getItemByCategories(key: String) : LiveData<List<Item>>?
where other queries as follow returning correct result in running application as well as in Android Debug Database
#Query("SELECT * FROM REPOSITORY_DATABASE_TABLE ORDER BY item_name")
fun getAllItems() : LiveData<List<Item>>
Item Data structure:
#Entity(tableName = ApplicationConstants.REPOSITORY_DATABASE_TABLE_NAME)
data class Item(
#PrimaryKey(autoGenerate = false) #SerializedName("item_id")
var itemID: Long = 0L,
#ColumnInfo(name = "item_guid") #SerializedName("item_guid")
var itemGUID: String = "0",
#ColumnInfo(name = "item_name") #SerializedName("item_name")
var itemName: String = "Mango",
#ColumnInfo(name = "item_category") #SerializedName("item_category")
var itemCategory: String = "Fruit",
#ColumnInfo(name = "item_weight") #SerializedName("item_weight")
var itemWeight: Int = 0,
#ColumnInfo(name = "item_count") #SerializedName("item_count")
var itemCount: Int = 1,
#ColumnInfo(name = "item_image") #SerializedName("item_image")
var itemImage: String = "https://stackoverflow.com/questions/62131564/a-failure-occurred-while-
executing-org-jetbrains-kotlin-gradle-internal-kaptexec",
#ColumnInfo(name = "item_notes") #SerializedName("item_notes")
var itemNotes: String = "Sweet Yellow Mango",
#ColumnInfo(name = "item_display_quantity") #SerializedName("item_display_quantity")
var itemDisplayQuantity: String = "0",
#ColumnInfo(name = "item_storage_type") #SerializedName("item_storage_type")
var itemStorageType: String = "0",
#ColumnInfo(name = "item_creation_date") #SerializedName("item_creation_date")
var itemCreationDate: String = "0",
#ColumnInfo(name = "item_is_checked") #SerializedName("item_is_checked")
var itemIsChecked: String = "0",
#ColumnInfo(name = "item_local_status") #SerializedName("item_local_status")
var itemLocalStatus: String = "0",
#ColumnInfo(name = "item_last_added") #SerializedName("item_last_added")
var itemLastAdded: String = "0",
#ColumnInfo(name = "item_notification_status") #SerializedName("item_notification_status")
var itemNotificationStatus: String = "0",
#ColumnInfo(name = "item_priority") #SerializedName("item_priority")
var itemPriority: String = "0",
#ColumnInfo(name = "item_notification_days") #SerializedName("item_notification_days")
var itemNotificationDays: Int = 1,
#ColumnInfo(name = "item_expiry") #SerializedName("item_expiry")
var itemExpiry: String = "0",
#ColumnInfo(name = "item_synonyms") #SerializedName("item_synonyms")
#TypeConverters(Converters::class)
var itemSynonyms: List<String> = listOf("0","0")
)
Also while debugging the database with Android Debug Database I am getting correct response as shown in following image
Android Debug Database Screenshot showing correct response
Try removing the null safety operator from the return type of the query like this:
fun getItemByCategory(key: String) : LiveData<List<Item>>
And you don't have to use #SerializedName() if the SerializedName name is going to be the same as the variable itself.
And also it is very recommended if you use #PrimaryKey(autoGenerate = True) instead of false. Otherwise, you have to manually update the PrimaryKey every time you modify your table.

Add Map to JSON Object for Saving to Firestore

Can't see how to do this and getting rather confused!
I am saving 'site' objects to firestore, but I want to add a list of users associated to each site.
I have added a Map of users to my JSON object as below:
#IgnoreExtraProperties
data class SiteObject(
var siteReference: String,
var siteAddress: String,
var sitePhoneNumber: String,
var siteEmail: String,
var invoiceAddress: String,
var invoicePhoneNumber: String,
var invoiceEmail: String,
var website: String,
var companyNumber: String,
var vatNumber: String,
var recentProjectsText: String,
//not set up yet:
var sitePriority: Boolean,
var siteRating: Int,
var plusCode: String,
var users: Map<String, Boolean>?, // This is the map I have added
#ServerTimestamp
var dateCreatedTimestamp: Date?,
#ServerTimestamp
var dateEditedTimestamp: Date?,
#Exclude
var siteID: String?
) : Serializable {
private constructor() : this(
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
false,
1,
"",
null,
null,
null,
null
)
override fun toString(): String {
return "$siteReference"
}
}
And in my respository I am trying to add the current user to this list of users as below:
// save sites to firebase
fun saveSite(site: SiteObject) {
site.users?.plus(Pair(firebaseUser?.uid.toString(), true)) // This is where I expected the user Id to be added to Map of users..
val documentReference = firestore.collection("sites").document().set(site)
.addOnCompleteListener {
if(it.isSuccessful){
Log.d(TAG, "${site.toString()} saved")
lastOperationText.value = "New site, ${site.siteReference}, saved!"
} else {
Log.d(TAG, "${site.toString()} saved")
lastOperationText.value = "Save new site failed"
}
}
}
However, I still seeing null for users in the Firestore console.
Your code never gives an initial value to users. It starts off null. Since it doesn't get assigned a value, this code will not make a change to it, because it's first checking to see if users is null using the ?. operator:
site.users?.plus(Pair(firebaseUser?.uid.toString(), true))
You will need to assign it an initial value before trying to modify it. It should probably never be null and just start empty.
var users = HashMap<String, Boolean>()
For completeness, below is my updated data class. This initialises the values when it is created and also includes #Exclude #set:Exclude #get:Exclude on siteID to prevent this being saved to Firestore (used to store generated id when read from Firestore):
#IgnoreExtraProperties
data class SiteObject(
var siteReference: String = "",
var siteAddress: String = "",
var sitePhoneNumber: String = "",
var siteEmail: String = "",
var invoiceAddress: String = "",
var invoicePhoneNumber: String = "",
var invoiceEmail: String = "",
var website: String = "",
var companyNumber: String = "",
var vatNumber: String = "",
var recentProjectsText: String = "",
var sitePriority: Boolean = false,
var siteRating: Int = 1,
var plusCode: String = "",
var users: HashMap<String, Boolean> = hashMapOf(),
#ServerTimestamp
var dateCreatedTimestamp: Date? = null,
#ServerTimestamp
var dateEditedTimestamp: Date? = null,
#Exclude #set:Exclude #get:Exclude
var siteID: String = ""
) : Serializable {
override fun toString(): String {
return "$siteReference, $siteAddress, $siteRating, $siteID"
}
fun siteDetailsText(): String {
var siteDetailsText = siteAddress
if (sitePhoneNumber.isNotEmpty()) siteDetailsText.plus("\n\n$sitePhoneNumber")
if (website.isNotEmpty()) siteDetailsText.plus("\n\n$website")
return siteDetailsText
}
fun invoiceDetailsText(): String {
var invoiceDetailsText = invoiceAddress
if (invoicePhoneNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$invoicePhoneNumber")
if (companyNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$companyNumber")
if (vatNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$vatNumber")
return invoiceDetailsText
}
}

Retrieve data from Firebase where is "params" are variable

I have a data class where I retrieve Firebase information. It looks similar to this:
#IgnoreExtraProperties
data class EventData(var eventEmoji: String = "",
var PlanType: PlanType = PlanType.CUSTOM_TYPE_1,
var accel: Boolean = false,
var latitude: String = "0.0",
var longitude: String = "0.0",
var initialDate: String = "",
var finalDate: String = "",
var initialHour: String = "",
var finalHour: String = "",
var plae: String = "",
var addr: String = "",
var description: String = "",
var adminProfileImageUrl: String = "") : Serializable
The problem that I'm facing now, is that exist a new data information that before was unused.
But this new field can exist or not depending on Business people. That field contains some translations, but... not always are the same or same number of it.
Example how is in Firebase:
The problem is that I don't know how to retrieve all this data in the EventData class.
I tried to add the new attribute as:
var localizable: Map<Any,Any>? = hashMapOf()
var localizable: Map<String,Any>? = hashMapOf()
var localizable: Map<String,String>? = hashMapOf()
var localizable: Map<String,SpecificClass>? = hashMapOf()
But... doesn't work.
Is possible to achieve?

AndroidX room database

Iam using room database in kotlin via androidX library. When i download feed and try to save in database, crash occurs showing error sqlite:NOTNULL constraint failed.Json Feed has objects in some tags and also have null data in some tags.
But i did not add any not null properties in database. In another project iam using room database from arch library in java with same feed it actually works.
I tried like this with some seconday constructor
constructor(0, "", "", "", "", listOf<SubMenuApi>, 0)
and also this...
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
#Entity(tableName = "tableMenu")
data class MenuApi(
#PrimaryKey(autoGenerate = true) var id: Int = 0,
#ColumnInfo(name = "title") #SerializedName("Title") var title: String = "",
#ColumnInfo(name = "TITLE_OF_ACCESS") #SerializedName("TitleofAccess") var titleOfAccess: String = "",
#ColumnInfo(name = "apexFileName") #SerializedName("AspxFileName") var apexFileName: String = "",
#ColumnInfo(name = "sectionId") #SerializedName("SectionId") var sectionId: String = "",
#TypeConverters(MenuConvertors::class) #SerializedName("SubMenu") var subMenuApi: List<SubMenuApi> = listOf<SubMenuApi>(),
#ColumnInfo(name = "subSecCount") #SerializedName("subsec_count") var subSecCount: Int = 0)
my database class
#Database(entities = [(MenuApi::class),], version = 1, exportSchema = false)
#TypeConverters(MenuConvertors::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun dbDao(): DbDao
}
menu convertors
class MenuConvertors {
private val gson = Gson()
#TypeConverter
fun stringToList(data: String?): List<SubMenuApi> {
if (data == null) {
return emptyList()
}
val listType = object : TypeToken<List<SubMenuApi>>() {}.type
return gson.fromJson(data, listType)
}
#TypeConverter
fun listToString(subMenuApiList: List<SubMenuApi>): String {
return gson.toJson(subMenuApiList)
}
}
submenu
data class SubMenuApi(
#SerializedName("Title") var title: String? = "",
#SerializedName("TitleofAccess") var titleOfAccess: String? = "",
#SerializedName("AspxFileName") var apexFileName: String? = "",
#SerializedName("SectionId") var sectionId: String? = "",
#SerializedName("URL") var url: String? = "")
my error is
android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: tableMenu.apexFileName (code 1299)
#################################################################
Error Code : 1299 (SQLITE_CONSTRAINT_NOTNULL)
Caused By : Abort due to constraint violation.
(NOT NULL constraint failed: tableMenu.apexFileName (code 1299))
#################################################################
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:915)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:97)
at com.thanthi.dtnext.dtnextapplication.database.DbDao_Impl.insertMenuData(DbDao_Impl.java:432)
at com.thanthi.dtnext.dtnextapplication.viewmodel.MenuViewModel$loadMenuData$1.onResponse(MenuViewModel.kt:53)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
null tag in apexFileName
is there any mistake in my code or bug in androidX.room
Since you are using kotlin, the variables have to be mutable if they are can be null.
Add a ? after the variable types in your entity and that will fix it. Without ? you are basically guaranteeing that it won't be null.
#PrimaryKey(autoGenerate = true) var id: Int? = 0, #ColumnInfo(name = "title")
#SerializedName("Title") var title: String? = "",
#ColumnInfo(name = "TITLE_OF_ACCESS") #SerializedName("TitleofAccess") var titleOfAccess: String? = "",
#ColumnInfo(name = "apexFileName") #SerializedName("AspxFileName") var apexFileName: String? = "",
#ColumnInfo(name = "sectionId") #SerializedName("SectionId") var sectionId: String? = "",
#TypeConverters(MenuConvertors::class) #SerializedName("SubMenu") var subMenuApi: List<SubMenuApi>? = listOf<SubMenuApi>(),
#ColumnInfo(name = "subSecCount") #SerializedName("subsec_count") var subSecCount: Int? = 0)
After adding null in string initialization code works correctly.. like this
#ColumnInfo(name = "title") #SerializedName("Title") var title: String? = null
when we initialize variable with empty value, room database marks that column in table as NOT NULL, so when we receive data as null, it goes error.
so when we don't know about the value we have to initialize variable as null in kotlin data class
Did you change the database scheme after creation? => uninstall app and rebuild
Also you should set exportSchema = true so you actually see what the generated schema looks like.

Categories

Resources