I'm using Room.
I have this insert method:
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Month month);
My insert method:
for(...){
...
monthDao.insert(new Month(0, monthTitle, monthUrl));
}
Also my model
#Entity(tableName = "news_month_table", indices = #Index(value = {"month_index"}, unique = true))
public class Month {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "month_id")
#Getter #Setter
public long month_id;
#ColumnInfo(name = "month_name")
#Getter #Setter
public String monthName;
#ColumnInfo(name = "month_url")
#Getter #Setter
public String monthURL;
#ColumnInfo(name = "month_index")
#Getter #Setter
public int monthIndex;
My situation:
1) Launch the app and download+insert data (12 rounds of for())
Now base is correct and contains 12 rows with 1-12 id's.
2) I have new data(ex for one row). Launch the app and download+insert data.
Now base contains 13 rows with 1-12 and 24 id.
I dont know what is problem, help me please
You can insert new elements by this code:
MonthDao.insert(new Month(monthDao.getLastMonthId()+1, monthTitle, monthUrl, mIndex));
...
#Query("SELECT * FROM news_month_table ORDER BY month_id DESC LIMIT 1;")
int getLastMonthId();
Just the way to solve the problem.
I think the problem regards the unique index on monthIndex attribute. Please check how you set the value of this attribute. Check on your database the value of associated column.
Related
I am getting a weird problem.
with SQL lite query in android 11 devices only.
#Query("SELECT *, SUM(case when isReadMessage = 0 then 1 else 0 end) as countMessage from chat_message_history\n" +
" where messageUser is not null GROUP BY messageUser ORDER by messageDate desc")
LiveData<List<MessagesData>> getAllLiveUniqueUsers();
The DAO class
#Entity(tableName = "chat_message_history", indices = {
#Index(value = "mesId")})
public class MessagesData {
#PrimaryKey(autoGenerate = true)
private int mesId;
private String message;
#TypeConverters(DateConverter.class)
private Date messageDate;
private boolean isReadMessage;
private int countMessage;
private String messageUser;
...}
Date Converter class
public class DateConverter {
#TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
#TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
The output should be order by date which is working in android 6 - android 10. In android 11 its not working.
Please help me to solve this problem.
Maybe your query worked coincidentally in previous versions, but actually it is wrong.
It is an aggregation query that counts the number of unread messages of each user of the table chat_message_history.
The flaw in your query is that you want to sort by the date of the message, but which date?
For each user exist many messages.
Which of these dates do you want to be used in the final sorting?
Maybe you want the first or maybe the last.
In this case, SQLite will chose arbitrarily a date (usually it picks the first but this is not guaranteed).
Use an aggregation function like MIN() or MAX() in the ORDER BY clause and also simplify the CASE expression:
SELECT *, SUM(isReadMessage = 0) AS countMessage
FROM chat_message_history
WHERE messageUser IS NOT NULL
GROUP BY messageUser
ORDER by MAX(messageDate) DESC;
Everything I mentioned above about SQLite picking arbitrary values for messageDate also apply the values of the columns returned by SELECT *.
It would be better if you return only aggregated columns like:
SELECT messageUser,
MAX(messageDate) last_date,
SUM(isReadMessage = 0) AS countMessage
FROM chat_message_history
WHERE messageUser IS NOT NULL
GROUP BY messageUser
ORDER by last_date DESC;
Find average of value in every hour using timeMills
for eaxample i have 20 value in 1h it add and give me the average of every hour average value using timeMills (use timeMills donot use String time).
I am using this query but found 0 values
List<DevicesValuesDB> getAverage();
#Query("SELECT DATE(timeMills / 1000, 'unixepoch') AS timeMills,\n" +
" AVG(value) AS avg\n" +
"FROM devicesvaluesdb\n" +
"GROUP BY timeMills")
List<DevicesValuesDB> gettime();
Model
#Entity
public class DevicesValuesDB {
#PrimaryKey(autoGenerate = true)
public Integer id;
#ColumnInfo(name = "value")
private Double value;
#ColumnInfo(name = "time")
private String time;
#ColumnInfo(name = "timeMills")
private long timeMills;
}
Actually this error says:
Your query returns timeMills,avg and you are storing the result in List<DevicesValuesDB> . With timeMills,avg Room can't create DevicesValuesDB object. So Room expects [id,takenTime,isSync,height,weight,bmi] this fields to create a DevicesValuesDB object.
I think you have imported wrong class for List<DevicesValuesDB> or you didn't post full Class
My database contains a list of these "Movement" class:
#PrimaryKey (autoGenerate = true)
private int NumeroDeOperacion;
private int FechaYear;
private int FechaMonth;
private int FechaDay;
private String TipoOperacion;
private String Category;
private String Notas;
private float Quantity;
In one of my queries I'd like to retrieve only Category and Quantity so I created another POJO object like this:
public class Category {
#ColumnInfo(name = "Category")
public String name;
#ColumnInfo(name = "Quantity")
public float quantity;
public Category(){}
}
What I'm triying to get is all the different Category in a specific year and the SUM of all Quantity.
So, let's say I have something like this:
Category Quantity
A 5
B 10
C 5
A 15
B 20
I'd like to get:
Category Quantity
A 20
B 30
C 5
I tried with this query but it is only getting the last entry of each Category:
#Query("SELECT DISTINCT Category, Quantity FROM OperacionesTable WHERE FechaYear = :year GROUP BY CategoryORDER BY Quantity DESC")
LiveData<List<Category>> getGastosCategoryTotalsInYear(int year);
Any help would be much appreciated.
Thanks in advance
To sum the quantities, you have to use SUM.
Also, there is no need for DISTINCT, since GROUP BY already takes care of that. My guess is that you added distinct, because there was an error. The error was there, because Quantity was neither in the group by columns, nor used in an aggregate function. This is typically an error (except in MySQL, which will just give you a random result).
Anyway, this should do the trick:
SELECT
Category,
SUM(Quantity) as TotalQuantity -- Column alias, to give the column a proper name
FROM
OperacionesTable
WHERE
FechaYear = :year
GROUP BY
Category
ORDER BY SUM(Quantity) DESC
I have a table that looks like following
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product
{
#PrimaryKey
#ColumnInfo(name = "ID")
#JsonProperty("ID")
public int id;
#ColumnInfo(name = "Name")
#JsonProperty("Name")
public String name;
#ColumnInfo(name = "Documents")
#JsonProperty("Documents")
#TypeConverters(DocumentConverter.class)
public List<Document> documents;
}
//...
#TypeConverters(DocumentConverter.class)
#JsonIgnoreProperties( ignoreUnknown = true )
#JsonTypeName("Documents")
public class Document
{
#JsonProperty("Name")
public String name;
#JsonProperty("URL")
public String url;
}
I am able to retrieve a product based on its name by doing something like this
#Query("SELECT * FROM Product WHERE Name = :name")
List<Product> getProducts(String name);
And I would then be able to access the list of documents from each Product object. However I would also like to only deal with Products that has certain documents. I could get all Products via a query like above, then manually filter for the documents that I want, but it becomes quite a pain when I'm only looking for very specific documents.
Is it possible to also query based on Document variables without it being a separate table?
Something like...
#Query("SELECT * FROM Product WHERE Name = :name AND Document.name = :documentName")
List<Product> getProducts(String name, String documentName);
Thanks.
You could use LIKE sql statement to search inside your json column with converted documents list. Example:
Assume that we have document converted like this for storing in db:
{
name: "Title",
url: "Your_url"
}
So your query for product with such document in list should be like this:
SELECT * FROM Product WHERE Name = :name AND Documents LIKE :documentLikeExpr
Where
String documentLikeExpr = "%name: \"Title\"%";
% in expression mean zero, one or multiple characters.
So the only thing we are doing here - is searching for part of string inside column using SQL language features.
You cannot query a Document class variables as it is not stored as a separate table. #TypeConverter annotation converts your Document list to some predefined data types such as String. Basically it stores list of Document as a string Gson in a column of Product table, So we cannot access the field name of Document class in SQL query like Document.name.
Read the Option #2 given by #CommonsWare here
So, to access it you have to create a separate table for Document.
I'm trying to get id column from my database, ad it to ArrayList and to each id add "\t0",
My database is created using Room, i have a lot of column which one of them is
#PrimaryKey(autoGenerate = true)
private int id;
I am operating using ItemDAO and i have there function
#Query("SELECT * FROM item")
List<Item> getItems();
Which writes to ArrayList<Items> all of contents
I was thinking of running it trough the loop getting id and adding to ArrayList<String> but this doesn't seems to be eficient.
Your DAO:
#Query("SELECT Id FROM item")
List<Integer> getAllIds();
Your model:
#ColumnInfo(name = "Id")
#PrimaryKey(autoGenerate = true)
private int id;
In you query SELECT * FROM item * means select All, put there your column name and you will get list of objects from that column
Example: Select all items in id column SELECT id FROM item
I tried to modify and test #Valgaal 's solution. It turns out that Room can also return other type of values, more than just id (or integer).
For example, you can write an item class like this:
#Entity(tableName = Item.TABLE_NAME)
public class Item {
public static final String TABLE_NAME = "ItemsTable";
public static final String COL_DESC = "Description";
#PrimaryKey(autoGenerate = true)
private int id;
#ColumnInfo(name = COL_DESC)
private String description;
// getter & setter...
}
And then, you can write Dao like this:
#Dao
public interface ItemDao {
#Query("SELECT * FROM " + Item.TABLE_NAME)
List<Item> getItems();
#Query("SELECT " + Item.COL_DESC + " FROM " + Item.TABLE_NAME)
List<String> getItemDescriptions();
}
And it's functional as it should be.
I guess all of the other data types that Room can save (including custom types?) can be queried (and returned lists of specific column data) by the same logic above. Hope this would help someone in the future!
For returning multiple columns, create a pojo class that can be set as a return type for your DAO function
Note the select query should contain the Pojo class variable name (can be done via AS keyword)
Detailed answer here
https://stackoverflow.com/a/50802209/1029110
I landed on this question for my issue...but didnt find answer. So this may help others.