I'm currently working with a simple JPA model for OpenStreetMap (OSM). There are ways and nodes, and each way has a sequence of nodes. Of course the order of the nodes is important, and a node may be used more than once for a given way.
Thus, the nodes collection has to be a List, not a Set, and we need an explicit order column specifying the sequence number of the nodes along the way. Sorting the nodes by ID would not make any sense, obviously.
Here is a snippet from the model:
@Entity @Table(name = "ways") public class OsmWay { @Id private long id; @ManyToMany(cascade = CascadeType.ALL) @OrderColumn(name = "sequence_id") @JoinTable(name = "way_nodes", joinColumns = @JoinColumn(name = "id"), inverseJoinColumns = @JoinColumn(name = "node_id")) private List<OsmNode> nodes = new ArrayList<OsmNode>(); }
This entity is represented by two tables:
CREATE TABLE ways ( id bigint NOT NULL ); CREATE TABLE way_nodes ( id bigint NOT NULL, node_id bigint NOT NULL, sequence_id integer, );
I've tested this scenario on Hibernate 3.5.3, Eclipselink 2.1.1 and OpenJPA 2.0.1: Hibernate and OpenJPA pass, Eclipselink fails with 2 issues.
First, the generated DDL is incorrect: There is a PRIMARY KEY (id, node_id) for way_nodes. This should be (id, sequence_id).
Second, the order of the list items is not maintained in all contexts. It is ok when the collection is lazily loaded, e.g.
OsmWay way = em.find(OsmWay.class, wayId); List<OsmNode> nodes = way.getNodes();
but it is broken when using a fetch join:
String jpql = "select distinct w from OsmWay w join fetch w.nodes"; TypedQuery<OsmWay> query = em.createQuery(jpql, OsmWay.class); List<OsmWay> ways = query.getResultList(); OsmWay way = ways.get(0); List<OsmNode> nodes = way.getNodes();
The funny thing is, the nodes are neither ordered by sequence_id nor by node_id. In my test case, the way has 5 nodes, one of which appears twice in different positions.
So here is some more evidence for my claim that the JPA 2.0 TCK is insufficient.
No comments:
Post a Comment