LoginSignup
4
8

More than 5 years have passed since last update.

JavaからPostgreSQLのデータ型(jsonb)を使う

Last updated at Posted at 2017-03-26

PostgreSQL特有のデータ側をPythonから利用する方法について調べたので記録しておきます。

ここで紹介するのはjsonb型についてです。

この内容は、第51回 長岡IT開発者勉強会で発表した内容の抜粋です。スライドはこちらです。

Python版はこちらです。

PostgreSQLをJavaから利用する

利用方法

アプリケーションからPostgreSQLを使用するときには、
JDBC API経由で使う。JDBC APIは仕様でインターフェースのみとなり実装としてJDBC Driver for PostgreSQLがある。これはPostgreSQL公式のJDBCドライバ。

JDBC経由で様々なDBアクセス用ライブラリが存在するが、今回はJava標準の永続化仕様としてJPAを使用する例を考える。JPAも仕様でありインターフェースが用意されてある。実装の一つとしてEclipseLinkがある。

ソースコード

jsonbを利用する

id info
1 {"a": 100, "b": "Hello"}
2 {"a": 200, "b": "World"}
CREATE TABLE json_test(
  id integer,
  info jsonb
)

低レベルAPI(JDBC)からjsonbの利用

SELECT

resultSet.getString("info");
// {"a": 100, "b": "Hello"}

jsonの列を取得し、getStringすることでJSON文字列を取得可能。

INSERT (1)

import org.postgresql.util.PGobject;

PGobject pgobj =new PGobject();
pgobj.setValue(json_string); //json文字列
pgobj.setType("jsonb");

preparedStatement.setObject(1, pgobj);

JDBC APIにはJSON型はない。JDBCの提供するインターフェース経由で使うのが普通だが、PostgreSQL提供のドライバの機能を使うしかない。共通ライブラリなど限定された箇所で使うべき。

INSERT (2)

PreparedStatement ps =conn.prepareStatement(
 "INSERT INTO json_test(info) VALUES(jsonb(?))");

ps.setString(1, json_string);  //json文字列

JSON文字列としてパラメータをセットし、SQL文でjsonbにキャストするパターン。
文字列としてsetStringするので、標準APIのみで可能。

高レベルAPI(JPA)からjsonbの利用

SELECT / INSERT

@Entity
@Table(name = "json_test")
public class JsonTest implements Serializable {
    // ... 中略 ...

    @Column(name = "info")
    @Convert(converter = JsonbConverter.class)
    private String info;
...

JPAというORマッパー的な永続化機能。JPAの仕様でConverterという仕組みが用意されている。
Converterを作成し、Java型 <=> SQL型の相互変換を定義すれば、アノテーションで列定義に使用できる。

JsonbConverterの実装

/**
@Converter
public class JsonbConverter implements AttributeConverter<String, PGobject>{

    /**
     * String-Pgobjectへの変換
     * @param x
     * @return 
     */
    @Override
    public PGobject convertToDatabaseColumn(String x) {
        PGobject pgobject =new PGobject();
        pgobject.setType("jsonb");
        try {
            pgobject.setValue(x);
        } catch (SQLException ex) {
            Logger.getLogger(JsonbConverter.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }
        return pgobject;
    }

    @Override
    /**
     * Pgobject-Stringへの変換
     * @param y
     * @return 
     */
    public String convertToEntityAttribute(PGobject y) {
        return y.getValue();
    }

}

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8