java - 多维数组映射<Integer, Map<Integer,Entity>> 或map<Entity1,Entity2>

标签 java arrays hibernate jpa collections

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

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 .

关于java - 多维数组映射<Integer, Map<Integer,Entity>> 或map<Entity1,Entity2>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19987563/

相关文章:

Javascript 数组 - 合并多个数组帮助

mysql - 如何将以下 sql 查询转换为 HQL 查询

java - 新行中的 PDF 格式的 ArrayList<String>

java - 推特认证后的回调

python - array.array 与 numpy.array

java - 如何将 Hibernate NamingStrategy 迁移到(隐式|物理)NamingStrategy?文档在哪里?

java - 如何在 Hibernate 中使用具有 ManyToMany 关联的嵌套对象正确分页?

java - 有什么好的基于Java的Master-Slave通信机制?

java - servlet 过滤器重写 URL

ruby - 根据字典匹配和替换 Ruby 数组