this articleで説明したように、Hibernateを使用してJSONオブジェクトを永続化するのは非常に簡単です。 、詳細情報については
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
をhibernate-types open-source projectをチェックアウト:
あなたは、単に次の依存関係を使用してMavenの中央を経由して にそれらを得ることができ、手動ですべてのこれらのタイプを作成する必要はありません。
ここで、そのすべての仕組みを説明します。
次のエンティティを持っていると仮定すると:
@Entity(name = "Book")
@Table(name = "book")
@TypeDef(
name = "jsonb-node",
typeClass = JsonNodeBinaryType.class
)
public class Book {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String isbn;
@Type(type = "jsonb-node")
@Column(columnDefinition = "jsonb")
private JsonNode properties;
//Getters and setters omitted for brevity
}
お知らせ上記のコードでは二つのこと:
@TypeDef
がによって処理される新しいカスタム休止タイプ、jsonb-node
を定義するために使用されますJsonNodeBinaryType
properties
属性はjsonb
の列タイプを持ち、それはジャクソンJsonNode
JsonNodeBinaryType
このように実装されている次のよう
public class JsonNodeBinaryType
extends AbstractSingleColumnStandardBasicType<JsonNode> {
public JsonNodeBinaryType() {
super(
JsonBinarySqlTypeDescriptor.INSTANCE,
JsonNodeTypeDescriptor.INSTANCE
);
}
public String getName() {
return "jsonb-node";
}
}
JsonBinarySqlTypeDescriptor
に見える:
public class JsonBinarySqlTypeDescriptor
extends AbstractJsonSqlTypeDescriptor {
public static final JsonBinarySqlTypeDescriptor INSTANCE =
new JsonBinarySqlTypeDescriptor();
@Override
public <X> ValueBinder<X> getBinder(
final JavaTypeDescriptor<X> javaTypeDescriptor
) {
return new BasicBinder<X>(javaTypeDescriptor, this) {
@Override
protected void doBind(
PreparedStatement st,
X value,
int index,
WrapperOptions options
) throws SQLException {
st.setObject(
index,
javaTypeDescriptor.unwrap(
value,
JsonNode.class,
options
),
getSqlType()
);
}
@Override
protected void doBind(
CallableStatement st,
X value,
String name,
WrapperOptions options
) throws SQLException {
st.setObject(
name,
javaTypeDescriptor.unwrap(
value,
JsonNode.class,
options
),
getSqlType()
);
}
};
}
}
AbstractJsonSqlTypeDescriptorソースコードはthis articleで可視化することができます。
次に、JsonNodeTypeDescriptor
パラメータを結合または根底ResultSet
からJSONオブジェクトからフェッチ中に、基礎となるJDBCドライバによって使用されるかもしれない種々の表現にJsonNode
を変換する責任があります。
public class JsonNodeTypeDescriptor
extends AbstractTypeDescriptor<JsonNode> {
public static final JsonNodeTypeDescriptor INSTANCE =
new JsonNodeTypeDescriptor();
public JsonNodeTypeDescriptor() {
super(
JsonNode.class,
new MutableMutabilityPlan<JsonNode>() {
@Override
protected JsonNode deepCopyNotNull(
JsonNode value
) {
return JacksonUtil.clone(value);
}
}
);
}
@Override
public boolean areEqual(JsonNode one, JsonNode another) {
if (one == another) {
return true;
}
if (one == null || another == null) {
return false;
}
return
JacksonUtil.toJsonNode(
JacksonUtil.toString(one)
).equals(
JacksonUtil.toJsonNode(
JacksonUtil.toString(another)
)
);
}
@Override
public String toString(JsonNode value) {
return JacksonUtil.toString(value);
}
@Override
public JsonNode fromString(String string) {
return JacksonUtil.toJsonNode(string);
}
@SuppressWarnings({ "unchecked" })
@Override
public <X> X unwrap(
JsonNode value,
Class<X> type,
WrapperOptions options
) {
if (value == null) {
return null;
}
if (String.class.isAssignableFrom(type)) {
return (X) toString(value);
}
if (JsonNode.class.isAssignableFrom(type)) {
return (X) JacksonUtil.toJsonNode(toString(value));
}
throw unknownUnwrap(type);
}
@Override
public <X> JsonNode wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
return fromString(value.toString());
}
}
これだけです!
さて、あなたはエンティティを保存する場合:
Book book = new Book();
book.setIsbn("978-9730228236");
book.setProperties(
JacksonUtil.toJsonNode(
"{" +
" \"title\": \"High-Performance Java Persistence\"," +
" \"author\": \"Vlad Mihalcea\"," +
" \"publisher\": \"Amazon\"," +
" \"price\": 44.99" +
"}"
)
);
entityManager.persist(book);
Hibernateは、次のSQL文を生成するために起こっている
:
INSERT INTO
book
(
isbn,
properties,
id
)
VALUES
(
'978-9730228236',
'{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99}',
1
)
をそして、あなたはまた戻ってそれをロードし、それを変更することができます
を
Session session = entityManager.unwrap(Session.class);
Book book = session
.bySimpleNaturalId(Book.class)
.load("978-9730228236");
LOGGER.info("Book details: {}", book.getProperties());
book.setProperties(
JacksonUtil.toJsonNode(
"{" +
" \"title\": \"High-Performance Java Persistence\"," +
" \"author\": \"Vlad Mihalcea\"," +
" \"publisher\": \"Amazon\"," +
" \"price\": 44.99," +
" \"url\": \"https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/\"" +
"}"
)
);
あなたのためのUPDATE
の声明を読んで休止状態:
SELECT b.id AS id1_0_
FROM book b
WHERE b.isbn = '978-9730228236'
SELECT b.id AS id1_0_0_ ,
b.isbn AS isbn2_0_0_ ,
b.properties AS properti3_0_0_
FROM book b
WHERE b.id = 1
-- Book details: {"price":44.99,"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon"}
UPDATE
book
SET
properties = '{"title":"High-Performance Java Persistence","author":"Vlad Mihalcea","publisher":"Amazon","price":44.99,"url":"https://www.amazon.com/High-Performance-Java-Persistence-Vlad-Mihalcea/dp/973022823X/"}'
WHERE
id = 1
GitHubで利用可能なすべてのコード。
"1つのレコードに全体のHashMap" ??または、単一のdbトランザクション内のハッシュマップ全体? –
私はシングルレコードを意味しました。 – Fawzan