How can I join two classes in ObjectBox which have one two many relationship?
I have two tables as following:
#Entity
public class Animal {
#Id(assignable = true)
public long id;
private String name;
private boolean flying;
private boolean swimming;
private boolean walking;
private ToOne<Zoo> zoo;
.../*setters and getters*/
}
and:
#Entity
public class Zoo {
#Id
public long id;
private String name;
// a Zoo can have many Animals
#Backlink
ToMany<Animal> animals;
.../*setters and getters*/
}
How can I implement Join operation?
Since version 2.0.0 you can do something like:
val builder = box.query().equal(Zoo_.name, "The Big Zoo")
builder.link(Zoo_.animals).equal(Animal_.flying, true)
val flyingAnimals = builder.build().find()
This is called "links" and there is documentation on it with an additional example.
Related
I am implementing Room Database. Here is my POJO Class
public class Task implements Serializable {
#PrimaryKey(autoGenerate = true)
private int id;
#ColumnInfo(name = "task_name")
private String task;
#ColumnInfo(name = "description")
private String desc;
#ColumnInfo(name = "finish_by")
private String finishBy;
#ColumnInfo(name = "finished")
private boolean finished;
#ColumnInfo(name="no_of_days")
private String no_of_days;
public String getNo_of_days() {
return no_of_days;
}
public void setNo_of_days(String no_of_days) {
this.no_of_days = no_of_days;
}
}
This is the DAO Class
#Dao
public interface TaskDao {
#Update
void update(Task task);
#Query("SELECT task_name,description,no_of_days FROM task")
List<Task> getTasksandDescription();
}
While running my code, I am getting the following error
com.example.myapplication1.model.Task has some fields [id, finish_by, finished] which are not returned by the query. If they are not supposed to be read from the result, you can mark them with #Ignore annotation. You can suppress this warning by annotating the method with #SuppressWarnings(RoomWarnings.CURSOR_MISMATCH).
Columns returned by the query: task_name, description, no_of_days. Fields in com.example.myapplication1.model.Task: id, task_name, description, finish_by, finished, no_of_days.
This is not an error but a warning, it's telling you that you are mapping an SQL to a Pojo but you are not returning all the fields required to set up the Pojo. So your class has more fields than is returned from the query, you can fix this by doing the following.
I. Do a select * to return all the fields
#Query("SELECT * FROM task")
II. Add #Ignore annotation to the fields you're not interested in
III. Create another Java class that contains only the fields you're interested in and return in from the query instead.
I am quite familiar with these kind of thing on Spring JPA but I can not make it work on Android. I post my code below so you can understand the question better. I have two classes and a third class that needs to contain objects of class 1 and 2. I know that the code for the third class is not correct, since Room does not support object references like that. If I save just the id-s of the objects as foreign keys I am not able to query after the results.
There must be some kind of nice solution for this problem. Thank you.
#Entity(tableName = "soup")
public class Soup {
#PrimaryKey(autoGenerate = true)
private long id;
private String name;
// getter and setters
}
#Entity(tableName = "main_course")
public class MainCourse {
#PrimaryKey(autoGenerate = true)
private long id;
private String name;
// getter and setters
}
#Entity(tableName = "menu")
public class Menu {
#PrimaryKey(autoGenerate = true)
private long id;
private Soup soupOptionOne;
private Soup soupOptionTwo;
private Soup soupOptionThree;
private MainCourse courseOptionOne;
private MainCourse courseOptionTwo;
private MainCourse courseOptionThree;
}
I ask this question after searching for hours for the solution to this problem and did not find it.
I have build a database with three columns: username, password and age.
I am able to isert new users and update them, but I want it to be impossible to insert two identical user names. I know how to do it in sqlite but in greendao it just does not go for me. thank you.
here is my UsersClass:
#Entity(nameInDb = "users")
public class Users{
#Id(autoincrement = true)
private Long id;
#NotNull
private String userName;
#NotNull
private String password;
#NotNull
private int age;
}
The #Unique annotation should work for you.
#Entity(nameInDb = "users")
public class Users{
#Id(autoincrement = true)
private Long id;
#Unique
private String userName;
#NotNull
private String password;
#NotNull
private int age;
}
If you need to customize further you can add options to the #Entity annotation
#Entity(
...
// Define indexes spanning multiple columns here.
indexes = {
#Index(value = "name DESC", unique = true)
},
...
)
I am having a hard time getting a list item into room. the list item is called measurements and its of type Measurement. the list item has no primarykey that would be related to the database.
but i have no problem adding the same primary key for the ProductModel if necessary.
Here is what i have so far:
#Entity(tableName = TABLE_NAME)
public class ProductModel {
public static final String TABLE_NAME = "product";
#PrimaryKey
private int idProduct;
private int idCategoryDefault;
#Relation(parentColumn = "idProduct", entityColumn = "idProduct", entity = SortedAttribute.class)
private List<SortedAttribute> sortedAttributes = null;
}
#Entity
public class SortedAttribute {
#PrimaryKey
private int idProduct;
private String reference;
#Embedded
private List<Measurement> measurements = null; //****how do i get this into room ? its a LIST of measurements, not a measurement so calling Embedded i think wont work as it cant flatten it****/
}
public class Measurement {
private String value;
private String valueCm;
public Measurement() {
}
}
Embedded annotation can be used on a POJO or Entity only, not for a List. So, Room can not automatically flatten your list in this case.
You can use TypeConverter to convert List<Measurement> into String(in JSON format) and vise versa. You can use any JSON parser library to support it. For example, I use Gson as following.
public class ProductTypeConverters {
#TypeConverter
public static List<Measurement> stringToMeasurements(String json) {
Gson gson = new Gson();
Type type = new TypeToken<List<Measurement>>() {}.getType();
List<Measurement> measurements = gson.fromJson(json, type);
return measurements;
}
#TypeConverter
public static String measurementsToString(List<Measurement> list) {
Gson gson = new Gson();
Type type = new TypeToken<List<Measurement>>() {}.getType();
String json = gson.toJson(list, type);
return json;
}
}
#Entity
#TypeConverters(ProductTypeConverter.class)
public class SortedAttribute {
#PrimaryKey
private int idProduct;
private String reference;
private List<Measurement> measurements = null;
}
EDIT: Use a type converter
#Relation is what you are looking for.
https://developer.android.com/reference/android/arch/persistence/room/Relation.html
From the Room docs:
#Entity
public class Pet {
# PrimaryKey
int petId;
String name;
}
public class UserNameAndAllPets {
public int userId;
public String name;
#Relation(parentColumn = "petId", entityColumn = "userId")
public List<Pet> pets;
}
#Dao
public interface UserPetDao {
#Query("SELECT petId, name from User")
public List<UserNameAndAllPets> loadUserAndPets();
}
Note: Upon further research, Room does not quite support lists of objects that are INSIDE objects. I (and others) have opted to handle the lists separately. Room can handle lists of objects just fine as long as they aren't within an object; so as long as your items inside the list are related to your overall object you can recover the list.
So, you would actually #Ignore the list and just handle it in your Dao abstract class. I could not find the SO post's I found earlier that portray this.
After Reading the doc's Relations pages, I can use a many to many relation like this:
#Entity
public class Product {
#Id private Long id;
#ToMany
#JoinEntity(
entity = JoinProductsWithOrders.class,
sourceProperty = "productId",
targetProperty = "orderId"
)
private List<Order> ordersWithThisProduct;
}
#Entity
public class JoinProductsWithOrders {
#Id private Long id;
private Long productId;
private Long orderId;
}
#Entity
public class Order {
#Id private Long id;
}
Now, with this code, can I have a bi-directionel relations and access from an Order the list of Products associated with it?
Or should I add a Product List in the Order class too? Something like this:
...
#Entity
public class Order {
#Id private Long id;
#ToMany //I don't know if this is corect btw.
private List<Product> productsForThisOrder;
}
This is how you should do it:
#Entity
public class Order {
#Id private Long id;
#ToMany
#JoinEntity(
entity = JoinProductsWithOrders.class,
sourceProperty = "orderId",
targetProperty = "productId"
)
private List<Product> productsForThisOrder;
}