I am trying to learn Realm basics by implementing a simple Android project.
The idea is that user have several items and several item lists and an item can be added to any of these lists and a list can have many items. Therefore, there is a many to many relationship between Item and List objects. Here are my objects.
public class Item extends RealmObject {
#PrimaryKey
private String id;
private String name;
private boolean isDone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDone() {
return isDone;
}
public void setDone(boolean done) {
isCollected = done;
}
}
public class List extends RealmObject {
#PrimaryKey
private String id;
private String name;
private RealmList<Item> items;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmList<Item> getItems() {
return items;
}
public void setItems(RealmList<Item> items) {
this.items = items;
}
}
My problem is, the field isDone might be different depending on the item's status in a given list. But when I update this field in a list, all the other items added to different lists get updated too. Since they are using the same object it makes sense but that is not to behavior I want. Is there a Realm way to create a pivot table/object with an extra column/field (in that case isDone) ?
Any help would be appreciated.
The problem is that the isDone property of Item doesn't truly belong to Item. If you can set the same Item in multiple Lists, then the property that a given task is deemed complete within a given List is the property of the List.
public class Item extends RealmObject {
#PrimaryKey
private String id;
private String name;
//private boolean isDone;
#LinkingObjects("completedItems")
private final RealmResults<List> tasksCompletedIn = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//public boolean isDone() {
// return isDone;
//}
//public void setDone(boolean done) {
// isDone = done;
//}
}
public class List extends RealmObject {
#PrimaryKey
private String id;
private String name;
private RealmList<Item> items;
private RealmList<Item> completedItems;
Then you know if it's a completed item if completedItems.contains(item) (where item is a managed object, or overrides equals to check against only id)
Related
I am developing an ORM library similar to Hibernate. Now I'm stuck with the OneToMany relationship. I'd like to know how to fetch automatically data from database when getter of the one side is called and how Hibernate does it under the hood.
Many side
public class Film {
private int id;
private String name;
#JoinColumn(name="producer_id")
private Producer producer;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Producer getProducer() {
return producer;
}
public void setProducer(Producer producer) {
this.producer = producer;
}
}
One Side
public class Producer {
#Id
private int id;
private String name;
#OneToMany(mappedBy="producer")
private Set<Film> films;
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
// When called, it executes: SELECT ... FROM Film where producer_id = ?
public Set<Film> getFilms() {
return films;
}
}
In other words, I want to fill films inside Producer only when getFilms() is called.
Hibernate uses proxies of entity classes instead of real entity class using bytebuddy by generating addintional code at runtime.
BTW, I am just curious why are you developing your own ORM when you can use hibernate itself? It's the best ORM out there covering almost all kind of use cases and different optimization techniques.
I am learning google app engine with datastore for my next project. I have made a sample app for the same.
Here are the code for entities:
#Entity
public class Quote {
#Id
private Long id;
#Parent #Load
private Ref<Author> author;
public Quote() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Author getAuther() {
return author.get();
}
public void setAuther(Author author) {
this.author = Ref.create(author);
}
}
#Entity
public class Author {
#Id
private Long id;
String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I am inserting a Quote using this API
#ApiMethod(
name = "insert",
path = "quote",
httpMethod = ApiMethod.HttpMethod.POST)
public Quote insert(Quote quote) {
ofy().save().entity(quote).now();
return ofy().load().entity(quote).now();
}
When I try to insert a new quote, I get my author.get() as null. I am stuck in this problem from a long time and I am not able to continue learning.
Thanks.
I was not inserting Auther before inserting Quote. You can either hide it within the Entity model or you can do it separately in an API call.
i have defined destination class and some subclasses like region, country, city with some additional fields. i want put all their instances in the same solr core. it works, because i have created the schema with all possible fields(regionName, countryName etc. in the same schema.xml).
but i don't know, how can i fetch them and convert in the correct type? has anyone any idea? or it is not possible?
thanks for your answers,
best regards
shan
the code likes:
Destiantion
#SolrDocument(solrCoreName = "destination")
public class Destination implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4593263425568053104L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
City
public class City extends Destination {
/**
*
*/
private static final long serialVersionUID = 4593263425568053104L;
private int regionId;
private String regionName;
public int getRegionId() {
return regionId;
}
public void setId(int regionId) {
this.regionId = regionId;
}
public String getRegionName() {
return regionName;
}
public void setName(String regionName) {
this.regionName = regionName;
}
}
What kind of a code is this??
You use
#Field
on top of the fields/methods for no reason.
You write
Integer
instead of
int
in the return type. Dude ar e you trolling or what?
And the answer is NO.
(Had to write NO in case this post gets deleted.)
(I believe your post is ridicilious and deserves the answer NO)
(That's how it works in stack overflow nowadays.)
I have following classes :
Emp.java
final public class Emp {
private Integer id;
private String name;
private Department department;
public Emp(Integer id, String name, Department department) {
this.id = id;
this.name = name;
this.department = department;
}
public Department getDepartment() {
return department;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
Department.java
public class Department {
private Integer id;
private String name;
public Department(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
EmployeeTest.java
public class EmployeeTest {
public static void main(String args[]) {
Department dept1 = new Department(1, "dept1");
Emp emp = new Emp(1, "emp1", dept1);
emp.getDepartment().setName("dept2");
System.out.println("emp = "+emp);
}
}
Here Emp class is not purely an immutable class because somehow I am able to change the values of Department (as shown in the example).
What are the best possible changes which will make Emp class a pure Immutable class ?
In getters for non-primitive field, use this structure
public class Line {
private final Point start;
private final Point end;
public Line(final Point start, final Point end) {
this.start = new Point(start);
this.end = new Point(end);
}
public Point getStart() {
return new Point(start);
}
public Point getEnd() {
return new Point(end);
}
}
So, simply create new instance of department that is equals to previous
P.S. In my example you can see pure immutable class
EDIT:
Also you can add to Department class copy-contructor
public Department(final Department dep)
{ ... }
And to Employer
getDepartment()
{
return new Department(department);
}
See Efffective Java:
Item 15: Minimize mutability – 5 rules to follow.
Don’t provide any methods that modify the object’s state
Ensure that the class can’t be extended
Make all fields final
Make all fields private
Ensure exclusive acess to any mutable components
If you don't like removing setters and do initialization in a constructor, you can think about returning immutable (from the point of view of the Emp class) objects, which will web objects' copies, in getters (see https://stackoverflow.com/a/128712/1579085).
final public class Emp {
private Integer id;
private String name;
private Department department;
public Emp(Integer id, String name, Department department) {
this.id = id;
this.name = name;
this.department = (Department) department.clone();
}
public Department getDepartment() {
return (Department) department.clone();
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
And implement the method clone() in Department (which will implement the interface Cloneable) of course.
This approach is suitable, if you need to be able to modify Department, but the objects of the Emp class should be safe from those outer modifications.
make all attributes final, and remove all setters
Implement clone() in Department and make Emp return a clone of department in getDepartment().
If references to Department used in constructing Emp are available after construction, then Emp's constructor should clone given Department.
If I create a Customer and Controller, then associate my Controller with a customer it saves fine.
If I then remove my controller it doesn't remove the relationship between them.
This causes an EntityNotFoundException when I load the Customer.
javax.persistence.EntityNotFoundException: Unable to find Controller with id 22
I'd like to know how to map this so that when a Controller is deleted the relationship is also deleted.
Database Tables
customer
controller
customer_controllers - mapping table.
The Controller's id is not getting removed from the customer_controllers mapping table.
#Entity
public class Customer implements Serializable{
private Integer id;
private Set<Controller> controllers;
#Id
#GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Controller> getControllers()
{
return controllers;
}
public void setControllers(Set<Controller> controllers)
{
this.controllers = controllers;
}
}
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
}
If you have a ManyToMany then you should map Controller to Customer with a
#ManyToMany(mappedBy="controllers")
or the other way around, depending on which side is the owning side.
As you have it now the relation is not fully defined and it will fail on events like "Cascade".
Have you checked the javadoc for #ManyToMany?
It includes the above example mappings.
you need to make the relationship bidirectional, so that the controller object is aware of its relationship to the customer. Yhis means that when the controller is deleted the record in the join table is also deleted.
This isn't the exact mapping but it gives you the idea.
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
private Set<Customer> customers;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Customer> getCustomers()
{
return customers;
}
public void setCustomers(Set<Customers> customers)
{
this.customers= customers;
}
}