我目前正在构建一款瓷砖游戏。在我原来的“游戏”中,我的棋盘有一个

Tile tiles[][];  

现在我想用 JPA 来持久化这个,据我所知,你不能持久化多维数组。

所以我想改变它。我可以为要获取的位置创建一个点类

map<Point,Tile>

我相信我会得到类似的东西:

@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; 
 
  ... 
} 

或者我可以使用

map<Integer, Map<Integer, Tile>>

(不知道如何在 JPA 中执行此操作)

我走在正确的轨道上吗?最好的方法是什么(性能等......)还是我想太多了?

谢谢大家。

请您参考如下方法:

Hibernate 类型项目

hibernate-types项目允许您为 JPA 和 Hibernate 实体属性保留多维数组。

因此,如果您需要保留 Tile[][] 数组,您可以轻松实现,而无需将其转换为 Map

现在,我有一个非常相似的示例,其中包含用于飞机座位预订系统的二维数组。

数据库表

因此,假设您有以下plane数据库表:

CREATE TABLE plane ( 
    id INT8 NOT NULL, 
    name VARCHAR(255), 
    seat_grid seat_status[][], 
    PRIMARY KEY (id) 
) 

其中 seat_status 是 PostgreSQL 枚举:

CREATE TYPE seat_status 
AS ENUM ( 
    'UNRESERVED', 
    'RESERVED', 
    'BLOCKED' 
); 

JPA 实体

您可以按如下方式映射plane数据库表:

@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]; 
    } 
} 

因此,您需要声明要使用的适当的 Hibernate 类型。对于枚举,您需要使用EnumArrayType:

@TypeDef( 
    name = "seat_status_array", 
    typeClass = EnumArrayType.class 
) 

@Type 注解允许您将参数传递给 Hibernate Type,就像 SQL 数组类一样:

@Type( 
    type = "seat_status_array", 
    parameters = @org.hibernate.annotations.Parameter( 
        name = "sql_array_type", 
        value = "seat_status" 
    ) 
) 

测试时间

现在,当您保留以下 Post 实体时:

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 将发出正确的 SQL INSERT 语句:

INSERT INTO plane ( 
    name, 
    seat_grid, 
    id 
) 
VALUES ( 
    'ATR-42', 
    { 
        {"BLOCKED", "BLOCKED", "BLOCKED", "BLOCKED"}, 
        {"UNRESERVED", "UNRESERVED", "RESERVED", "UNRESERVED"}, 
        {"RESERVED", "RESERVED", "RESERVED", "RESERVED"} 
    }, 
    1 
) 

并且,在获取实体时,一切都按预期工作:

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')); 

有关此主题的更多详细信息,请查看 this article .


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!