I want to map a MariaDB Point
field to a custom Vector2
type with Hibernate.
I have the following table:
CREATE TABLE `ships` (
`accounts_id` int NOT NULL,
`maps_id` int NOT NULL,
`position` point NOT NULL
) ENGINE InnoDB CHARACTER SET utf8;
And I want to map it to a class like this:
class Ship {
public Account account;
public Map map;
public Vector2 position;
}
The problem comes with the position
field, how do I map it to an already existing type?
The solutions I've found implied using hibernate-spatial in order to use its Point
class, however I want to use my Vector2
class instead of that one
After some hours of reading I figured it out.
First I need a simple way to get the X and Y coordinates of a point
column.
According to the manual they are stored in WKB, HOWEVER, when I tried myself to retrieve the raw bytes something wasn't right:
ResultSet rs = statement.executeQuery("SELECT * FROM accounts_ships");
rs.next();
byte[] position = rs.getBytes("position");
// position ==> byte[25] { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 80, -44, 64, 0, 0, 0, 0, 0, 0, -55, 64 }
There were 4 additional bytes to the beginning of the array. A part of this, everything was right so I proceeded to parse the result while keeping in mind those bytes:
var in = new ByteArrayInputStream(rs.getBytes(names[0]));
if (in.available() == 25) {
in.skip(4);
}
var order = ByteOrder.BIG_ENDIAN;
if (in.read() == 1) {
order = ByteOrder.LITTLE_ENDIAN;
}
var typeBytes = new byte[4];
var xBytes = new byte[8];
var yBytes = new byte[8];
try {
in.read(typeBytes);
in.read(xBytes);
in.read(yBytes);
} catch (Exception e) {
throw new HibernateException("Can't parse point column!", e);
}
var type = ByteBuffer.wrap(typeBytes)
.order(order);
if (type.getInt() != 1) {
throw new HibernateException("Not a point!");
}
var x = ByteBuffer.wrap(xBytes)
.order(order);
var y = ByteBuffer.wrap(yBytes)
.order(order);
return new Vector2((float) x.getDouble(), (float) y.getDouble());
And the only thing left to do was to make a custom type so hibernate had something to parse it.