Persisting timestamp field as Date or Long? - jpa

I need a consensus on the practice of persisting timestamps, specifically on the pros & cons of using java.util.Date compared to using long.
Scope of this discussion:
Performance
Querying Flexibility (e.g. date range)
Any hazards in coding and querying
Portability (e.g. migration to other DB)
About myself:
I consider myself to be a beginner in JPA, dabbling in it once in a while, not being able to apply it into production level projects until now. In my current project, I commit myself to use ObjectDB (embedded) through JPA calls.

The following class demonstrates 3 possible methods for persisting timestamps in JPA:
#Entity
public class Timestamps {
private java.sql.Timestamp ts1;
private #Temporal(TemporalType.TIMESTAMP) java.util.Date ts2;
private long ts3;
:
}
Regarding performance and memory consumption, ts3 is a bit more efficient.
ts3 may be less convenient to use than ts1 and ts2 (in ObjectDB Database Explorer, reports, etc.).
Basic queries such as retrieval by date range are supported for all the three, but extracting date and time parts (YEAR, MONTH, etc.) in queries is not supported for ts3.
All these forms are expected to be portable.
ts1 and ts2 are practically equivalent.
More details are provided in the ObjectDB manual.

In the documentation of java it looks like timestamp is closer related to java.util.date
http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/Timestamp.html
additionally if you care about the semantic of your code, a timestamp is a date.

You should be aware about java.sql.Timestamp's fact before using it:
There are some classes in the Java platform libraries that do extend an instantiable
class and add a value component. For example, java.sql.Timestamp
extends java.util.Date and adds a nanoseconds field. The equals implementation
for Timestamp does violate symmetry and can cause erratic behavior if
Timestamp and Date objects are used in the same collection or are otherwise intermixed.
The Timestamp class has a disclaimer cautioning programmers against
mixing dates and timestamps. While you won’t get into trouble as long as you
keep them separate, there’s nothing to prevent you from mixing them, and the
resulting errors can be hard to debug. This behavior of the Timestamp class was a
mistake and should not be emulated. (Bloch, Effective Java, 2nd Ed.)

Related

integration testing, comparing JPA entities

Consider you are doing some integration testing, you are storing some bigger entity into db, and then read it back and would like to compare it. Obviously it has some associations as well, but that's just a cherry on top of very unpleasant cake. How do you compare those entities? I saw lot of incorrect ideas and feel, that this has to be written manually. How you guys do that?
Issues:
you cannot use equals/hashcode: these are for natural Id.
you cannot use subclass with fixed equals, as that would test different class and can give wrong results when persisting data as data are handled differently in persistence context.
lot of fields: you don't want to type all comparisons by hand. You want reflection.
#Temporal annotations: you cannot use trivial "reflection equals" approaches, because #Temporal(TIMESTAMP) java.util.Date <> java.sql.Date
associations: typical entity you would like to have properly tested will have several associations, thus tool/approach ideally should support deep comparison. Also cycles in object graph can ruin the fun.
Best solution what I found:
don't use transmogrifying data types (like Date) in JPA entities.
all associations should be initialized in entity, because null <> empty list.
calculate externaly toString via say ReflectionToStringBuilder, and compare those. Reason for that is to allow entity to have its toString, tests should not depend that someone does not change something. Theoretically, toString can be deep, but commons recursive toStringStyle includes object identifier, which ruins it.
I though, that I could use json format to string, but commons support that only for shallow toString, Jackson (without further instructions on entity) fails on cycles over associations
Alternative solution would be actually declaring subclasses with generated id (say lombok) and use some automatic mapping tool (say remondis mapper), with option to overcome differences in Dates/collections.
But I'm listening. Does anyone posses better solution?

Converting datetime to a long timestamp in JPQL

I have an entity with two columns:
// time when the event happened (stored in UTC)
#Temporal(TemporalType.TIMESTAMP)
private Date eventTime;
// timezone offset in milliseconds
// so local millis are eventTime.getTime() + offset
#Basic
private int offset;
It appears that in JPQL queries I can't use something like WHERE eventTime + offset > :parameter. But is it possible to work around by casting eventTime to a long in some way? Of course, there is an option of using native queries...
EDIT:
It isn't supported in the standard and isn't mentioned in OpenJPA documentation, so probably not possible at the moment.
It may not be possible for you to modify the table, but can you possibly just add another column which is the computed timestamp with offset? Then just base all of your queries off of that? It will probably yield better performance, as well.
Another way I've solved problems like this is to create a SQL view and and create a different #Entity based on that view. I have done this when I need a lot of complex computations and don't want all of that complexity in the code itself. This is useful when you have other non-JPA based applications that want to get at the same information (such as a reporting engine). While this solution ends up using a SQL view, it allows your Java/JPA code to not have to deal with native queries.
What I've done in similar situations before is to declare the setters/getters private or protected and then have public #Transient getters to perform the desired calculation.
This solves all programmatic issues. For desired jpa sql you'll need to perform the appropriate calculation in the query.

does morphia supports automatic timestamp?

Does anyone knows if morphia supports automatic timestamp for create/update of documents in a collection in mongodb during its create/modify operations.
I have already come to know that this support is not available in mongodb. I would like to know if there is any way to get the last access/update time of data or documents in morphia driver.
Thanks,
sadish
I'm generally using a base entity, which all other entities extend. It provides the ObjectId, creation date, last change date, a disabled flag,...
The relevant code snippets look like this:
protected Date creationDate;
protected Date lastChange;
// Getters and setters or final setters which don't do anything,
// if you only want to allow the entity to update the values
#PrePersist
public void prePersist() {
creationDate = (creationDate == null) ? new Date() : creationDate;
lastChange = (lastChange == null) ? creationDate : new Date();
}
Sorry in advance if this isn't the exact answer you're looking for. But the short answer is no.
There appears to be no API in the latest Morphia which supports that operation. Maybe there is a bug opened to support this. In the meantime, you should use your favorite constructor for java.util.Date or java.sql.Timestamp.
The source code for Morphia has the appropriate converter built in to handle this TimestampConverter.java.
Only tangentially related. If your reason for using $currentDate is to avoid clock skew problems among multiple hosts, then you're barking up the wrong tree. Though not explicitly stated in the $currentDate documentation, it is documented that MongoDB does nothing to address clock skew among various hosts. This can be found in the documentation for ObjectId.getTimestamp(). Therefore, the usage of $currentDate is going to provide little benefit as opposed to time-stamping in the client side.

Scala, Morphia and Enumeration

I need to store Scala class in Morphia. With annotations it works well unless I try to store collection of _ <: Enumeration
Morphia complains that it does not have serializers for that type, and I am wondering, how to provide one. For now I changed type of collection to Seq[String], and fill it with invoking toString on every item in collection.
That works well, however I'm not sure if that is right way.
This problem is common to several available layers of abstraction on the top of MongoDB. It all come back to a base reason: there is no enum equivalent in json/bson. Salat for example has the same problem.
In fact, MongoDB Java driver does not support enums as you can read in the discussion going on here: https://jira.mongodb.org/browse/JAVA-268 where you can see the problem is still open. Most of the frameworks I have seen to use MongoDB with Java do not implement low-level functionalities such as this one. I think this choice makes a lot of sense because they leave you the choice on how to deal with data structures not handled by the low-level driver, instead of imposing you how to do it.
In general I feel that the absence of support comes not from technical limitation but rather from design choice. For enums, there are multiple way to map them with their pros and their cons, while for other data types is probably simpler. I don't know the MongoDB Java driver in detail, but I guess supporting multiple "modes" would have required some refactoring (maybe that's why they are talking about a new version of serialization?)
These are two strategies I am thinking about:
If you want to index on an enum and minimize space occupation, you will map the enum to an integer ( Not using the ordinal , please can set enum start value in java).
If your concern is queryability on the mongoshell, because your data will be accessed by data scientist, you would rather store the enum using its string value
To conclude, there is nothing wrong in adding an intermediate data structure between your native object and MongoDB. Salat support it through CustomTransformers, on Morphia maybe you would need to do the conversion explicitely. Go for it.

Best ID datatype for GWT+ JPA

I know, that similar questions are around.
But for my case: I use GWT 2.4 + JPA 2.0 + (MySQL):
Whatis the best data type for my table IDs?
I want to avoid any type conversions in my GWT project.
My desire is easiness, not performance.
Do you advise me to use Wrapper classes i.e long vs. Long?
A simple and straightforward choice is Long. Prefer to use the wrapper class, so you can set the id to null, before the object is inserted into the DB (see also Always use primitive object wrappers for JPA #Id instead of primitive type?)
If performance is not a high priority, you may consider using UUIDs instead: This makes it a lot easier to put objects into sets and maps - before they are stored on the servers side. For easiness, you could use Strings to store the UUIDs (GWT doesn't support the UUID datatype), though using an UUID-specific datatype would be a lot more efficient in a database.
Certainly the wrapper сlass is better than the primitive. Using of object has many advantages. But in my opinion the best choose of type in this situation is class String. Long is undesirable to use in GWT development because JavaScript doesn't have the concept of a long. So recommended to avoid using long if possible. It's emulated on GWT it affects performance.