How to Save Foreign Keys in Room Database - android

I have the following Model class that i want to store in Room Database:
I don't know much but i think i need to use foreign key here. Though i dont have much idea, its just a guess.
If you can give a detailed explanation,
public class EarthquakeData {
public List < Feature > features;
public class Feature {
public String type;
public Properties properties;
// public Geometry geometry;
public String id;
public class Properties {
public double mag;
public String place;
public Object time;
public Object updated;
public Object tz;
public String url;
public String detail;
public int felt;
public double cdi;
public double mmi;
public String alert;
public String status;
public int tsunami;
public int sig;
public String net;
public String code;
public String ids;
public String sources;
public String types;
public int nst;
public double dmin;
public double rms;
public double gap;
public String magType;
public String type;
public String title;
}
}
}
I have saved only a simple class in Room database like the following class:
#Entity(tableName = "notes")
public class Note {
#PrimaryKey
#NonNull
private String id;
#NonNull
#ColumnInfo(name = "note")
private String mNote;
public Note(#NonNull String id, #NonNull String mNote) {
this.id = id;
this.mNote = mNote;
}
#NonNull
public String getId() {
return id;
}
#NonNull
public String getNote() {
return this.mNote;
}
}
But i don't know to save the first type of model class in Room which is very complex for me because it consists of objects within a class.

From what I understand you have the following relationships:
1 EarthquakeData - Many Features
and
1 Feature - 1 Properties
So you could model it this way:
Table Features(id: PrimaryKey, earthquake_data_id: ForeignKey, ...)
and
Table Feature(id: PrimaryKey, properties_id: ForeignKey, ...)
With Room entities this would look something like this for the features:
#Entity(
tableName = "features",
foreignKeys = [
ForeignKey(
entity = EarthquakeDataEntity::class,
parentColumns = ["id"],
childColumns = ["earthquake_data_id"],
onDelete = ForeignKey.CASCADE, // See documentation for other operations
onUpdate = ForeignKey.CASCADE
)
]
class Features {
...
}
Check out the ForeignKey official documentation for the parameters

Related

Android Studio how to store API data in room database and retrieve by city name?

Android Studio how to store API data in room database and retrieve by city name?
I want to save the data I get from API to the room database. then how can I pull the data by city name?
I'm creating an SQLite database in android to store data from JSON in the database to view data if the app is offline.
public interface WeatherAPI {
#GET("forecast?")
Single<WeatherModel> getData(#Query("q") String name, #Query("APPID") String app_id);
}
My Model
#Entity(tableName = "Places")
public class WeatherModel {
#ColumnInfo(name = "cod")
#SerializedName("cod")
public String cod;
#SerializedName("message")
public int message;
#SerializedName("cnt")
public int cnt;
#SerializedName("list")
public List<list> list;
#SerializedName("city")
public City city;
public class Main{
#SerializedName("temp")
public double temp;
#SerializedName("feels_like")
public double feels_like;
#SerializedName("temp_min")
public double temp_min;
#SerializedName("temp_max")
public double temp_max;
#SerializedName("pressure")
public int pressure;
#SerializedName("sea_level")
public int sea_level;
#SerializedName("humidity")
public int humidity;
#SerializedName("temp_kf")
public double temp_kf;
}
public City getCity(){
return city;
}
public void setCity(City city) {
this.city = city;
}
public class Weather{
#SerializedName("id")
public int id;
#SerializedName("main")
public String main;
#SerializedName("description")
public String description;
#SerializedName("icon")
public String icon;
}
public class Clouds{
#SerializedName("all")
public int all;
}
public class Wind{
#SerializedName("speed")
public double speed;
#SerializedName("deg")
public int deg;
#SerializedName("gust")
public double gust;
}
public class Sys{
#SerializedName("pod")
public String pod;
}
public class Rain{
#SerializedName("3h")
public double _3h;
}
public class list{
#SerializedName("dt")
public int dt;
#SerializedName("main")
public Main main;
#SerializedName("weather")
public List<Weather> weather;
#SerializedName("clouds")
public Clouds clouds;
#SerializedName("wind")
public Wind wind;
#SerializedName("visibility")
public int visibility;
#SerializedName("pop")
public double pop;
#SerializedName("sys")
public Sys sys;
#SerializedName("dt_txt")
public String dt_txt;
#SerializedName("rain")
public Rain rain;
}
public class Coord{
#SerializedName("lon")
public double lon;
#SerializedName("lat")
public double lat;
}
public class City{
public int id;
#SerializedName("name")
public String name;
public Coord coord;
public String country;
public int population;
public int timezone;
public int sunrise;
public int sunset;
}
public WeatherModel(String cod, int message, int cnt, List<WeatherModel.list> list, City city) {
this.cod = cod;
this.message = message;
this.cnt = cnt;
this.list = list;
this.city = city;
}
}
#Dao
public interface PlacesDao {
#Query("SELECT * FROM Places")
Single<WeatherModel> getAll();
#Insert
io.reactivex.Completable insert(WeatherModel weatherModel);
#Delete
io.reactivex.Completable delete(WeatherModel weatherModel);
#Update
io.reactivex.Completable upDate(WeatherModel weatherModel);
}
First assuming that you want to store the data as per you model, you will need Type converters for all of the columns in the WeatherModel class (aka the Places table) the that are not types of String, integer types (long, Long, int, Int etc), decimal types (float, double Float, Double etc), or byte arrays; to convert them into such types.
i.e list and city.
Typically these converters would convert the type into a String as a JSON string (a byte array could potentially be used, it is unlikely (impossible?) to represent such objects as the integer or decimal values).
However, the resultant string, doesn't exactly assist in retrieving by a city name. That is the data in the city column would be something like :-
This is where you may start experiencing difficulties, say you wanted to search for *New York within the above data.
Then simply using a query that uses .... WHERE instr(city,'New York') > 0 , which in itself is beyond where some would be familiar with, could be used e.g. in room it could be :-
#Query("SELECT * FROM places WHERE instr(city,:cityname) > 0")
List<WeatherModel> getByCityNameV1(String cityname);
WHERE city LIKE '%'||:cityname||'%'" is similar but is not case sensitive unlike the instr function.
and this would get just the 1 row (first) (according to the data above) that has New York.
BUT if the above query were used for York then it would return both New York (first row) and York, the 2nd row.
To definitively find York then you need to search for, at the minimum "York" and hope that there are no other values that could clash, a safer bet would be to search for name":"York",". Now you have introduced the complexity of double quotes which can be problematic, so for this simple task you end of with something along the lines of:-
#Query("SELECT * FROM places WHERE instr(city,'name'||char(34)||':'||char(34)||:cityname||char(34)) > 0")
List<WeatherModel> getByCityNameV2(String cityname);

GSON Array to go

I'm thinking about it, but I can't print the name and age of the json Crospromotion on the console. I'm using the GSON library, but I'm stuck right now and I don't know how to move forward.
I have my JSON
{
"crospromotion": [
{
"name": "Orus",
"age":14
},
{
"name": "Michelle",
"age":29
},
{
"name": "Jack",
"age":29
}
],
"totalAccessorios": 20,
"totalCaras": 20
}
My JSon controller class:
public class Data {
private Crospromotion crospromotion;
private int totalAccessorios, totalCaras;
public int getTotalAccessorios() {
return totalAccessorios;
}
public int getTotalCaras() {
return totalCaras;
}
}
Class Crospromotion:
public class Crospromotion {
private String nombre;
private int edad;
public String getNombre() {
return nombre;
}
public int getEdad() {
return edad;
}
}
MainActivity:
Gson gson = new Gson();
final Data data = gson.fromJson(myResponse, Data.class);
Log.d("MEN: ", data.getTotalAccessorios());
// I want to print in Log, the fields Crospromotion: name and age. But I don't know how to continue.
The attributes in the json string have different names than in the class Crospromotion. So you can just change the property names of the Crospromotion class like this:
public class Crospromotion {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Also in the json string you have an array of Crospromotion instances, but in the data class you only have one instance. That means you have to change the json string or write the class like this.
import java.util.List;
public class Data {
private List<Crospromotion> crospromotions;
private int totalAccessorios, totalCaras;
public int getTotalAccessorios() {
return totalAccessorios;
}
public int getTotalCaras() {
return totalCaras;
}
public List<Crospromotion> getCrospromotions() {
return crospromotions;
}
}
You also didn't have a getter for the Crospromotion List. Therefore you couldn't access it, because the property was private. With this code you should be able to access the data that you want to access.
It looks like you just forgot to add a getter for your Crospromotion field in your Data class?
public class Data {
private List<Crospromotion> crospromotion;
private int totalAccessorios, totalCaras;
public int getTotalAccessorios() {
return totalAccessorios;
}
public int getTotalCaras() {
return totalCaras;
}
public Crospromotion getCrospromotion() {
return crospromotion;
}
}
...
Log.d("MEN: ", data.getCrospromotion().getAge());
Btw, it looks like the fields in your JSON don't match your Crospromotion class. GSON uses reflection to match json fields to members of a class. You can use #SerializedName() to map JSON field names to member fields if the names differ.
For example:
public class Crospromotion {
#SerializedName("name") private String nombre;
#SerializedName("age") private int edad;
public String getNombre() {
return nombre;
}
public int getEdad() {
return edad;
}
}

Serialise / deserialise model in firestore

I have the following class that I want to store in firestore.
public class User extends Model {
#PropertyName("user_auth_id")
public String authUid;
#PropertyName("first_name")
public String firstName;
#PropertyName("last_name")
public String lastName;
#PropertyName("picture_url")
public String pictureUrl;
#PropertyName("email")
public String email;
#PropertyName("companies")
public ArrayList<UserCompany> companies;
public User() {}
}
public class UserCompany extends Model {
public String name;
public String role;
public String position;
public UserCompany() {
super();
}
public UserCompany(Company company, String role, String position) {
this();
name = company.name;
this.role = role;
this.position = position;
}
public Map<String, Object> toObject() {
Map<String, Object> object = new HashMap<>();
object.put("id", id);
object.put("name", name);
object.put("role", role);
object.put("position", position);
return object;
}
}
#IgnoreExtraProperties
public class Model {
#Exclude
public String id;
public <T extends Model> T withId(#NonNull final String id) {
this.id = id;
return (T) this;
}
}
And I want to use a transaction to update an user entry with it's newly created company list. (appUser instanceOf User)
transaction.update(userRef, "companies", appUser.companies);
If I do so...I get
Invalid data. Unsupported type: ro.exemple.model.UserCompany
How can I serialise an User object so that I can deserialise it as such
User appUser = queryDocumentSnapshots.getDocuments().get(0).toObject(User.class);
Where queryDocumentSnapshots is the result of a query in my firestore db.
I know I can change from ArrayList to HashMap, but I wish to keep the List, and try to serialise and deserialise it, in order to obtain in firestore an array of objects.
if this serialization you must tag your class as Serializable..
public UserCompany extends Model implements Serializable
public class User extends Model implements Serializable
plus tag the class Model as well

How to insert data and retrieve data in nested relationships in Room Database Android

I have entities
#Entity
public class A {
#PrimaryKey(autoGenerate = true)
public long id;
public String bFId;
public List<B> bList;
}
#Entity()
public class B {
#PrimaryKey #NonNull
public String id;
public String oneCId;
public List<C> cList;
}
#Entity
public class C {
#PrimaryKey #NonNull
public String id;
public String value;
}
And I wrote this like a Relation
public class AWithB extends A{
#Relation(parentColumn = "id", entityColumn = "bId")
public List<BWithC> bWithC;
}
public class BWithC {
#Embedded
public B b;
#Relation(entity=C.class,parentColumn="bFId",entityColun="cid")
public List<C> {}
}
Is my relation wrong? And How to insert data And retrieve data this.I must to be used this relation.I cannot use another relation.Please help me.

nested json parsing for android with jackson

i just started to android prograamming and found nice tutorial by using imdb api. instead of using xml in this tutorial i would like to use json and for the recevied json i have a problem.
this is the person.json:
[
{
"score":1,
"popularity":3,
"name":"Brad Pitt",
"id":287,
"biography":"test",
"url":"http://www.themoviedb.org/person/287",
"profile":[
{
"image":{
"type":"profile",
"size":"thumb",
"height":68,
"width":45,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w45/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"profile",
"height":281,
"width":185,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"h632",
"height":632,
"width":416,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/h632/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"original",
"height":1969,
"width":1295,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/original/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
}
],
"version":685,
"last_modified_at":"2013-02-16 07:11:15 UTC"
}
]
my two object for them:
public class Person implements Serializable {
private static final long serialVersionUID = 6794898677027141412L;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
public String lastModifiedAt;
public Profile profile;
}
public class Profile implements Serializable {
private static final long serialVersionUID = -8735669377345509929L;
public ArrayList<Image> imagesList;
}
public class Image implements Serializable {
private static final long serialVersionUID = -2428562977284114465L;
public String type;
public String url;
public String size;
public int width;
public int height;
}
ı couldnt figure out how to retrieve person list by using jackson object mapper.
when i use this one:
ObjectMapper mapper = new ObjectMapper();
Person person= mapper.readValue(jsonResponseString, Person.class);
i got:
02-16 18:34:48.010: W/System.err(376): com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.example.imdbsearcher.model.Person out of START_ARRAY token
02-16 18:34:48.180: W/System.err(376): at [Source: java.io.StringReader#40a81778; line: 1, column: 1]
02-16 18:34:48.554: W/System.err(376): at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599)
02-16 18:34:48.830: W/System.err(376): at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593)
i have changed the retrieve method with advice of Keith and crdnilfan.
but now i have a problem with the attribute of profile.
i realized that i am missing that one in person object and basicly i have created new profile object and moved imageList to this class.
i have updated POJO's as above.
but now i am getting the same error for the profile.
Can not deserialize instance of com.example.imdbsearcher.model.Profile out of START_ARRAY token
You need to deserialize the list, as your JSON is an array:
List<Person> people = mapper.readValue(
jsonResponseString, new TypeReference<List<Person >>(){});
However, after you do that you will have some additional deserialization errors because of the profile property in your JSON. Checkout: http://jackson.codehaus.org/1.5.7/javadoc/org/codehaus/jackson/annotate/JsonIgnoreProperties.html
Update:
public class Person implements Serializable
{
public List<Object> profile;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
public String last_modified_at;
}
There are several ways to deal with this. This will give you a linked hash map for Profile.
Alternatively, if you control the JSON format, change the profile syntax to this:
"profile":[
image:...,
image:...
]
That's because you are trying to deserialize a list of Person.class, not one instance. Create another class like this
public class PersonList extends ArrayList<Person> {}
and then use
ArrayList<Person> people = mapper.readValue(jsonResponseString, PersonList.class);
The other two answers clearly explain the reason for the error, it would get rid off the error and it will parse Person object. But for me it failed to parse image objects. With below POJO we can parse the specified json completely, without any issues even in the absence of
#JsonIgnoreProperties
or
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
POJO definition:
public class PersonList extends ArrayList<Person> {}
public class Person implements Serializable {
private static final long serialVersionUID = 6794898677027141412L;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
#JsonProperty(value="last_modified_at")
public String lastModifiedAt;
public List<Profile> profile;
}
public class Profile implements Serializable {
private static final long serialVersionUID = -8735669377345509929L;
#JsonProperty(value="image")
public Image imagesList;
}
public class Image implements Serializable {
private static final long serialVersionUID = -2428562977284114465L;
public String id;
public String type;
public String url;
public String size;
public int width;
public int height;
}
This should parse the json
String jsonResponseString = readJsonFile("person.json");
ObjectMapper mapper = new ObjectMapper();
PersonList person= mapper.readValue(jsonResponseString, PersonList.class);
or
List<Person> person= mapper.readValue(jsonResponseString,
new TypeReference<List< Person>>(){}); //if we use this we dont have to define PersonList class

Categories

Resources