#Query Update in Android Room Database doesn't update primary key field - android

I'm writing Android app with Room Database. My database contains GroupVc entity with such code:
#Entity
public class GroupVc {
#ColumnInfo(name = "language")
private String language;
#NonNull
#PrimaryKey
#ColumnInfo(name = "name_group")
private String nameGroup;
public GroupVc(String language, String nameGroup) {
this.language = language;
this.nameGroup = nameGroup;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
#NonNull
public String getNameGroup() {
return nameGroup;
}
#NonNull
public void setNameGroup(String nameGroup) {
this.nameGroup = nameGroup;
}
}
As you can see my entity class contains two columns where nameGroup is my PrimaryKey. In my application I want to let the user to see the full list of groups and change the name of Group DialogFragments by entering new Group's names. To implement such function I've created the next DAO #Query method:
#Dao
public interface GroupVcDao {
#Query("UPDATE groupvc SET name_group= :newName WHERE name_group= :currentName")
void updateNameOfGroup(String currentName, String newName);
}
In this QUERY I want to change name of GroupVc by getting the existing name of GroupVc from RecyclerView (currentName param) and applying new one from DialogFragment (newName param).
My problem is that this QUERY doesn't bring any effect and doesn't update the name. Although I don't get any errors or exceptions. So I need to know: does such QUERY correct? Is it possible to write Update queries where primary key is changeable value and condition at the same time?
Here is the link to my complete project on GitHub
https://github.com/LAHomieJob/VocaNote

I can't be sure, but my guess would be that your query is working, but since you're changing the primary key your database is left with an instance of the old object as well as the new one. Try checking to see if you have an object with both the old name_group and the new name_group. Also if you're looking to allow your users to change the group name, it may make sense to move your primary key to a UUID or some other key that doesn't change.

Related

Confuse on dealing with relations between objects using Android Room

When using the android data-persistent library Android Room ,how can I directly insert the Comment Object into the database including all the field value, and how can I query all the value out as a Comment Object?
As I know, I can not use the Comment Object as a Entity in Room directory, because of the field replyComment is also a Comment Object. And I can not query out a Comment Object even I define a POJO using the #Relations annotation either because of the one-to-one relations and one-to-many relations all included in the Comment Object.
Is there any other way except changing the Comment Model definition, such as using foreign key, making a effect on insert action and query action?
public class Comment {
public String content;
public String id;
public Comment replyComment;
public User user;
public List<ImageMedia> images;
}
public class User{
public String id;
public String name;
}
public class ImageMedia{
public String key;
public String url;
}
Is there any other way except changing the Comment Model definition
No. You would need to create a set of entities that model the database structure, where children have foreign key columns pointing back to their parents:
CommentEntity has a foreign key back to CommentEntity for the reply
CommentEntity has a foreign key back to UserEntity
ImageMediaEntity has a foreign key back to CommentEntity

Practical use of #Ignore in Realm?

I've been trying to add Realm in my Android app. Their docs are pretty well explained & easy to follow. But it fails to explain this one particular area. I'm unable to figure out the practical use for the #Ignore annotation. I know that fields under this annotation are not persisted.
Can someone please share a few use cases. Also I wanted to know the scope of such fields. I mean, if I set an #Ignore field to some value, would that value be available to the other classes in my app for that particular launch session. If yes, then how do we access it? If no (which I guess is the case), then why do we need such a field anyway?
I've searched here and on web but couldn't find the relevant information. If out of my ignorance, I've missed upon some resource, please guide me to it.
Thanks.
Accordingly to the official documentation (see https://realm.io/docs/java/latest/) #Ignore is useful in two cases:
When you use GSON integration and your JSON contains more data than you want to store, but you still would like to parse it, and use right after.
You can't create custom getters and setter in classes extending RealmObject, since they are going to be overridden. But in case you want to have some custom logic anyway, ignored fields can be used as a hack to do that, because Realm doesn't override their getter & setters. Example:
package io.realm.entities;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
public class StringOnly extends RealmObject {
private String name;
#Ignore
private String kingName;
// custom setter
public void setKingName(String kingName) { setName("King " + kingName); }
// custom getter
public String getKingName() { return getName(); }
// setter and getter for 'name'
}
Ignored fields are accessible only from the object they were set in (same as with regular objects in Java).
UPDATE: As the #The-null-Pointer- pointed out in the comments the second point is out of date. Realm now allows having custom getters and setters in Realm models.
Here's a couple of real-world use cases:
1 - Get user's fullname:
public class User extends RealmObject {
private String first;
private String last;
#Ignore
private String fullName;
public String getFullName() {
return getFirst() + " " + getLast();
}
Get JSON representation of object:
public class User extends RealmObject {
private String first;
private String last;
#Ignore
private JSONObject Json;
public JSONObject getJson() {
try {
JSONObject dict = new JSONObject();
dict.put("first", getFirst());
dict.put("last", getLast());
return dict;
} catch (JSONException e) {
// log the exception
}
return null;
}
I've found it useful to define field names for when I am querying. For example
User.java
public class User extends RealmObject {
#Index
public String name;
#Ignore
public static final String NAME = "name";
}
And then later on I can do something like:
realm.where(User.class).equalTo(User.NAME, "John").findFirst();
This way if the schema changes from say name to id I don't have to hunt down every occurrence of "name".
Please see the the official documentation about #Ignore annotation:
The annotation #Ignore implies that a field should not be persisted to disk. Ignored fields are useful if your input contains more fields than your model, and you don’t wish to have many special cases for handling these unused data fields.

How to make a field auto increment in ActiveAndroid ORM

How can I make an integer or long field to be auto-incremented using annotation.
As we can read in a documentation:
One important thing to note is that ActiveAndroid creates an id field
for your tables. This field is an auto-incrementing primary key.
Maybe accessing auto-generated primary key will be enough for you?
Moreover, if you would like to create custom primary key in you model, you can check solution mentioned in GitHub issue connected with ActiveAndroid, which looks like this:
#Table(name = "Items", id = "clientId")
public class Item extends Model {
#Column(name = "id")
private long id;
}
Then, id field is custom primary key, which will be auto-incremented.
In case of ActiveAndroid ORM you do not need to write id column in model, It will automatic generate auto incremented value and you can simply use it.
I am giving a sample model below-
#Table(name="Items")
public class Item extends Model{
#Column(name="name")
public String name;
}
Instead of
#Table(name="Items")
public class Item extends Model{
#Column(name="Id")
public long id;
#Column(name="name")
public String name;
}
If item is an object of Item then you can simply get id by using
item.getId();
So, the correct model is first one. For reference you can click here.

How to Select All Columns from Azure Mobile Service in Android

I am using the .Net backend for Azure Mobile Service. I can successfully run the following query, and it returns all items from the database however it only returns the items with their IDs and no other columns are returns, they are all set to null
TableName.execute(new TableQueryCallback<ClassName>() {
#Override
public void onCompleted(List<ClassName> result, int count,
Exception exception, ServiceFilterResponse response)
So do I need to supply a select filter or should I be using the TableOperationsCallback? There is no error, it just returns all the columns as null except for the id column
Thanks
Make sure that the casing of the fields match between the client and the server. By default the .NET backend will make all properties camel-case, so that if you have this class:
public class Person : EntityData
{
public string Name { get; set; }
public int Age { get; set; }
}
Then the JSON response in a GET operation will look something like this:
[
{ "id":"the-first-id", "name":"John Doe", "age":33 },
{ "id":"the-first-id", "name":"Jane Roe", "age":34 }
]
So you need to define in your Android application a type where the field is either named in lower case, or properly tagged with the #SerializeName annotation, like in the example below (you don't need to do that for the id property as it's special-cased by the SDK):
public class Person {
#SerializedName("id")
public String Id;
#SerializedName("name")
public String Name;
#SerializedName("age")
public String Age;
}

setting own Key in Entity while using app engine

I am using eclipse to create a app engine based application where I am also using app engine datastore(using JPA) using endpoints.
I wrote a test application with help from
https://developers.google.com/eclipse/docs/endpoints-addentities
and it went fine.
Now I want to create an entity where I define my own Key rather than it being automatically assigned by the system. Can someone help me as to what do I need to do that in my Notes.java entity class. By default the Notes.java like this.
package com.bfp.mypackage;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Note {
#Id
private String id;
private String emailAddress;
private String description;
public Note() {
}
public String getId() {
return id;
}
public String getDescription() {
return description;
}
public String getEmailAddress() {
return emailAddress;
}
public void setId(String idIn) {
this.id = idIn;
}
public void setDescription(String description) {
this.description = description;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
When I test this code I see the Note entity created in my dev app server admin console with the values(an emailAddress, a dsescription and an ID(I pass timestamp there)) I had supplied. I see two other fields created when I view the entity in admin console. One "Key" and other "Write ops". Now the "Key" field as I understand is the one generated automatically by java. Is there anyway I can set my emailAddress field as the Key? If so then what changes I need to do in above code. That way I can use emailAddress as the unique key for each entity.
You must set your email address as the "Key" name : a key is defined by either an auto-incremented long ID, or a user assigned key name that is unique for an entity kind.
I'm not the most experimented using JPA since I've used mostly JDO and the low level approach, but you might have to use directly the com.google.appengine.api.datastore.Key object instead of a java.lang.String attribute...
The low level API method is :
KeyFactory.createKey("EntityName", "whatever#domain.com");

Categories

Resources