2

How can I convert a 2d char array from my Postgres DB to a native Java char[][]? This is my attempt based on this answer:

import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;

public class GameMapper implements ResultSetMapper<Game>{
    public Game map(int index, ResultSet resultSet, StatementContext statementContext) throws SQLException
    {
        Array board = resultSet.getArray("BOARD");
        return new Game(resultSet.getInt("ID"),
                        resultSet.getInt("WHOSE_TURN"),
                        resultSet.getInt("WINNER"),
                        (char[][]) board.getArray());
    }
}

Data class:

public class Game {
    protected int id; 
    protected int whoseTurn;
    protected int winner;
    protected char[][] board;

    public Game(int id, int turn, int winner, char[][] board ) {
        this.id=id;
        this.whoseTurn=turn;
        this.winner=winner;
        this.board=board;
    }

    @JsonProperty
    public int getId() {
        return id;
    }

    @JsonInclude(Include.NON_NULL)
    public int getWhoseTurn() {
        return whoseTurn;
    }

    @JsonInclude(Include.NON_NULL)
    public int getWinner() {
        return winner;
    }

    public char[][] getBoard() {
        return board;
    }   
}

DAO:

@RegisterMapper(GameMapper.class)
public interface GameDAO {

    @SqlUpdate("create table if not exists GAMES (ID integer, WHOSE_TURN varchar(10), WINNER varchar(10), BOARD char(1)[][])")
    void createTableIfNotExists();

    @SqlUpdate("insert into GAMES (ID, WHOSE_TURN, WINNER, BOARD) values (:id, :whoseTurn, :winner, :board)")
    void insert(@BindBean Game game);
}

But this results in a cast error:

java.lang.ClassCastException: [[Ljava.lang.String; cannot be cast to [[C

Do I need to use ResultSet instead?

4

2 回答 2

4

[[Ljava.lang.String; 不能转换为 [[C

是时候了解 Java 数组类型名称的含义了

[array-of。array-of array-of 也是如此[[,即两个类型名称都是二维数组。

L表示引用类型,后跟类名。

C是原始类型char

所以在这里,我们看到您正在尝试将二维数组java.lang.String转换为 的二维数组char。这没有任何意义。看起来 JDBI 将 Java 数据类型映射char到 SQL 字符串类型,例如characteror character varying(通过检查数据库中的表来验证)。如果是这样,JDBC 驱动程序将从数据库中返回java.lang.String.

因此,您需要覆盖该映射以使用数据库数据类型"char"(单个字符),或者更简单地说,断言字符串是一个字符长并将它们解压缩为一个字符。所以你必须复制数组。

于 2015-10-12T06:16:37.493 回答
1

我查看了 postgres JDBC 驱动程序。如果列类型是 CHAR 或 VARCHAR,它会尝试将其转换为字符串数组。

    else if (type == Types.CHAR || type == Types.VARCHAR)
    {
        Object[] oa = null;
        ret = oa = (dims > 1 ? (Object[]) java.lang.reflect.Array.newInstance(String.class, dimsLength) : new String[count]);
    }

所以你会得到二维字符串数组。您需要在映射器中将其转换为 char[][]。

于 2015-10-12T09:43:38.857 回答