ZonedDateTime
çšã®çµã¿èŸŒã¿ããããŒããããŸããããã¯SQLã®TIMESTAMP WITH TIME ZONE
ãçŽæ¥ãµããŒããããŠããããã«èŠããŸãããããããŒã¯ãããè¡ããŸããã
ãŸãŒã³ãèªèããªããŸãŒã³èªèã¿ã€ãã®ããããŒãå ¬éããããšã¯æ£ããããšã§ã¯ãªããšæããŸãã
æ£è§£ã§ãããçŸæç¹ã§JDBCããµããŒãããŠããã®ã¯ããã ãã§ãã ãã¹ãŠã®java.timeã¿ã€ãããã¿ã€ã ãŸãŒã³/ãªãã»ããããŒã¿ããªãjava.utilãŸãã¯java.sqlã¿ã€ãã«å€æããå¿ èŠããããŸãã
奜å¥å¿ãããPostgresã䜿çšããŠããŸããïŒ ã¿ã€ã ã¹ã¿ã³ãä»ãã®ã¿ã€ã ã¹ã¿ã³ãã¯ãäºæ³ãšã¯ç°ãªãåäœãããããã§ãã
Postgresã䜿çšããŠããŸããïŒ ã¿ã€ã ã¹ã¿ã³ãä»ãã®ã¿ã€ã ã¹ã¿ã³ãã¯ãäºæ³ãšã¯ç°ãªãåäœãããããã§ãã
ç§ã¯æ¿ç¥ããŠããŸãã ïŒãã以å€ã®ç¹ã§ã¯éåžžã«æšæºã«æºæ ããããŒã¿ããŒã¹ã«å€§ããªå€±æããããŸããïŒ
æ£è§£ã§ãããçŸæç¹ã§JDBCããµããŒãããŠããã®ã¯ããã ãã§ãã
JDBIãæåã§ãããè¡ãå¿
èŠãªãã«H2ã®org.h2.api.TimestampWithTimeZone
ããã«ããããšãæåŸ
ããŠããŸããã
TIMESTAMP W / TZå€ãååŸããããã®ãããŒã¿ãã«ãïŒããŸããŸãªãã©ã€ããŒéã§æ©èœããïŒæ¹æ³ãããããªããããçã®è§£æ±ºçã¯ãããŸããã
ãã ãããã¹ãŠã®æ
å ±ãååŸããªãå Žåã¯ãååŸãããµããããŠã¯ãªããŸãããã€ãŸããIMOã«ã¯ZonedDateTime
ãžã®çµã¿èŸŒã¿ããããŒããªãã¯ãã§ãã ãã以å€ã®å Žåã¯ãPostgresãšåãããã«å®è¡ããŠããŸããç§ãæåŸ
ããããšã§ã¯ãããŸããã
ãŠãŒã¶ãŒãZonedDateTime
ã䜿çšãããããããŒã¿ããŒã¹ã®ã¿ã€ã ãŸãŒã³ã§ã¯ãªãã¢ããªãµãŒããŒã®ã¿ã€ã ãŸãŒã³ã§è¿ãããããšãæ°ã«ããªãå Žåã§ã䟿å©ã ãšæããŸãã
ã¡ãªã¿ã«ãDropwizardã¯JDBI2çšã«ç°ãªãããŒãžã§ã³ã®ããããŒã䜿çšããŠããŸãããŠãŒã¶ãŒã¯ããŒã¿ããŒã¹ã®ã¿ã€ã ãŸãŒã³ãæ瀺çã«èšå®ã§ããŸãïŒ https ïŒ
H2ã§ZonedDateTime
ãååŸ/èšå®ããæ¹æ³ã®ãµã³ãã«ã³ãŒããæäŸããŠããã ããã°ããã©ã°ã€ã³ã«è¿œå ãããŠããã ããŸãã
ãŠãŒã¶ãŒãZonedDateTimeã䜿çšãããããããŒã¿ããŒã¹ã®ã¿ã€ã ãŸãŒã³ã§ã¯ãªãã¢ããªãµãŒããŒã®ã¿ã€ã ãŸãŒã³ã§è¿ãããããšãæ°ã«ããªãå Žåã§ã䟿å©ã ãšæããŸãã
@arteam ããŠãŒã¶ãŒããã®éžæãè¡ãããšã«æ°ä»ããŠããå Žå-ç§ã¯åæããŸãã
ãã ããAFAIR https://github.com/jdbi/jdbi/blob/master/core/src/main/java/org/jdbi/v3/core/mapper/BuiltInMapperFactory.java#L182ã¯ãH2ã§ã¯æ©èœããŸããã TS w TZã rs.getTimestamp(..)
ã¯ãã®ã¿ã€ãã§ã¯ãµããŒããããŠããªãããã
H2ã§ZonedDateTimeãååŸ/èšå®ããæ¹æ³ã®ãµã³ãã«ã³ãŒããæäŸã§ããã°ãããããã©ã°ã€ã³ã«è¿œå ã§ããã°å¹žãã§ãã
移æ€å¯èœãªæ¹æ³ã¯ããããŸãããç§ãç¥ã£ãŠããå¯äžã®æ¹æ³ã¯(org.h2.api.TimestampWithTimeZone) rs.getObject(..)
ãããããšãã°Oracleã®å Žåãåæ§ã§ãããOracleåºæã®ã¯ã©ã¹ã䜿çšããŸãã
äžè¬ã«ãæ£ããå€æïŒ LocalDateTime
ãžã®ã¿ã€ã ã¹ã¿ã³ãïŒã䜿çšããããŸãŒã³åããæ瀺çã«è¿œå ããããã«ãAPIã«ãã£ãŠ_匷å¶_ãããããšã奜ã¿ãŸãã
ããªãã¯åæããªãããã§ããã€ãŸãããã®åé¡ãéãããŸãŸã«ããŠããæå³ã¯ãããŸããã
ã¹ã¿ãã¯ã§è¡ãããšã®1ã€ã¯ãJavaã®ã¿ã€ã ãŸãŒã³== Postgresã®ã¿ã€ã ãŸãŒã³ã§ãããšå®éã«äž»åŒµããããšã§ãããã®å Žåããã¹ãŠãé©åã«æ©èœããŸãã äžäžèŽãããå ŽåãèŠåãçºããå¿ èŠããããŸããïŒ ããã¯ã人ã ãæåŸ ããæ©èœãæå¹ã«ããããšãšãTZãæ£ããããšãšã®éã®åŠ¥åç¹ãšããŠã¯åé¡ãããŸãããïŒ
ãªããããªã«æ©ãéããã®ãããããªãã®ã§ããã£ãšè©±ãåãããšããããšæããŸããã
ãã¹ãŠã®ãã³ããŒã§ãããäžè¬çã«è§£æ±ºã§ããªãå Žåã§ãããã³ããŒããšã«ããã確å®ã«ãµããŒãã§ããŸãã
Jdbiã«å梱ãããŠããããããŒãšåŒæ°ãã¡ã¯ããªã¯ãå¥ã®ããããŒ/åŒæ°ãç»é²ããã ãã§ãªãŒããŒã©ã€ãã§ããŸãã æåŸã«ç»é²ãããïŒã¿ã€ãããšã«ïŒåã¡ãŸãã
PostgresPlugin
ã®ãœãŒã¹ãèŠããšã LocalDate
ã LocalTime
ResultSet.getObject(Class)
ã䜿çšãã代æ¿ããããŒãæäŸããJavaTimeMapperFactory
ãç»é²ãããŠããããšãããããŸãã LocalTime
ã LocalDateTime
ãããã³OffsetDateTime
ã¯ãPostgresJDBCãã©ã€ããŒã«ãã£ãŠçŽæ¥ãµããŒããããŠããŸãã
H2ã«ãŸãŒã³ãåé€ããã«ZonedDateTime
ãä¿åããæ¹æ³ãããå Žåã¯ã H2DatabasePlugin
ãå€æŽããŠããã®ããã®ã«ã¹ã¿ã ããããŒã䜿çšã§ããŸãã
ç§ã¯ä»ã®ãšãããããåéããŸããããã§è¡ãããã¹ãè¯ãè°è«ããããŸãããããŠ@findepiç§ãã¡ã¯ç©äºãæ£ããè¡ãããšã«å€§ãã«æ°ã
ãã®ã³ã³ããããjdbiããŒã ãhsqldbå°çšã®åŒæ°ãšããããŒãæäŸããjdbi3-hsqldbãµããããžã§ã¯ã/ã¢ãŒãã£ãã¡ã¯ã/ ...ïŒsetObject / getObjectã䜿çšããã«java.timeãªããžã§ã¯ããçŽæ¥äœ¿çšããããšããµããŒãããïŒã«é¢å¿ãããããšãæ£ããç解ããŠããŸããïŒäŒè©±ïŒïŒ
絶察ã
æ£çŽãªãšããã @ findepiã«åæã
jdbiãæäŸããããããŒããã£ããå€æŽãããŠããããšã誰ãç¥ã£ãŠããããç¥ããããããã¹ãå®è¡äžã«å®è¡æäŸå€ã䜿çšããŠãjdbiãç¹å®ã®ã¿ã€ãã®ããããŒãæäŸããªãããšã確èªããŠããèªåã§äœæããããšæããŸããç§ã®ããŒã¿ã
å€ãã®ã¿ã€ãã®å€ãæžã蟌ãã§ããèªã¿åã倧èŠæš¡ãªåäœãã¹ãããããdbèªäœïŒhsqldbïŒãšjdbiã®äž¡æ¹ã§å®è£ ã®æ£ç¢ºæ§/ããŒã¿ã®æŽåæ§ãæ€èšŒããŠãããããjdbiããããŒ/åŒæ°ãèšè¿°ããŠåé¡ãåŠçã§ããŸãã ä»æ§ãããèšã£ãŠããã«ãããããããhsqldbã¯çŸåšjava.timeãåºæ¬çã«ãµããŒãããŠããªãã®ã§ãç§ã¯ä»ããã€ãæžãå¿ èŠããããŸããïŒå·šå€§ãªãã°ïŒã ç§ã¯ãŸã èªåã®ã·ã¹ãã 以å€ã®ãŸãŒã³/ãªãã»ããã§java.timeãªããžã§ã¯ãããã¹ãããããšãèããŠããªãã£ãã®ã§ããã¹ãããã ãã§ã確ãã«ããªãã»ãã/ãŸãŒã³ãã·ã¹ãã å€ã«ãªã»ãããããŠæ»ã£ãŠããŸãããjdbiã®ãããã³ã°ãåå ã§ãhsqldbã®ãã°ãåå ã§ã¯ãªããTimestampã«éä¿¡ãããŸãã
ãããã®æ¬ é¥ã®ããããããŒãjdbi3ããåé€ãããã³ããŒåºæã®ã¢ãŒãã£ãã¡ã¯ãïŒjdbi3-hsqldbãªã©ïŒã«ç§»åããŠãå®è£ ãå®å šã«æ£ããããããšããå§ãããŸãã
ãšã«ãããèªåã®ãããžã§ã¯ãã«å¿ èŠãªãã¹ãŠã®ããããŒãšåŒæ°ããã§ã«äœæããŠããã®ã§ãjdbi-hsqldbãèªåã§æäŸã§ããå¯èœæ§ããããŸãã
ç§ã¯ãããããã£ãšè³¢æãªéã ã£ããšæããŸããããã®æç¹ã§v3ããªãªãŒã¹ãããç«ã¯è¢ããåºãããŸãã
ãããã®ããããŒãŸãã¯åŒæ°ãã¡ã¯ããªãåé€ããããšã¯ããããã«äŸåããŠããæ¢åã®ãŠãŒã¶ãŒã«ãšã£ãŠé倧ãªå€æŽã«ãªããŸãã
誰ãããã§ã«ãããã«äŸåããŠããå ŽåïŒåœŒãã®æ¬ é¥ãèªèããŠãããã©ããã«ãããããïŒãç§ã¯ãããã®ãŠãŒã¶ãŒããããã«ããããåœãŠãã®ã«ååç°¡åã ãšæããŸãïŒå€æã¯ã»ãšãã©ã¯ã³ã©ã€ããŒã§ãã äžæ¹ãããããä¿æãããšãæäŸãããŠããããã«æ©èœãããšæ³å®ããç§ã®ãããªäººã
ããŸããŸãå¢ããŸãïŒæ£çŽãªãšãããjdbcãã¿ã€ã ãŸãŒã³ããµããŒãããŠããªããªã©ã®ãã¹ãŠã®æè¡ä»æ§ãç¥ã£ãŠããŸããïŒïŒåŸã§ã圌ãã®ããŒã¿ã誀ã£ãŠåŠçãããŠããããšãç¥ããŸã...
åºæ¬çã«ã圌ããçãŸãããããšã«ããæœåšçãªå°æ¥ã®æ害ã¯ãããããåé€ããããšã«ãã£ãŠæŽæ°ããå°æ°ã®äººã
ã«çŸåšåŒãèµ·ããããŠããæ害ãããã¯ããã«å€§ãããšæããŸãã
@TheRealMarnesæ©èœãåé€ããããšã¯ïŒååšããŠã¯ãªããªãããšã«åæãããšããŠãïŒããã»ã©åçŽã§ã¯ãªããšæããŸãã 人ã ã¯ã»ãã³ãã£ãã¯ããŒãžã§ãã³ã°ãæ³å®ããåŸåããããŸãïŒãããžã§ã¯ããããã«ç¶ããã©ããã«é¢ä¿ãªãïŒã ãããžã§ã¯ãã®ã«ãŒã«ã¯ããããŸããããéåžžã¯v3ã§éæšå¥šã«ãªãïŒéæšå¥šãšããŒã¯ã§ããAPIã¡ãœããããªããããããã§ã¯éæšå¥šã«ãªããŸããããã¥ã¡ã³ããšãã°ãæ®ã£ãŠããŸãïŒãv4ã§æ©èœãåé€ããŸãã ããªãªãŒã¹ããŒã/移è¡ã¬ã€ããèªãããšãæåŸ ããŠããŸãã
ç§ã¯ãã®ãããªããšã¯æ±ºããŠåçŽã§ã¯ãªãã解決çã¯åžžã«èª°ããäžå¹žã«ããã ãããšåæããŸãããç§ã¯çµãããæ段ãæ£åœåããæ¬ é¥ã®ããã·ã¹ãã ãããè¯ããã®ã«çœ®ãæããããã«åæºãããããšã¯é·æçã«ã¯åžžã«åæºãã䟡å€ããããšæãåŸåããããŸãã ãããŠããªãªãŒã¹ããŒã/移è¡ã¬ã€ããèªãããšãæåŸ ããã®ã¯äžåçã ãšã¯æããŸãã...ã¡ã³ããã³ã¹ãšãã€ããŒã¢ããããŒãã§ã¯ç¢ºãã§ãããã¡ãžã£ãŒã¢ããããŒãã§ã¯ããã§ã¯ãããŸããã Jdbi3èªäœã¯ãæ°ããã¬ã€ããèªãŸãªããšãjdbi2ããã¯äœ¿çšã§ããŸããã
ããããå ã«æ»ãããšãã¯ã³ã©ã€ããŒã§ãããªãã°ãç§ã¯ãããã®ããããŒ/åŒæ°ãç¡å¹ã«ãã解決çãåŸåãã«ããããšãã§ãããšæããŸã-å€åãããã®ããããŒããã©ã°ã€ã³ã«ç§»åããŸããïŒ
ãã³ããŒåºæã§ã¯ãªãjdbi3-core-experimental
ïŒ
ç·šéïŒç§ã®æªããããªãã¯jdbi.installPlugin(new ExperimentalMappersPlugin())
ãæå³ããŸã
ãããã¯å®éã«ã¯ãå®éšçãã§ã¯ãããŸããããããã¯ã¢ã€ãã¢ã§ãã
TimezoneInsensitiveJavaTimeMappers thenïŒP
ããã¯ããããŒã ãã§ãªããè°è«ã®å·¥å Žã§ããããŸãã
JavaTimeYoloTZPlugin
ã©ãã§ããïŒwinkïŒ
ãã¹ãŠã®ãã³ããŒã§ãããäžè¬çã«è§£æ±ºã§ããªãå Žåã§ãããã³ããŒããšã«ããã確å®ã«ãµããŒãã§ããŸãã
@qualidafialæè¿ãJava8以éã®äžçã§æ¥ä»/æå»ã®å€ãååŸããããã®æ°ããããã¡ã¯ãã¹ã¿ã³ããŒããããããã ãšããããšãç¥ããŸããã
ãŸããããå°ãèæ¯ïŒ
TIMESTAMP WITH TIME ZONE
ããZonedDateTime
ãžã®å€æã«ã€ããŠãã®åé¡ãäœæããŸãããããã«ãããã¿ã€ã ãŸãŒã³æ
å ±ãç Žæ£ãããŸããTIMESTAMP
ã DATE
ã TIME
ãªããžã§ã¯ããååŸãããããšã«ãªã£ãŠããæ¹æ³ã§ããã€ãŸãã java.sql.{Timestamp,Date,Time}
ã¯ã©ã¹ã䜿çšããŸãã ã¯ã©ã¹ã¯ãã¹ãŠjava.util.Date
ããæ¡åŒµãããŸãã Calendar
ãã©ã®ããã«å°å
¥ããã java.util.Date
ã®ã¡ãœãããå»æ¢ããã幎/æ/æ¥/æ/å/ç§ãåŠçããããèŠããŠãã人ã¯ããŸããïŒ æ£åœãªçç±ã§ããã§ãïŒãããŠç§ã¯Calendar
ãã¹ãŠã®åé¡ã解決ãããšããæå³ã§ã¯ãããŸããïŒãjava.sql.Timestamp
ãååŸããããšã¯ã§ããŸããã ãããã£ãŠãç±³åœã§å®è¡ãããŠããã¢ããªã¯ãäžéšã®å
±æããŒã¿ããŒã¹ã«2017-03-26 02:30:00
ïŒãŸãŒã³ãªãïŒïŒã®ã¿ã€ã ã¹ã¿ã³ãå€ãä¿åã§ããŸããããšãŒãããã§å®è¡ãããŠããã¢ããªïŒããšãã°ãJVMãŸãŒã³ãšããŠEurope/Berlin
ïŒã¯ä¿åãããŸãããåœæãšãŒãããã«ã¯DSTããã£ãããããã®ã¿ã€ã ã¹ã¿ã³ããååŸã§ããŸããjava.sql.Date
ã«ãåœãŠã¯ãŸããŸãã java.sql.Date
ã¯ãçå€äžã®java.sql.Timestamp
ã§ãããã®ããã«æ¥ä»ãè¡šââããŸãããçå€äžããªãå ŽåããããŸãã æ·±å€ïŒçŸåšãŸãã¯éå»ïŒã«DSTãå€æŽããããŸãŒã³ããããŸããjava.sql.Time
ã¯ãååŸãããæå»ã1970-01-01ã®ã¿ã€ã ã¹ã¿ã³ããšããŠè¡šãããããã®åé¡ã¯ãªããšæããŸããïŒ æ®å¿µãªããããã®æ¥ã«ããªã·ãŒãå€æŽããã®ã«ååãªãŸãŒã³ãããããã§ãïŒããšãã°ã America/Bahia_Banderas
ã America/Hermosillo
ïŒã ãããã®ãŸãŒã³ã§JVMã1ã€ã§ããå ŽåãJDBCã䜿çšããããã°ã©ã ã¯ç¹å®ã®TIME
å€ãååŸã§ããŸããã解決çã§ã¯ãªãã®ã¯ãJDBCã®å€ãAPIã䜿çšããŠååŸããããããæ°ããã¯ã©ã¹ã«å€æããããšã§ãã ããããããã¯äžè¬çã«ééã£ãŠããŸãã
resultSet.getTimestamp(col).toLocalDateTime()
ãresultSet.getDate(col).toLocalDate()
ãresultSet.getTime(col).toLocalTime()
ãããã¯ã³ã³ãã€ã«ãããŠããŸãæ©èœããŸãããäžèšã®åé¡ã®ãããã解決ãããŸããïŒJVMãŸãŒã³ãPacific/Apia
ãååŸãããæ¥ä»ã2011-12-30
å Žåãæ¥ä»ã®ååŸãæ©èœããŸãã;ïŒ
ããŠãæ°ããªãœãªã¥ãŒã·ã§ã³ãžã ResultSet
ã¯ãã®ããŸã人æ°ã®ãªãAPIããããJDBCãã©ã€ããŒã«ã¿ã€ããå€æããããã«äŸé Œã§ããŸãã
resultSet.getObject(col, LocalDateTime.class) // for TIMESTAMP
resultSet.getObject(col, LocalDate.class) // for DATE
resultSet.getObject(col, LocalTime.class) // for TIME
resultSet.getObject(col, ZonedDateTime.class) // for TIMESTAMP WITH TIME ZONE
ããã¯ãPostgreSQLãMySQLãOracleãããã³H2ã®JDBCãã©ã€ããŒã§æ©èœããŠããããã§ãã ãããŠãéæ³ã¯ãäžèšã®ãJVMãŸãŒã³ã§ã®è¡šçŸäžèœãã®åé¡ãåé¿ããŸãã
ãã®å€æã¯SQLServerãã©ã€ããŒãªã©ã«ã¯ãŸã å®è£
ãããŠããŸããããJDBIãåºè·ããJavaTimeã¯ã©ã¹ã®ããã©ã«ãã®ãããã³ã°ã«ããããšãã§ãããšæããŸãã
ããŒãïŒ
JDBC 4.2ä»æ§ã§ã¯ããã©ã€ããŒããããå®è£
ããå¿
èŠãããããšã矩åä»ããŠããŸããã ãã ãããã®ä»æ§ã§ã¯ã PreparedStatement.setObject
ãšRowSet.setObject
ãJava Timeã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãåãå
¥ããŠæ£ããåŠçããå¿
èŠãããããããã©ã€ããŒã¯ãããã®ã¯ã©ã¹ãæ瀺çã«ãµããŒãããå¿
èŠããããŸãã
ã«ãã³ããïŒ ç§ã®äž»ãªæžå¿µã¯ããã®ã¢ãããŒããžã®å€æŽããé£è§£ãªãã©ã€ããŒã䜿çšããŠãããŠãŒã¶ãŒã®ãªã°ã¬ãã·ã§ã³ãšããŠçŸããå¯èœæ§ãããããšã§ãã ãããããªãªãŒã¹ããŒãã«é©åãªã¡ãã»ãŒãžãéãããšã§ãæ£ããæ¹æ³ã§ç©äºãè¡ããšããåç®ã§ããã®å°ããªæè¡çã«ç Žå£çãªå€æŽãå ããããšãã§ãããããããŸãã...
@stevenschlanskerããªãã¯æ£ããã§ãã JDBIãæäŸã§ãããšæããŸã
ãã€ããŒããŒãžã§ã³ã®ãŸãŸã«ããŠãããŸãããã3ããªãªãŒã¹ããã°ããã§ããããã¯ãééã£ããŸãŸã«ããå Žåã®é倧ãªå€æŽã«ãããŸãã...;ïŒ
ç§ãèããŠããããã«èããããã®ãåçããããã ãã«ïŒ
YoloTimePlugin
奜ãã§ãïŒResultSet.getObject(column, type)
ã䜿çšããæ°ããçµã¿èŸŒã¿ããããŒã代ããã«è¿œå ããŸããç§ã¯ãããåŸåãã«ããããšãã§ããŸãã
ãã ãããããã®æ¥ä»/æå»ãªããžã§ã¯ãã®ãã€ã³ãã«é¢ãã質åã«ã¯ãŸã åçããŠããŸããã ããŒã¿ããŒã¹ã®çµæã®ãããã³ã°ã«é¢ããŠå€æŽãããã®ã¯ãã¹ãŠãæ¥ä»/æå»åŒæ°ãSQLã¹ããŒãã¡ã³ãã«ãã€ã³ãããæ¹æ³ã§ãã©ãŒãªã³ã°ããå¿ èŠããããŸãã
ããŒã¿ããŒã¹ããã®çµæã®ãããã³ã°ã«é¢ããŠå€æŽãããã®ã¯ãã¹ãŠãæ¥ä»/æå»åŒæ°ãSQLã¹ããŒãã¡ã³ãã«ãã€ã³ãããæ¹æ³ã§ãã©ãŒãªã³ã°ããå¿ èŠããããŸãã
@qualidafial ããšãŠãè¯ã質åã§ãã ç§ã¯ããããã¹ãããŠããŸããã ããã¯JDBC4.2ä»æ§ã§æ瀺çã«ã«ããŒãããŠããããã_æ£åžžã«æ©èœããã¯ãã§ãâ¢_ã
ããã¯JDBC4.2ä»æ§ã§æ瀺çã«ã«ããŒãããŠããããã_æ£åžžã«æ©èœããã¯ãã§ãâ¢_ã
ããã¯ãJDBCãã©ã€ããŒã®å®è£ è ãä»æ§ã«å®å šã«åŸã£ãŠããããšãåæãšããŠããŸãã ãã°ã®ãªãJDBCãã©ã€ããŒã®å®è£ ã¯ãŸã èŠã€ãããŸããã
ãã¹ãŠã®ããŒã¿ããŒã¹ãããã³ããŒã¿åã®ãµããŒããç°ãªãããŸããŸãªããŒãžã§ã³ã®ããããŒããã©ã°ã€ã³ã«æäŸããã®ã¯é¢åã ãšæããŸãã ããããããã空çœã®ã¹ã¬ãŒãã¢ãããŒããæ©èœããå¯èœæ§ããããŸããããããŒãããªã€ã³ã¹ããŒã«ãããŠããªãJdbiã€ã³ã¹ã¿ã³ã¹ããéå§ããã³ã¢ã¢ãŒãã£ãã¡ã¯ãã¯ãæåã§ã€ã³ã¹ããŒã«ããããã«éžæã§ããããŸããŸãªããããŒãæäŸããŸããåãããŒã¿åãåŠçããããã®ããžãã¯ãç°ãªããã®ããããŸã-get / setObjectãget / setXãä»ã®ã¿ã€ããžã®å€æãªã©ãããŒã¿ããŒã¹ïŒããŒãžã§ã³ïŒãšã¢ããªã±ãŒã·ã§ã³ããžãã¯ã«æé©ãªããããŒãèªåã§å€æããåäœãã¹ãã䜿çšããŠãã§ãã¯ããå¿ èŠããããŸãã
ããã¯åºæ¬çã«ç§ãç§ã®ãããžã§ã¯ãã§ãšã«ããä»ãã§ã«ãã£ãŠããããšã§ãã Jdbiã«ããªã€ã³ã¹ããŒã«ãããŠããããããŒã®äžã«ã¯ãç§ã®ããŒã¿ããŒã¹ã§ã¯æ©èœããªããã®ããããä»ã®ãšããå¿ èŠãªãã®ã§ãUnsupportedOperationExceptionãã¹ããŒããåŒæ°/ããããŒãã¡ã¯ããªã§å®éã«ãªãŒããŒã©ã€ãããŸãããå®è£ ïŒä»¥äžãåç §ïŒã
ããã¯ãdbãšèŠªå¯ã«ãªãããã¹ãŠãå®å šã«æ©èœããããšã確èªããã人ã«ãšã£ãŠã¯è§£æ±ºçã§ãããJustWerkâ¢ïŒå®éã«ã¯ããã§ã¯ãªãïŒã«äœããæ±ããŠãã人ã«ãšã£ãŠã¯äœãå€ãããŸããã
ãããè¡ãããšã§ãç§ã¯ãªããšãèŠã€ããŸãã... hsqldbãã©ã€ããŒã§ãç¬èªã®ä»æ§ããéžè±ããŠãããã€ã³ããå€ãããŸãïŒãœãŒã¹ã§å ±åããã³ä¿®æ£ãããæŽæ°ãããã¢ãŒãã£ãã¡ã¯ããæçµçã«ããªãã¯ã§å ¬éãããã®ããŸã åŸ ã£ãŠããŸãïŒãåäœããŸããåäœãããããã³ã°ããžãã¯ãèªåã§èŠã€ããããšã§ããããã®æ¬ é¥ãåé¿ããŸãã
// I want strings handled differently
<strong i="13">@Component</strong>
public class CleanStringArgumentFactory extends AbstractArgumentFactory<String> {
protected CleanStringArgumentFactory() {
super(Types.VARCHAR);
}
<strong i="14">@Override</strong>
protected Argument build(String value, ConfigRegistry config) {
return (position, statement, ctx) -> statement.setString(position, StringUtils.trimToNull(value));
}
}
// no need for jdbi's built-in logic
<strong i="17">@Component</strong>
public class SetObjectArgumentFactory implements ArgumentFactory {
private static final Set<Type> SUPPORTED = ImmutableSet.of(UUID.class, LocalDateTime.class);
<strong i="18">@Override</strong>
public Optional<Argument> build(Type type, Object value, ConfigRegistry config) {
return SUPPORTED.contains(type)
? Optional.of(new LoggableArgument(value, (position, statement, context) -> statement.setObject(position, value)))
: Optional.empty();
}
}
// these built-ins don't work and I don't need them anyway
<strong i="21">@Component</strong>
public class UnsupportedArgumentFactory implements ArgumentFactory {
private static final Set<Type> UNSUPPORTED = ImmutableSet.of(ZonedDateTime.class, OffsetDateTime.class, OffsetTime.class);
<strong i="22">@Override</strong>
public Optional<Argument> build(Type type, Object value, ConfigRegistry config) {
if (UNSUPPORTED.contains(type)) {
throw new UnsupportedOperationException(type.getTypeName() + " is not supported at the moment");
} else {
return Optional.empty();
}
}
}
// voodoo
<strong i="25">@Inject</strong>
public JdbiConfiguration(
@Named("dataSource") DataSource dataSource,
Set<ArgumentFactory> arguments,
Set<ColumnMapper> mappers,
Set<ColumnMapperFactory> mapperFactories
) {
jdbi = Jdbi.create(dataSource);
jdbi.clearMappings();
jdbi.installPlugin(new SqlObjectPlugin());
arguments.forEach(jdbi::registerArgument);
mapperFactories.forEach(jdbi::registerColumnMapper);
mappers.forEach(jdbi::registerColumnMapper);
// ...
// Jdbi instance fine-tuned for my exact database and demands, without surprises and at my own responsibility
ããŠããŒãïŒ ããšãã°ãã¢ã¯ãã£ãåããå¿ èŠã®ããã¯ã©ã¹ã®ã»ããã§åæåããå¿ èŠãããSetObjectArgumentFactoryãšãå€ãã®ããŒã¿åã®ãããã³ã°ããžãã¯ã®ããããçš®é¡ã®ããªãšãŒã·ã§ã³ãæäŸãã該åœããå Žåã¯ããã€ãã®æ§æå¯èœãªåäœãæäŸã§ããŸãã ã¿ããªå¹žãã ãšã³ããŠãŒã¶ãŒã®äœæ¥ãå¿ èŠã§ãããjdbiãç§ãæãã§ããããšãšãããŒã¿ããŒã¹ããµããŒãããŠããããšãæ£ç¢ºã«å®è¡ããŠããããšãç¥ã£ãŠããã®ã¯è¯ãããšã§ãã
ãã¹ãŠã®ããŒã¿ããŒã¹ãããã³ããŒã¿åã®ãµããŒããç°ãªãããŸããŸãªããŒãžã§ã³ã®ããããŒããã©ã°ã€ã³ã«æäŸããã®ã¯é¢åã ãšæããŸãã
å€ãã®ããŒã¿ããŒã¹ãã³ããŒåãã®ãã©ã°ã€ã³ã欲ããã§ãã ããŒã¿ããŒã¹ãã³ããŒãŸãã¯ãã®JDBCãã©ã€ããŒã®ç¹ç°æ§ã«Jdbiãé©åãããããã«ãããŒã¿ããŒã¹ã«ããã€ãã®ã«ã¹ã¿ãã€ãºãå¿ èŠ/å¿ èŠãªå Žåã¯ãããã«ã€ããŠãèãããããšæããŸãã ãŸãã¯ããã«è¯ãããšã«ããã«ãªã¯ãšã¹ããå¿ èŠã§ãïŒ :)
ããŒã¿ããŒã¹ãTravisCIã«ãã£ãŠçŽæ¥ãµããŒããããŠããå Žåã¯ããŒãã¹ãã€ã³ãããããå®éã«ããŒã¿ããŒã¹ã«å¯ŸããŠãã¹ããå®è¡ã§ããŸãïŒ
ããªãã®ãçœçŽã®ç¶æ ãã®ææ¡ã«é¢ããŠãç§ã¯ãã€ããŒãªç°è°ãããããŸããïŒ
clearMappings()
ã«çŽæ¥ã¡ãœãããRowMappers
ã ColumnMappers
ã Arguments
ãããã³JdbiCollectors
configã®ã¯ã©ã¹ã®ä»£ããã«Jdbi
ããããŠç§ã¯ãããã«clear()
ãšããååãä»ããŸãã@ jdbi / Contributorsä»ã®èª°ããéã蟌ã¿ããã§ããïŒ
éžæãããã®ã®1ã€ãç»é²ããã®ãå¿ããå Žåã«åããŠãããã©ã«ãã®ããããŒã誀ã£ãŠäœ¿çšããªãããã«ãçœçŽã®ç¶æ ã®ã¢ã€ãã¢ãå«ããŸããã ããã©ã«ãã®implãããNotImplementedExceptionãå¿ èŠã§ãã ã©ã¹ããŠã£ã³ã¯çŽ æŽãããããšã§ãããäœãæãŸãªãå Žåã«ãã©ããåŽäžããå¿ èŠãããããç¥ãæ¹æ³ã¯ãããŸããã
æã£ãŠããã®ãçãããã§ã¯ãããŸããã 人ã ããã®ã¢ãããŒããæãŸãªãå Žåãæ確ãªã¡ãœãããåŒã³åºãå¿ èŠã¯ãªããäœãå€ãããŸããã ããã¯ãããã©ã«ãã®ãªãäœæ¥æ¹æ³ã奜ã人ã®ããã ãã®ãã®ã§ãã
æ¢åã®ããããŒãå
¬éããã ãã§ã¯ãããªãããšã«åæããŸãã ã¯ãªãŒã³ã¹ã¬ãŒããªãã·ã§ã³ãæäŸããããšãéžæããå ŽåãããããŒãšãã€ã³ããŒã劥åœãªPlugin
ãã£ã³ã¯ã PrimitivesPlugin
ã BoxedPrimitivesPlugin
ã CollectionsPlugin
ãªã©ã«ãã³ãã«ããå¿
èŠããããŸãã
次ã«ãæ§æããŸã£ããè¡ããã«ãããŒã¹ãjdbiã®æ°ãããã¡ã¯ããªãè¿œå ããããã䜿çšããããã«æ¢åã®ãã¡ã¯ããªãå€æŽããŠã WholeJdbiEnchiladaPlugin
ãè¿œå ã§ããŸãã
ä»å çã«æ§ç¯ããã®ãé£ããå Žåã瀺ãããšãã§ããªãéããç§ã¯ãã¯ãªã¢ãã«ããããå察ããŠããŸã-ç§ã«ã¯ã³ãŒãã®èãã®ããã«æããŸãã
ä»å çã«æ§ç¯ããã®ãé£ããå Žåã瀺ãããšãã§ããªãéããç§ã¯ãã¯ãªã¢ãã«ããããå察ããŠããŸã-ç§ã«ã¯ã³ãŒãã®èãã®ããã«æããŸãã
å¥ã®no-preconfigjdbiãã¡ã¯ããªãè¿œå ããå Žåããããè¿œå çã«æ§ç¯ããããšã¯é£ãããªãã®ã§ãclearïŒïŒã¯å®éã«ã¯å¿ èŠãããŸããã
ããã§ããç§ãã¡ã¯ããã§åæããŠãããšæããŸããç§ã¯clear()
ã¹ã¿ã€ã«ãããæ°ãããã¯ãªãŒã³ãªããã¡ã¯ããªã¡ãœãããè¿œå ãããšãã奜ã¿ãè¡šçŸããŠããŸããã
ããã§ãããã¯ã¿ããªã®åé¡ã解決ããŸããïŒ å人çã«ã¯ããã®èšç»ã¯ããªãã»ã¯ã·ãŒã«èããããšæããŸãã
Jdbi
ãããã©ã«ããªãã«ããŸãïŒã»ãšãã©ãã¹ãŠã«äŸå€ãã¹ããŒããŸãïŒPrimitivesPlugin
ã BoxedPrimitivesPlugin
ãªã©ïŒã«ããŸããUTCJavaTimePlugin
vs LocalJavaTimePlugin
vs ConvertJavaTimeToUtilDatePlugin
ã GetObjectMapper.forClasses(Class... cs)
ã SetObjectArgumentFactory.forClasses(Class... cs)
ã NullsToDefaultsPrimitivesPlugin
vs NullThrowsExceptionPrimitivesPlugin
ïŒãããŠããããåãæ¹æ³ã§ïŒãã©ã°ã€ã³ã§ãããŠåå¥ã«ïŒå
¬éããã®ã§ã人ã
ã¯åœŒããæããã®ã ããæ£ç¢ºã«ãšã£ãŠã圌ãèªèº«ã®å®å
šã«æãŸãããããã³ã°ããžãã¯ãæ§æããããšãã§ããŸãã äžæ£ãªnullãã¿ã€ã ãŸãŒã³ã®æ¬ èœãåŠçããããã®ããŸããŸãªæŠç¥ããã®ä»ã®èããããäžäžèŽãªã©ãããã§å¿
èŠã«ãªãå¯èœæ§ã®ããå€ãã®ããããŒæ§æJdbi
ããå§ããŠãdbïŒ HsqlDb2_4_0Plugin
ïŒã®æ¢ç¥ã®é©åãªãããã³ã°ã¹ããŒã ã1è¡ã§ã€ã³ã¹ããŒã«ã§ããŸããããŸããŸãªæŠç¥ã®æ§æãªãã·ã§ã³ä»ãBuiltInGenericPreconfigurationPlugin
ïŒãšãèšå®ãªãã®ãã¡ã¯ããªã¡ãœãããå®è¡ãããã ãã§ããã¹ãŠã®äžäœäºææ§ãå®çŸã§ããŸãã
Jdbi
ãããã©ã«ããªãã«ãã
ç§ã¯ããŸã匷ãæèŠã¯ãããŸããããããã¯ãã¹ãŠãŠãŒã¶ãŒã®èŠ³ç¹ããã¯éåžžã«è€éã«èãããŸãã ãŠãŒã¶ãŒã¯ã䜿çšããã¿ã€ãã«å¯ŸããŠå¯èœãªããŸããŸãªãããã³ã°ãç解ããé©åãªãããã³ã°ãéžæããå¿ èŠããããŸãã ããã¯ãç¹ã«ãã³ãã©ã«ãæ©èœããŠããå Žåã¯å°é£ã§ããå¯èœãªããŸããŸãªãªãã·ã§ã³ãç解ããããšã¯å®éã«ã¯ç°¡åã§ã¯ãããŸããã
ãŠãŒã¶ãŒã¯ã䜿çšããã¿ã€ãã«å¯ŸããŠå¯èœãªããŸããŸãªãããã³ã°ãç解ããé©åãªãããã³ã°ãéžæããå¿ èŠããããŸãã
ãããã圌ããæãå Žåã«éããŸãã æ¢åã®ãã¡ã¯ããªã¡ãœããã¯ãçŸåšãšãŸã£ããåãããªã€ã³ã¹ããŒã«ãããããããŒã䜿çšããŠJdbi
ã€ã³ã¹ã¿ã³ã¹ãåºåãç¶ããŸãã ããã«DIYæ§æãã¡ã¯ããªã¡ãœãããååŸããŸããããããéžæãã人ã¯ããããã³ã°ã®èŠªå¯ããç解ããå¿
èŠããããŸãã DIYã€ã³ã¹ã¿ã³ã¹ãååŸãã YourDbAndVersionPlugin
ãã€ã³ã¹ããŒã«ããŠããããäœãããã«ããŠãããŒã«ããã¯ããéäžããããŸãã ç§ã®é·ã説æã¯ãããŒã¹ã©ã€ã³ã§ã¯ãªããäž»ã«jdbiã®å
éšãšé«åºŠãªäœ¿çšæ³ã§ããã
TLDRïŒããªãã¯ãŸã Jdbi.create(dataSource)
ãããããšãã§ããŸãããããŠããªãã¯ããªãããŸã äžããŠããªãããã«ã€ããŠã®è¿œå ã®ããŒããäžããå¿
èŠã¯ãããŸããã ä»ã®èª°ããJdbi.createBlank(dataSource).install(x).install(y).install(z)...
éžæããã ãã§ã
ç§ã¯åå ããŠããŸãããæ¢åã®å·¥å Žãå»æ¢ããå¿ èŠã¯ãªããšæããŸããããç®±ããåºããŠããã«äœ¿ãããåäœã¯ããªãè¯ãã®ã§ãã»ãšãã©ã®ãŠãŒã¶ãŒã¯åŒãç¶ãããã䜿çšãããšæããŸãã
ãã£ããã
@TheRealMarnesãã®äŒè©±å šäœã¯ãJDBCã§çŽæ¥ãµããŒããããŠããªãJSR-310ããŒã¿åãæ±ãããšããå§ãŸããŸããã
誀ã£ãjava.timeããããŒãšåŒæ°ãåé€ããçµã¿èŸŒã¿ã§ã¯ãªããã©ã°ã€ã³ã«å ¥ããããšã«ã€ããŠã¯ã³ã³ã»ã³ãµã¹ããããšæããŸãã
ããã§ããããè¿œæ±ãããã§ããïŒ
java.timeã®ãã®ã ãã§ããïŒ JavaTimePluginïŒ
ã¯ããjava.timeåå°çšã®ãã©ã°ã€ã³ã§ããã@ findepiã§èª¬æãããŠ
SimplisticJavaTimePlugin
ïŒ
ç§ã®ä»ã®PRãäžè©±ããããŸã§ããã§åŸ ã£ãŠããŸã...ããã¯åæã«å°ãå€ãããŸãã
æãåèã«ãªãã³ã¡ã³ã
æ£çŽãªãšããã @ findepiã«åæã
jdbiãæäŸããããããŒããã£ããå€æŽãããŠããããšã誰ãç¥ã£ãŠããããç¥ããããããã¹ãå®è¡äžã«å®è¡æäŸå€ã䜿çšããŠãjdbiãç¹å®ã®ã¿ã€ãã®ããããŒãæäŸããªãããšã確èªããŠããèªåã§äœæããããšæããŸããç§ã®ããŒã¿ã
å€ãã®ã¿ã€ãã®å€ãæžã蟌ãã§ããèªã¿åã倧èŠæš¡ãªåäœãã¹ãããããdbèªäœïŒhsqldbïŒãšjdbiã®äž¡æ¹ã§å®è£ ã®æ£ç¢ºæ§/ããŒã¿ã®æŽåæ§ãæ€èšŒããŠãããããjdbiããããŒ/åŒæ°ãèšè¿°ããŠåé¡ãåŠçã§ããŸãã ä»æ§ãããèšã£ãŠããã«ãããããããhsqldbã¯çŸåšjava.timeãåºæ¬çã«ãµããŒãããŠããªãã®ã§ãç§ã¯ä»ããã€ãæžãå¿ èŠããããŸããïŒå·šå€§ãªãã°ïŒã ç§ã¯ãŸã èªåã®ã·ã¹ãã 以å€ã®ãŸãŒã³/ãªãã»ããã§java.timeãªããžã§ã¯ãããã¹ãããããšãèããŠããªãã£ãã®ã§ããã¹ãããã ãã§ã確ãã«ããªãã»ãã/ãŸãŒã³ãã·ã¹ãã å€ã«ãªã»ãããããŠæ»ã£ãŠããŸãããjdbiã®ãããã³ã°ãåå ã§ãhsqldbã®ãã°ãåå ã§ã¯ãªããTimestampã«éä¿¡ãããŸãã
ãããã®æ¬ é¥ã®ããããããŒãjdbi3ããåé€ãããã³ããŒåºæã®ã¢ãŒãã£ãã¡ã¯ãïŒjdbi3-hsqldbãªã©ïŒã«ç§»åããŠãå®è£ ãå®å šã«æ£ããããããšããå§ãããŸãã
ãšã«ãããèªåã®ãããžã§ã¯ãã«å¿ èŠãªãã¹ãŠã®ããããŒãšåŒæ°ããã§ã«äœæããŠããã®ã§ãjdbi-hsqldbãèªåã§æäŸã§ããå¯èœæ§ããããŸãã