I'm currently building an tile game. In my original "game" my board has an
Tile tiles[][];
Now I want to persist this with JPA and for so far as I know you can't persist multidimensional array's.
So I was looking in to change it. I can create a point class for the location to get
map<Point,Tile>
I believe I would get something like:
@Entity
public class Board{
@Id
private long id;
...
@OneToMany(mappedBy="board")
@MapKeyJoinColumn(name="POINT_ID")
private Map<Point, Tile> tiles;
...
}
@Entity
public class Tile{
@Id
private long id;
...
@ManyToOne
private Board board;
...
}
@Entity
public class Point{
@Id
private long id;
...
@Column(name = "ROW")
private int row;
@Column(name = "COL")
private int col;
...
}
or I could use
map<Integer, Map<Integer, Tile>>
(No idea how to do this in JPA)
Am I on the right track and what would be the best way (performance, etc ...) or am I overthinking this?
Thx all.
The hibernate-types project allows you to persist multidimensional arrays for your JPA and Hibernate entity attributes.
So, if you need to persist the Tile[][]
array, you can easily to that without having to transform that to a Map
.
Now, I have a very similar example with a two-dimensional array for a plane seat reservation system.
So, assuming you have the following plane
database table:
CREATE TABLE plane (
id INT8 NOT NULL,
name VARCHAR(255),
seat_grid seat_status[][],
PRIMARY KEY (id)
)
Where the seat_status
is a PostgreSQL enum:
CREATE TYPE seat_status
AS ENUM (
'UNRESERVED',
'RESERVED',
'BLOCKED'
);
You can map the plane
database table as follows:
@Entity(name = "Plane")
@Table(name = "plane")
@TypeDef(
name = "seat_status_array",
typeClass = EnumArrayType.class
)
public static class Plane {
@Id
private Long id;
private String name;
@Type(
type = "seat_status_array",
parameters = @org.hibernate.annotations.Parameter(
name = "sql_array_type",
value = "seat_status"
)
)
@Column(
name = "seat_grid",
columnDefinition = "seat_status[][]"
)
private SeatStatus[][] seatGrid;
//Getters and setters omitted for brevity
public SeatStatus getSeatStatus(int row, char letter) {
return seatGrid[row - 1][letter - 65];
}
}
So, you need to declare the appropriate Hibernate Type to use. For enums, you need to use the EnumArrayType
:
@TypeDef(
name = "seat_status_array",
typeClass = EnumArrayType.class
)
The @Type
annotation allows you to pass parameters to the Hibernate Type, like the SQL array class:
@Type(
type = "seat_status_array",
parameters = @org.hibernate.annotations.Parameter(
name = "sql_array_type",
value = "seat_status"
)
)
Now, when you persist the following Post
entity:
entityManager.persist(
new Plane()
.setId(1L)
.setName("ATR-42")
.setSeatGrid(
new SeatStatus[][] {
{
SeatStatus.BLOCKED, SeatStatus.BLOCKED,
SeatStatus.BLOCKED, SeatStatus.BLOCKED
},
{
SeatStatus.UNRESERVED, SeatStatus.UNRESERVED,
SeatStatus.RESERVED, SeatStatus.UNRESERVED
},
{
SeatStatus.RESERVED, SeatStatus.RESERVED,
SeatStatus.RESERVED, SeatStatus.RESERVED
}
}
)
);
Hibernate will issue the proper SQL INSERT statement:
INSERT INTO plane (
name,
seat_grid,
id
)
VALUES (
'ATR-42',
{
{"BLOCKED", "BLOCKED", "BLOCKED", "BLOCKED"},
{"UNRESERVED", "UNRESERVED", "RESERVED", "UNRESERVED"},
{"RESERVED", "RESERVED", "RESERVED", "RESERVED"}
},
1
)
And, when fetching the entity, everything works as expected:
Plane plane = entityManager.find(Plane.class, 1L);
assertEquals("ATR-42", plane.getName());
assertEquals(SeatStatus.BLOCKED, plane.getSeatStatus(1, 'A'));
assertEquals(SeatStatus.BLOCKED, plane.getSeatStatus(1, 'B'));
assertEquals(SeatStatus.BLOCKED, plane.getSeatStatus(1, 'C'));
assertEquals(SeatStatus.BLOCKED, plane.getSeatStatus(1, 'D'));
assertEquals(SeatStatus.UNRESERVED, plane.getSeatStatus(2, 'A'));
assertEquals(SeatStatus.UNRESERVED, plane.getSeatStatus(2, 'B'));
assertEquals(SeatStatus.RESERVED, plane.getSeatStatus(2, 'C'));
assertEquals(SeatStatus.UNRESERVED, plane.getSeatStatus(2, 'D'));
For more details about this topic, check out this article .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.