çããããã«ã¡ã¯ã Hibernate Reactiveã¯ã«ã¹ã¿ã UserTypeããµããŒãããŠããŸããïŒ Postgres JSONB Typeã䜿çšãããã®ã§ãHibernateã®AbstractSingleColumnStandardBasicTypeã«åºã¥ããŠã«ã¹ã¿ã ã¿ã€ããæ§ç¯ãã次ã®ã©ã€ãã©ãªhttps://github.com/vladmihalcea/hibernate-typesã䜿çšããŠããŸããã æ®å¿µãªãããHibernateããHibernate Reactiveã«ç§»è¡ããã ãã§ããããã®ã¿ã€ãã䜿çšããåã¯ãšã³ãã£ãã£å ã§åžžã«nullã«ãªããŸãã å¥ã®æ¹æ³ãšããŠãHibernateã®UserTypeã§JSONBPostgresãµããŒããæ§ç¯ãããã®èšäºãèŠã€ããŸããã çŸåšãã«ã¹ã¿ã ã¿ã€ãã®å®çŸ©ãšHibernate Reactiveã®äœ¿çšã«é¢ããŠæ¢ç¥ã®å¶éã¯ãããŸããïŒ
ããã«ã¡ã¯ã UserType
ã€ã³ã¿ãŒãã§ã€ã¹ã¯JDBCã«é¢é£ä»ããããŠããããããã¹ãããŸãã
代ããã«ãç§ã®èãã¯ã人ã ãJPAã³ã³ããŒã¿ãŒã䜿çšã§ãããšãããã®ã§ããã ç§ã¯ããããã¹ãããŸããããããŠãããæ©èœããããšã確èªããŸããã ããªãã¯ãããè©ŠããŸãããïŒ
UserTypeã䜿çšããŠç°¡åãªãã¹ããè©ŠããŸããããã¯ãšãªã®å®è¡æã«PgClientãäŸå€ãã¹ããŒãããããæ©èœããªãããã§ãã
UserTypeã䜿çšããŠç°¡åãªãã¹ããè©ŠããŸããããã¯ãšãªã®å®è¡æã«PgClientãäŸå€ãã¹ããŒãããããæ©èœããªãããã§ãã
ããããããã¯ãåœã®JDBCã¬ã€ã€ãŒãäžå®å šã§ããããšãåå ã§ããå¯èœæ§ããããŸãã ïŒããã€ãã®å®è£ ãããŠããªãã¡ãœãããïŒ
æ確ã«ããããã«ãvladã©ã€ãã©ãªã䜿çšããŠäŸãè©ŠããŸããã
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@Entity(name="GuineaPig")
@Table(name="Pig")
public static class GuineaPig {
<strong i="6">@Id</strong>
private Integer id;
private String name;
@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private Location location;
ããã¯ãšã©ãŒã§ãïŒ
Caused by: io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[0] with class = [com.fasterxml.jackson.databind.node.ObjectNode] and value = [{"country":"UK","city":"Gotham"}] can not be coerced to the expected class = [java.lang.Object] for encoding.
ãªã¢ã¯ãã£ãpgã¯ã©ã€ã¢ã³ãã¯å¥ã®ã¿ã€ãã䜿çšããŠJSONã«å€æããŠããããã§ãã
@gavinking pg-clientã¿ã€ãã®ããçš®ã®ãããã³ã°ããµããŒãããå¿ èŠããã
JSON (io.reactiverse.pgclient.data.Json)
JSONB (io.reactiverse.pgclient.data.Json)
POINT (io.reactiverse.pgclient.data.Point)
LINE (io.reactiverse.pgclient.data.Line)
LSEG (io.reactiverse.pgclient.data.LineSegment)
BOX (io.reactiverse.pgclient.data.Box)
PATH (io.reactiverse.pgclient.data.Path)
POLYGON (io.reactiverse.pgclient.data.Polygon)
CIRCLE (io.reactiverse.pgclient.data.Circle)
ã¯ã©ã€ã¢ã³ãã¯ã¿ã€ãio.reactiverse.pgclient.data.Json
ãªããžã§ã¯ããæåŸ
ããŠãããšæããŸãã UserType
æ£ããåŠçããŠããããã§ãã
ããããããã§ãç§ã¯äžèšã®ã³ã¡ã³ãã§ãããæå³ããŸããã ç§ãã¡ã®JDBCã¢ããã¿ãŒã¯ãJDBCã®å®å šãªå®è£ ã«ããè¿ã¥ããŠãããã決ããŠãããªãããšã¯ãªãã ãããšç§ã¯èããŠããŸãã ç¹ã«ãããããšããŸããã¯ããªJDBCã¿ã€ãã®å ŽåãVert.xAPIãšã®éã§ãããã³ã°ããã®ã¯éåžžã«é£ããå ŽåããããŸãã
pg-clientã¿ã€ãã®ããçš®ã®ãããã³ã°ããµããŒãããå¿ èŠããããŸããïŒ
ãŸãã確ãã«ããããåççã«ç°¡åã§ããã°ã
ãããããã§ãªãå Žåã¯ãããããUserType
ã¯ããã§ã¯é©åãªæœè±¡åã§ã¯ãªãããšãèæ
®ããå¥ã®ã¢ãããŒããæ¢ãå¿
èŠããããŸãã
ã€ãŸããæ¢åã®UserType
ãæãããããšãäœãããã«æ©èœãããããšãã§ããç¯å²ã§ã確ãã«ãããããæ©èœãããŸãããã 移è¡ã容æã«ãªããŸãã ããããããã§å®éã«äœãå¯èœãã«ã€ããŠãããã«å¶éã«ã¶ã€ããå¯èœæ§ããããšæããŸãã
ããšã§èŠãŠã¿ãŸã
ããšã§èŠãŠã¿ãŸã
æåã®ã¹ããããšããŠãåºæ¬çãªæŠå¿µãæ©èœããããšã確èªããããã«ã掟æãªããŒã¿ããŒã¹ã¿ã€ãã䜿çšããªãå®å
šã«åçŽãªUserType
ãã¹ããè¿œå ããå¿
èŠããããŸãïŒãªãæ©èœããªãã®ãããããŸããïŒ ïŒã
@gavinkingãããHibernateã¿ã€ãã©ã€ãã©ãªãšäžç·ã«Hibernateã䜿çšããŠãããããã³ã³ããŒã¿ãŒã¯ãŸã ãã¹ãããŠããŸããã ããããã³ã³ããŒã¿ãŒã䜿çšãããšããææ¡ã¯ãæçµçã«ãPostgresJSONBã¿ã€ãã§ã¯ãªããã¬ãŒã³ãªPostgresText / VarcharãDBã«é 眮ããããšãæå³ããŸãã
@gavinkingãããHibernateã¿ã€ãã©ã€ãã©ãªãšäžç·ã«Hibernateã䜿çšããŠãããããã³ã³ããŒã¿ãŒã¯ãŸã ãã¹ãããŠããŸããã ããããã³ã³ããŒã¿ãŒã䜿çšãããšããææ¡ã¯ãæçµçã«ãPostgresJSONBã¿ã€ãã§ã¯ãªããã¬ãŒã³ãªPostgresText / VarcharãDBã«é 眮ããããšãæå³ããŸãã
æ確ã«ããããã«ïŒããªãã¯ããªããJavaãŸãã¯ããŒã¿ããŒã¹ã«ã©ããªã¿ã€ããæã£ãŠãããã«ã€ããŠå¿é ããŠããŸããïŒ ããã«ã¯2ã€ã®ç°ãªããã®ããããŸãã
JSONB
ã䜿çšããããšã§ãããååãšããŠããã©ã€ããŒã¯æååããã®åã«ééçã«å€æã§ãããšæããŸããã ïŒããããªããç§ã¯è©ŠããããšããªããïŒio.reactiverse.pgclient.data.Json
ã䜿çšããããšã§ãã ããã¯ãŸã£ããå¥ã®åé¡ã§ãããå®éã«ã¯UserType
ãããªãã®ãå¿
èŠã«ãªããŸãã@gavinking
Postgres JSONB
ã¿ã€ãã䜿çšãããã Hibernateã§ã¯çŽæ¥ãµããŒããããŠããªããšæããŸãã ãã®ãããç§ã¯ãã®https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/ã«äŸåããŸããã ãŸãã¯ãããšãã°ããã®https://thorben-janssen.com/persist-postgresqls-jsonb-data-type-hibernate/ã§ã¯ãã¬ã€ãã¯UserTypeã䜿çšããŸãã
確ãã«ç§ã¯ãããç解ããŠããŸãããJava String
ãã¿ã€ãJSONB
åã«ãããã³ã°ãããããªæ¬åœã«åçŽãªããšãè©Šã¿ãŸãããïŒ ãããããŸããã£ããããã§ååã§ããããïŒ
@gavinkingãããããŸã è©ŠããŠããŸããã ã¯ããããã§ååã§ãããã ãšã³ãã£ãã£ãDBã«æ¿å ¥ããåã«ãJSONãªããžã§ã¯ããJSONæååã«å€æããå¿ èŠããããŸãã
ãããªããVert.xã¯ã©ã€ã¢ã³ãããã§ã«ãã®åå€æããµããŒãããŠããå¯èœæ§ããããŸããè©ŠããŠã¿ãå¿ èŠããããŸããããµããŒãããŠããªãå Žåã§ãããããããµããŒãããå¿ èŠããããšæããŸãã
@DavideDããã®ã¹ããŒã¿ã¹ã¯äœã§ããïŒ ããã詳ããèŠãŠã»ããã§ããïŒ
ç§ã¯èéã«ãªããŸããã æéãããã°ãæ°è»œã«åãçµãã§ãã ããã
ïŒ301ã§ã UserType
ãHRã§æ©èœããããšã瀺ããã¹ããè¿œå ããŸãããå°ãªããšãã PreparedStatement
ããã³ResultSet
ã¢ããã¿ãŒãJDBCã®å¿ å®ãªå®è£
ã§ããç¯å²ã§ïŒããã¯ç¹ã«å€§ããªç¯å²ã§ã¯ãããŸããïŒã
@gavinking pg-clientã¿ã€ãã®ããçš®ã®ãããã³ã°ããµããŒãããå¿ èŠããã
JSON (io.reactiverse.pgclient.data.Json) JSONB (io.reactiverse.pgclient.data.Json) POINT (io.reactiverse.pgclient.data.Point) LINE (io.reactiverse.pgclient.data.Line) LSEG (io.reactiverse.pgclient.data.LineSegment) BOX (io.reactiverse.pgclient.data.Box) PATH (io.reactiverse.pgclient.data.Path) POLYGON (io.reactiverse.pgclient.data.Polygon) CIRCLE (io.reactiverse.pgclient.data.Circle)
ãããã£ãŠãåé¡ã¯æ¬¡ã®ããã«ãªããŸããPostgreSQLã¯ã©ã€ã¢ã³ããžã®åŒ·ãäŸåé¢ä¿ãäœæããã«ãJDBCã¢ããã¿ãŒã®getObject()
ãšsetObject()
ã§ãããã®ã¿ã€ãããµããŒãã§ããããã«ããããšã¯ã§ããŸããïŒ
次ã®ãããªãã®ãæã€ããšã¯å¯èœã§ããããïŒ
@Type(type="passthrough")
Circle circle
ããã¯å€æãè¡ããŸããããå€ããã®ãŸãŸæž¡ããŸããïŒ
ãããã£ãŠãåé¡ã¯æ¬¡ã®ããã«ãªããŸããPostgreSQLã¯ã©ã€ã¢ã³ããžã®åŒ·ãäŸåé¢ä¿ãäœæããã«ãJDBCã¢ããã¿ãŒã®
getObject()
ãšsetObject()
ã§ãããã®ã¿ã€ãããµããŒãã§ããããã«ããããšã¯ã§ããŸããïŒ
ããŠãç§ã¯ãããè©ŠããŸããããPostgresãŸãã¯MySQLã§io.vertx.core.json.JsonObject
ãåŠçããããã«ãå®éã«ã¯ç¹å¥ãªããšãããå¿
èŠã¯ãªãããã§ãã ããªãã ã䜿çšããããšãã§ããŸãgetObject()
/ setObject()
ããªãããUserType
ã
ããã¯æ©èœããŸãïŒ
public class Json implements UserType {
<strong i="15">@Override</strong>
public int[] sqlTypes() {
return new int[] {Types.OTHER};
}
<strong i="16">@Override</strong>
public Class returnedClass() {
return JsonObject.class;
}
<strong i="17">@Override</strong>
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x,y);
}
<strong i="18">@Override</strong>
public int hashCode(Object x) throws HibernateException {
return Objects.hashCode(x);
}
<strong i="19">@Override</strong>
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
return rs.getObject(names[0]);
}
<strong i="20">@Override</strong>
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value==null) {
st.setNull(index, Types.OTHER);
}
else {
st.setObject(index, value);
}
}
...
}
次ã®ãããªãã®ãæã€ããšã¯å¯èœã§ããããïŒ
@Type(type="passthrough") Circle circle
ããã¯å€æãè¡ããŸããããå€ããã®ãŸãŸæž¡ããŸããïŒ
ã¯ãããããããŸãããã§ãããã
54434c94b3ff57261fd905abaeb25961b2ed285cãåç §ããŠãã ããã
ãã®åé¡ã解決ã§ãããšæããŸãã
ããšãã°io.reactiverse.pgclient.data.Circle
ãããªä»ã®ã¿ã€ãã¯ã©ãã§ããïŒ
@akoufaã¯ãå ã®è³ªåã«å¯Ÿããå ·äœçãªåçãæäŸããŸãã
Hibernate Reactiveã¯ã«ã¹ã¿ã
UserTypes
ãµããŒãããŠããŸããïŒ
çãã¯ã€ãšã¹ã§ãïŒ
ãã ããJDBCã«ãã䌌ããã®ãUserType
ã«å
¬éããŠããå
éšã§ã¯JDBCæ¥ç¶ã¯ãªãããŸã£ããç°ãªãéããããã³ã°ããŒã¿ããŒã¹ã¯ã©ã€ã¢ã³ãã§ããããšã«æ³šæããå¿
èŠããããŸãã ãã®ãããåã«æ©èœããªããã®ããããŸãã
ç§ã¯æ¬¡ã®ã©ã€ãã©ãªã䜿çšããŠããŸããhttps://github.com/vladmihalcea/hibernate-types
ã§ããããããã«ã€ããŠã¯ããªãçŸå®çã§ããå¿
èŠããããšæããŸãã äžèšã®ã©ã€ãã©ãªã¯ããã®ããã€ãã®äžæ¹ã§ãJDBCã§åäœããããã«æžãããŠããUserType
ä»ã®äººã¯ããªãã ãããsããããããªãäœåã
å¥ã®æ¹æ³ãšããŠãHibernateã®
UserType
JSONBPostgresãµããŒããæ§ç¯ãããã®èšäºãèŠã€ããŸããã
ãã¹ãã¹ã€ãŒãã§ãããã©ã®ããã«å®è£
ããããèŠãŠãã ããã åºæ¬çãªèãæ¹ã¯ã setObject()
åŒã³åºãã ãã§ãVert.x JsonObject
ãVert.xPostgreSQLãŸãã¯MySQLã¯ã©ã€ã¢ã³ãã«æž¡ãå¿
èŠããããšããããšã§ãã
ããšãã°
io.reactiverse.pgclient.data.Circle
ãããªä»ã®ã¿ã€ãã¯ã©ãã§ããïŒ
ç§ã¯ãã¹ãããŸããã§ããããåãååŒã«ãªãã¯ãã§ãã
ã¡ãªã¿ã«ã io.reactiverse.pgclient.data
ã¯æ»ãã§ããŸãã 以åã®ããŒãžã§ã³ã®ã¯ã©ã€ã¢ã³ãçšã§ãã ããã¯ããªããèŠãã¹ããã®ã§ã¯ãããŸããã
ã¿ã€ãã®çŸåšã®ãªã¹ãã¯æ¬¡ã®ãšããã§ãã
https://vertx.io/docs/vertx-pg-client/java/#_postgresql_type_mapping
ç§ã¯ãããç解ããŠããŸãããJavaæååãJSONBåã®åã«ãããã³ã°ãããããªæ¬åœã«åçŽãªããšãè©Šã¿ãŸãããïŒ
..ã
ãããªããVert.xã¯ã©ã€ã¢ã³ãããã§ã«ãã®åå€æããµããŒãããŠããå¯èœæ§ããããŸããè©ŠããŠã¿ãå¿ èŠããããŸããããµããŒãããŠããªãå Žåã§ãããããããµããŒãããå¿ èŠããããšæããŸãã
äžã§ãªã³ã¯ããããã¥ã¡ã³ãã«ãããšãããã¯æ©èœããŸãã JSONB
ã¿ã€ãã®åã«æŽæ°ãçŽæ¥æžã蟌ãããšããã¹ãããŸããããæ©èœããŸããã
ãããã£ãŠãååãšããŠãå¿
èŠããªããã°JsonObject
ããããå¿
èŠã¯ãããŸããã ïŒãããããã£ãšãããã§ããïŒ
確ãã«ãä»ã®ç¹å®ã®ã¿ã€ãã®ããã€ãã®ãã¹ããè¿œå ã§ããŸããïŒ ç·ãåã®ããã«ã ãããã³ã°ãã©ã®ããã«èŠãããã瀺ãããšãã§ããããã«
ããïŒ
https://github.com/vladmihalcea/hibernate-typesã®ãããªhibernate-reactiveã§äœ¿çšããã©ã€ãã©ãªãèŠãããšããããŸããïŒ
ããããŸã ååšããªãå Žåã¯ããããžã§ã¯ãçšã«äœããæ§ç¯ããããšæããŸãïŒquarkusã䜿çšïŒã postgresã§ã¯å€ãã®JSONåã䜿çšããŠããŸãã
ããããç§ã¯ãããééãããã©ããããããŸãããã hibernate-reactive
ã¯UserType
ã€ã³ã¿ãŒãã§ã€ã¹ããå®è£
ããããšã«ãã£ãŠã®ã¿ã«ã¹ã¿ã ã¿ã€ããèš±å¯ããŸããïŒ ïŒhttp://hibernate.org/reactive/documentation/1.0/reference/html_single/#_custom_typesïŒ
@ AlexandreGuidin ã @ gavinkingã¯ä»¥åã®ã³ã¡ã³ãã®1ã€ã§ããªãã®è³ªåã«ãã§ã«çããŠãããšæããŸãïŒ https ïŒ
ããããäœãã足ããªãå Žåã¯ãããã«è³ªåãããŠãã ããã