Finally, after quite a while, we found some free time to work on Android persistence library I wrote about in this blog post. Knowing we have very tight schedule, as always, we wanted to make sure library is ready to be used. So, we took a good look at what we did before, rolled up our sleaves and got to work.
Main goal was to make library stable and useful. In order to achieve that, some of the functionalities were reimplemented, some new were added and some were removed. There is no sense in having some features that are not part of any complete logic representing only fractions of future functionality set. Since those are useless if looked upon separately, they could only confuse person who is using the library.
So, what has, actually, been done?
First of all, support for primitive types is removed. This decision was influenced by several factors. By doing this, handling null values is finally made clear. The problem was in combination of primitive types and database null values. If you have a field of primitive type, how would you write null value in appropriate database table column? If you somehow manage to do that, there is no way to set it properly as a value of appropriate field on instantiated object. Of course, some kind of “zero” value could be set, but this would lead to ambiguity since it wouldn’t answer the question does some field of type ‘long’ holds 0L value because it is null (user didn’t input anything) or it is really zero.
Also, complexity and readability of code is much improved, i.e. number of “if” statements is reduced now and those still existing are simpler.
One of the features that is removed are fetch type and cascade type descriptors. This means that, currently, library has some strict rules how fetching is done and those cannot be altered using annotations or any configuration.
Fetching is always done lazily so user has to load any relationship objects manually.
Persisting is done eagerly means everything attached to the object being persisted, will be persisted also. No synchronization will be done (no deletion of objects missing from the list or anything of that kind), only persisting of what is present on the object is done.
Deletion is done eagerly meaning when deleting object, its children will be deleted too – not only those attached to the object, but all currently present in database.
Regarding mapping different types of relationship, it is important to point out that many-to-many relationship is not yet supported. Furthermore, library recognizes only unidirectional relationships. This is very important to have in mind while annotating domain model in order to avoid creating silly database structure.
This is how relationship annotations are interpreted by the library:
- @OneToOne annotation: database table corresponding to the declaring class of a field annotated with this annotation contains foreign key column referencing the other side of the relationship.
- @OneToMany annotation: database table corresponding to the class of a field annonatated with this annotation contains foreign key column referencing database table corresponding to the declaring class of that field.
- @ManyToOne annotation: database table corresponding to the declaring class of a field annotated with this annotation contains foreign key column referencing the other side of the relationship.
Meanwhile, this small project of ours got its name – Simple Persistence for Android. Being a company that wants to share knowledge with the community, we made it publicly and freely available for everyone who wants to use it. SPA is now open-sourced and can be found on GitHub. A demo project called “spa-tester” can be found there and it should be used as quick-start example.
There are some future development plans for it, of course. For example, we would realy like to support bidirectional relationships, implement many-to-many mapping, put back cascading and fetching type descriptors and improve database querying by making it more separated from physical structure. But, for the time being, we will have to hold that in mind and commit ourselves to our commercial projects.