My team and I are strongly considering ditching our homebrew ORM for Hibernate/JPA and are now in the prototype phase, but I'm coming up against an issue, and I'm looking for pointers on a path forward.
Our projects have a very nice measurements with units framework.
Code:
public enum Units {
SECONDS, MINUTES, ...
FEET, METERS, ...
}
public class Measurable {
private double value;
private Units units;
public Measurable(double value, Units units) {...}
public double getValue(Units wantUnits) {...}
public Units getUnits() {...}
// no setters - immutable
public Measurable add(Measurable other) {...}
}
public class Distance extends Measurable {
public static fromMeters(double meters) {...}
}
public class Angle extends Measurable {
public double sin() {...}
public double cos() {...}
}
Etc., etc., and life is great. We can do lots of unit-aware manipulations and dimensional analysis without too much work on the client's end. However, as you can imagine, these things don't naturally fit into the POJO bean idiom that JPA and Hibernate prefer.
Code:
@Entity
public class DeliveryLocation {
private Long id;
private String name;
private Angle latitude;
private Angle longitude;
private Distance distFromDenver;
@Id
public Long getId() {...}
@DbUnits(Units.DEGREES)
public Angle getLatitude() {...}
@DbUnits(Units.DEGREES)
public Angle getLongitude() {...}
@DbUnits(Units.KILOMETERS)
public Distance getDistFromDenver() {...}
// setters, etc.
}
CREATE TABLE DELIVERY_LOCATION (
ID INT PRIMARY KEY NOT NULL,
LATITUDE_DEG FLOAT,
LONGITUDE_DEG FLOAT,
DISTANCE_FROM_DENVER_KM FLOAT
);
Our old ORM used our @DbUnits annotation for a few things. Part of it was appending the units onto the default column name, which is tricky but seemingly possible with a custom NamingStrategy. However, I still can't seem to get the knack of actually reading and writing the values. I think it will involve a custom ComponentTuplizer, and probably a custom Instantiator since they're immutable. However, there seem to be too many facets that I'm not conceptualizing clearly. Will my Measurables be @Embeddable, and my entity fields @Embedded? How do I get the @DbUnits annotation from the entity class when I'm tuplizing and instantiating my Measurables? How do I take the column names from the entity property name and not the Measurable field name without a @Column(name=) on everything? Are there other extension points I'm not aware of needing to change yet?
I did find a post (https://forum.hibernate.org/viewtopic.php?f=9&t=939592) which says of Tuplizer and Instantiator that, at least in 2005,
Quote:
Eventually these will be extension points hopefully. Currently they are not per-se.
Is that the case still? It seems like they are fully-fledged now, but I can't really find published examples of people acutally doing this.