24 Ocak 2023 Salı

Sütun Tipleri - TIMESTAMP ve JDBC

Kullanım Özeti
- Ben Connector/J 8 ve üstünü kullanıyorum ve hem MySQL sunucusunun hem de uygulamamın saat dilimi UTC. Başka da bir şey yapmama gerek kalmadı.
- Eğer uygulamamın saat dilimini UTC yapamıyorsam, bağlantıya "preserveInstants=true&connectionTimeZone=UTC" eklemek yeterli.
- Eğer Hibernate kullanıyorsam şöyle yaparız
# JPA
<property name="hibernate.jdbc.time_zone" value="UTC"/>

#Spring
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
1. Bağlantı string'i
İki kullanım şekli var
- preserveInstants=true verilir ve bağlantıda belirtilen saat diliminin kullanılması istenir
- preserveInstants=false verilir ve JVM'in saat diliminin kullanılması istenir
 - Eğer Bağlantı string'inde saat dilimi verilmemişse JVM saat dilimi kullanılır

Örnek 
UTC için JDBC bağlantısına "preserveInstants=true&connectionTimeZone=UTC" eklenir. preserveInstants=true yerelleştirme ve belirttiğim saat dilimini kullanma anlamına geliyor.


1.1 preserveInstants=true + Saat Dilimi
preserveInstants=true için açıklama şöyle. JVM'in saat dilimi değil, bağlantıda belirtilen ayarlar kullanılıyor
When preserveInstants is true, Connector/J attempts to preserve the time instants by performing the conversions in a manner defined by the connection properties connectionTimeZone and forceConnectionTimeZoneToSession.
preserveInstants=true için bir örnek şöyle. Bu sefer değerler yerelleştirildi
Use preserveInstants=true&connectionTimeZone=SERVER . Connector/J then queries the value of the session time zone from the server, and converts the event timestamps between the session time zone and the JVM time zone. For example:

Time zones: UTC+2 for JVM, UTC+1 for server session

Original timestamp from client (in UTC+2): 2020-01-01 02:00:00

Timestamp sent to server by Connector/J: 2020-01-01 01:00:00 (after conversion from UTC+2 to UTC+1)

Timestamp value stored internally on the server: 2020-01-01 00:00:00 UTC (after internal conversion from UTC+1 to UTC)

Timestamp value retrieved later into a server session in UTC+1: 2020-01-01 01:00:00 (after internal conversion from UTC to UTC+1)

Timestamp values constructed by Connector/J in the same JVM time zone as before (UTC+2) and returned to an application: 2020-01-01 02:00:00 (after conversion from UTC+1 to UTC+2)

Timestamp values constructed by Connector/J in another JVM time zone (say, UTC+3) and returned to an application: 2020-01-01 03:00:00 (after conversion from UTC+1 to UTC+3)

Comment: Time instant is preserved.
Örnek
Şöyle yaparız. Kayıt şöyle '1970-01-01 00:00:01.000000'. Burada bağlantıda verilen UTC ayar kullanılır ve TimeStamp UTC'ye göre string'e çevrilir.
dataSource.setUrl("jdbc:mysql://172.18.17.209:32110/ADV
?preserveInstants=true&connectionTimeZone=UTC");
...
new Timestamp(1000)
1.2 preserveInstants=false
preserveInstants=false ise açıklaması şöyle. Yani JVM'in saat dilimine göre string'e çevrilir ve gönderilir. Ancak Connector/J 8.0.23 ile varsayılan davranış bu değil. Varsayılan davranış preserveInstants=true
With ‘preserveInstants=false’ Connector/J 8.0.23 always uses the JVM default time zone for rendering the values it sends to the server and for constructing the Java objects from the fetched data. It matches the default Connector/J 5.1 behavior. If ‘preserveInstants=true’ (which is the default value), Connector/J does its best to preserve the instant point on the time-line for Java instant-based objects such as java.sql.Timestamp or java.time.OffsetDateTime, instead of preserving the time’s original visual form.
preserveInstants=false için bir örnek şöyle. Yani gönderilen ve alınan değer hep aynı çıktı. Yerelleştirilmedi
Time zones: UTC for JVM, UTC+1 for server session

Original timestamp from client (in UTC): 2020-01-01 01:00:00

Timestamp sent to server by Connector/J: 2020-01-01 01:00:00 (no conversion)

Timestamp values stored internally on the server: 2020-01-01 00:00:00 UTC 

Timestamp value retrieved later into a server section (in UTC+1): 2020-01-01 01:00:00 

Timestamp values constructed by Connector/J in some other JVM time zone then before (say, in UTC+3): 2020-01-01 01:00:00

Comment: Time instant is not preserved
2. Eğer Bağlantı string'inde saat dilimi verilmemişse JVM saat dilimi kullanılır

Örnek - JVM GMT + 2 İse
new TimeStamp(0) olarak kaydedince veri tabanı '1970-01-01 02:00:00.000000' olarak gösterdi. Açıklaması şöyle
Internally a MySQL timestamp column is stored as UTC but when selecting a date MySQL will automatically convert it to the current session timezone.

Örnek - JVM UTC İse
Şöyle yapınca kaydetmedi
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
...
new Timestamp(0)
Hata şöyle. Yani 1292 hatasını veriyor. Benzer bir hata da burada.
Incorrect datetime value: '1970-01-01 00:00:00' for column 'EXPIRATION_DATE' at row 1 (errno 1292) (sqlstate 22007)
Şöyle yapınca kaydetti. Kayıt şöyle '1970-01-01 00:00:01.000000'
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
...
new Timestamp(1_000L)

Hiç yorum yok:

Yorum Gönder

Soft Delete

Giriş Açıklaması  şöyle When using the soft delete mechanism on the database, you might run into a situation where a record with a unique co...