Realm : How to structure one to many relationship - java

I have been looking over to many ORM's in android, by far what i have used and would fit to my app so far are ActiveAndroid and SugarOrm, but what i need is not currently supported(not supported but can be fix by creating sql scripts) as of now (one-to-many relationship). Im looking at Realm ORM for android a very promising one.
Is this possible with Realm?
// this is just a sample of what i need to do.,
// parent
class Message{
long id;
List<Meta> messages;
}
// child
class Meta{
long senderId;
String message;
Date date;
int status;
}
// I have already know how to do this on ActiveAndroid but seems a bit hard
// to update records or fetch single data.
Note: I have been having problems lately when manually creating my SQL scripts, and its very time consuming coding all of those when ORM's are there, And its very annoying when something needs to change I have to restructure most of the affected columns and etc.
I hope I had asked my question clearly and I hope there is a better way for this.
Thanks

Yes, that is very much possible with Realm. Realm is an object store, so it stores your objects as they are. In a normal object model one-to-many relationships are defined using lists, the same with Realm which has a special list called RealmList you can use.
In Realm the model you have should be defined as follow:
class Message extends RealmObject {
private long id;
private RealmList<Meta> messages;
// Getters and setters
}
class Meta extends RealmObject {
private long senderId;
private String message;
private Date date;
private int status;
// Getters and setters
}

Related

Improving JPA entity classes for existing DB schema

I am attempting to implement a Hibernate/JPA2 solution over an existing schema, which cannot be changed. Here is a minimal example of the existing schema:
CREATE TABLE REASON (
REASON_CODE CHAR(1),
REASON_DESCRIPTION CHAR(50))
CREATE TABLE HEADER (
REASON_CODE CHAR(1),
OTHERFIELD1 CHAR(40),
OTHERFIELD2 CHAR(40) )
Normally this would be the "correct" way from a DB perspective: Link REASON to HEADER by the REASON_CODE. However it's presenting me with an awkward problem in Java and I'm not sure of the best way to solve it. I've modeled these entities as follows:
#Entity
#Table(name="REASON")
public class Reason implements java.io.Serializable {
#Id
#Column(name="REASON_CODE", unique=true, nullable=false, length=1)
private Character reasonCode;
#Column(name="REASON_DESCRIPTION", nullable=false, length=25)
private String reasonDescription;
}
#Entity
#Table(name="HEADER")
public class Header implements java.io.Serializable {
#ManyToOne
#JoinColumn(name = "REASON_CODE", nullable = false)
private Reason reason;
#Column(name="OTHERFIELD1")
private String otherField1;
#Column(name="OTHERFIELD2")
private String otherField2;
}
Once again, as far as I can tell, this is "correct" from a Java perspective - linking Header to Reason with a reference.
The problem is that when I need to use one of these Reason values in my code I wind up with awkward syntax like:
Reason r = reasonService.findOne('X'); // X is the REASON_CODE in the database record
// Do some processing with variable r
Or this:
header.setReason(reasonService.findOne('X'));
Ideally I could implement Reason as an enum like:
public enum Reason {
X_MARKSTHESPOT("X"),
C_MEANSSOMETHINGELSE("C"),
F_MEANSATHIRDTHING("F") ;
private String code;
private Reason(String code) {
this.code = code;
}
}
And then simply have this in my code:
header.setReason(Reason.X_MARKSTHESPOT);
But from what I understand that is not possible with JPA, which offers only EnumType.STRING (basically the name) or EnumType.ORDINAL (even worse, the index in the enum list). A possible way around this would be JPA 2.1's Converter, but I have never used it. I have also read here (in one of the answers) that a Hibernate User Type might be useful. One of our programmers has solved this in another app by writing two complete classes - an enum class for internal use and a "shadow" class which iterates through the enum and syncs the records in the database on every startup. But this seems like a kludgey way to do it. What is the best way to handle this, bearing in mind that the database schema cannot be changed?

What is appropriate way of creating objects with One-to-Many relationship using Objectify and RequestFactory?

What is appropriate way of creating objects with One-to-Many relationship using Objectify and RequestFactory? I've read documentation for these libraries, and also reviewed number of sample projects such as listwidget and gwtgae2011. All of them use #Embedded annotation which is not what I want because it stores everything within one entity. Another option according to documentation would be to use #Parent property in child classes. In my example (getters/setters removed for simplicity) I have entities Person and Organization which defined as
#Entity
public class Person extends DatastoreObject
{
private String name;
private String phoneNumber;
private String email;
#Parent private Key<Organization> organizationKey;
}
and
#Entity
public class Organization extends DatastoreObject
{
private String name;
private List<Person> contactPeople;
private String address;
}
Now if I understood documentation correctly in order to persist Organization with one Person I have to persist Organization first, then set organizationKey to ObjectifyService.factory().getKey(organization) for Person object and then persist it. I already don't like that I have to iterate through every child object manually but using RequestFactory makes everything is more convoluted due to presence of proxy classes. How would I define Organization and OrganizationProxy classes - with Key<> or without it ? Will I have to define something like this in Organization ?
public void setContactPeople(List<Person> contactPeople)
{
for (int i = 0; i < contactPeople.size(); ++i)
{
DAOBase dao = new DAOBase();
Key<Organization> key = dao.ofy().put(this);
contactPeople.get(i).setOrganizationKey(key);
}
this.contactPeople = contactPeople;
}
And how would I load Organization with its children from Datastore ? Will I have to manually fetch every Person and fill out Organization.contactPeople in #PostLoad method ?
It seems like I'll have to write A LOT of maintenance code just to do what JPA/JDO does behind the scene. I simply don't get it :(
Am I missing something or it's the only way to implement it ?
Thanks a lot for answers in advance!!!
You need to make it as #Parent only when you going to use it in transaction against all Person in this Organization. I'm sure it's not what you want.
It's enough to save just private Key<Organization> organizationKey, and filter by this field when you need to find Person for specified Organization
As about loading all referenced objects - yes, it is, you have to load it manually. It's pita, but it's not a lot of code.
Also, there is a different way to store this relationship, if your organization are small enough, and consists of few hundreds of people. At this case you can have List<Key<Person>> contactPeopleKey;, and load all this people by existing Key, manually, it much be much faster than loading by new Query

What is the best approach to write a data access object (DAO)?

I was trying to write a user authentication system in Java. So I wrote some DAO class. First I did write a class named Persistence which is abstract. It is responsible for holding some common attributes. And wrote a class named User extending Persistence class. Those classes are –
public abstract class Persistance {
private Date createdDate;
private Date lastUpdatedDate;
private long version;
private boolean isDeleted;
//getter and setters
}
and the user class
public class User extends Persistance{
private String username;
private String password;
private String passwordConfired;
// getters and setters
}
My questions are- what is the best way to write variable name, which one is good, createdDate or dateCreated, deleted or isDeleted etc.
And is this approach is okay or is there more good approach ?
And how to implement data versioning?
To write a DAO, typically you create an interface that defines the behavior of the DAO.
interface MyObjDao {
public int save(MyObj myObj);
public void delete (MyObj myObj);
// as many methods as you need for data acess
}
and then you create the actual implementation
class MyObjDaoImpl implements MyObjDao {
// implement methods here
}
The advantages of this are:
1) Because you define an interface, mocking DAOs is easy for any testing framework
2) The behavior is not tied to an implementation -- your DAOImpl could use jdbc, hibernate, whatever
Your Persistance class is really a base class for all entities -- i.e. all classes instances of which get saved, where you want to represent some common fields in one place. This is a good practice -- I wouldn't call the class Persistance, something like BaseEntity is better (IMHO). Be sure to have javadocs that explain the purpose of the class.
With respect to variable names, as long as they make sense and describe what they are for, its good.
so dateCreated or createdDate are both fine; they both get the idea across.
You are mixing a DAO (data access object) and a VO (value object) - also known as a DTO (data transfer object) - in the same class.
Example using an interface for DAO behavior (blammy and kpow might be webservice, oracle database, mysql database, hibernate, or anything meaningful):
public interface UserDTO
{
boolean deleteUser(String userId);
UserVO readUser(String userId);
void updateUser(String userId, UserVO newValues);
}
package blah.blammy;
public class UserDTOImpl implements UserDTO
{
... implement it based on blammy.
}
package blah.kpow;
public class UserDTOImpl implements UserDTO
{
... implement it based on kpow.
}
Example VO:
public class UserVO
{
String firstName;
String lastName;
String middleInitial;
... getters and setters.
}
I prefer to identify the target of the delete using an ID instead of a VO object. Also, it is possible that an update will change the target identified by user ID "smackdown" to have user ID "smackup", so I generally pass an id and a VO.
A good approach would be to use JPA with all of its features, this tutorial was really helpful.
It explains how to use the #PrePersist and #PreUpdate annotations for setting create and update timestamps. Optimistic locking is supported by the #Version annotation.
My questions are- what is the best way to write variable name, which
one is good, createdDate or dateCreated, deleted or isDeleted etc.
createdDate or dateCreated is very subjective. In databases, I have mostly seen createdDate though. Between deleted and isDeleted, I prefer (again subjective) deleted. I think the getter method can be named isDeleted().

Hibernate joins every table in database

I've set up a small project as a test. I'm using BlazeDS and JPA with Hibernate on my test server, and flex with with dpHibernate to access the Java entities. Each Java entity extends BaseEntity, a class that contains ID and UUID fields. The Flex entities are created by DTO2FX.
My problem is that, when I run the Flex project to try and display a few rows from a Users entity, the SQL that is actually being executed is joining every table in my database. This continues until I get java.lang.StackOverflowError. This behavior is completely unexpected, and I'm not really sure where to look to fix the problem. Any suggestions would be greatly appreciated.
Clearly I've left out some details, but I'm hoping this gives a reasonable idea about the project. I would be more than happy to include any code that might be helpful, but I really have no idea what's causing the behavior at the moment. Thanks!
EDIT: Here is a mapping that might better explain the problem.
#Entity
#FXClass(ignoreSuperclasses={Principal.class, UserDetails.class})
#Table(name="edrUser")
public class User extends BaseEntity implements IAbstractEntity, Principal, UserDetails {
#Column(length=20)
private String username;
#ManyToMany(mappedBy="users",fetch=FetchType.LAZY)
private Set<Department> departments = new HashSet<Department>(0);
#ManyToOne
#JoinColumn(name="company_id",nullable=false)
private Company company;
#OneToMany(cascade=CascadeType.ALL, mappedBy="user", fetch=FetchType.LAZY)
private Set<DepartmentJobUserLink> departmentJobUsers = new HashSet<DepartmentJobUserLink>(0);
#Column(length=20)
private String password;
#Column(length=20)
private String forename;
public User(){
super();
}
/* Getters and setters */
}
Did you force lazy-loading to false?
Sounds to me like u having a cycle in your SQL tabledependencies, but thats just a guess. Checked that already?

Preventing infinite loop data retrieval with Hibernate

I was wondering: Imagine a scenario where e.g.
//POJO
public class User {
private String userName;
private String name;
private String surname;
private List<Blog> blogList;
//All getters and setters are found here and assume they're generated.
}
public class Blog {
private String title;
private String content;
private User author;
private Date datePublished;
private Date dateLastModified;
//All getters and setters have been generated (by Eclipse or NetBeans)
}
Imagine that these objects have been correctly mapped into their respective Hibernate configuration files.
My question:
How would I retrieve my user with the list of all the user blogs on code level? (i.e., not allow hibernate to populate blogList automatically for me.
I want to add paging (i.e. from list 5, retrieve 20 list) and also, if you think carefully, this might be an infinite loop as a Blog has a User entity which has a List<Blog> entity.
How do I prevent this?
PS Just out of curiousity, how would I let Hibernate populate my blogList on the configuration side?
Thanks in advance.
Hibernate detects such loops and doesn't let them happen
You can mark your collection with fetch type=lazy (fetchType=FetchType.LAZY) so that the collection elements are not fetched when the owning object is
you can used a Query with setFirstResult(..) and setMaxResults(..) in order to achieve paging. (and get rid of the collection then)

Categories