Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hibernate-dialect/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Fixed @JdbcTypeCode annotation on fields: Json, JsonDocument and others with YdbJdbcCode

## 1.5.0 ##

- Support for `GenerationType.IDENTITY` with JDBC YDB Driver **2.3.11** and later.
Expand Down
4 changes: 2 additions & 2 deletions hibernate-dialect/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>tech.ydb.dialects</groupId>
<artifactId>hibernate-ydb-dialect</artifactId>
<version>1.5.0</version>
<version>1.5.1</version>

<packaging>jar</packaging>

Expand Down Expand Up @@ -42,7 +42,7 @@
<log4j2.version>2.17.2</log4j2.version>

<ydb.sdk.version>2.3.13</ydb.sdk.version>
<ydb.jdbc.version>2.3.11</ydb.jdbc.version>
<ydb.jdbc.version>2.3.18</ydb.jdbc.version>
</properties>

<licenses>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,27 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.DATETIME_64, LocalDateTime.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.TIMESTAMP_64, Instant.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INTERVAL_64, Duration.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.JSON, String.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.JSON_DOCUMENT, String.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.BOOL, Boolean.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INT8, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INT16, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.UINT16, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INT32, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.UINT32, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INT64, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.UINT64, Integer.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.FLOAT, Float.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.DOUBLE, Double.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.BYTES, byte[].class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.TEXT, String.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.YSON, byte[].class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.JSON, String.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.UUID, java.util.UUID.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.DATE, LocalDate.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.DATETIME, LocalDateTime.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.TIMESTAMP, Instant.class));
typeContributions.contributeJdbcType(new YdbJdbcType(YdbJdbcCode.INTERVAL, Duration.class));

typeContributions.contributeJavaType(BigDecimalJavaType.INSTANCE_22_9);
typeContributions.contributeJdbcType(new DecimalJdbcType(YdbJdbcCode.DECIMAL_22_9));
Expand Down Expand Up @@ -171,6 +192,26 @@ protected void registerColumnTypes(TypeContributions typeContributions, ServiceR
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DECIMAL_31_9, "Decimal(31, 9)", "Decimal(31, 9)", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DECIMAL_35_0, "Decimal(35, 0)", "Decimal(35, 0)", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DECIMAL_35_9, "Decimal(35, 9)", "Decimal(35, 9)", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.JSON, "Json", "Json", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.JSON_DOCUMENT, "JsonDocument", "JsonDocument", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.BOOL, "Bool", "Bool", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.INT8, "Int8", "Int8", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.INT16, "Int16", "Int16", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.UINT16, "Uint16", "Uint16", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.INT32, "Int32", "Int32", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.UINT32, "Uint32", "Uint32", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.INT64, "Int64", "Int64", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.UINT64, "Uint64", "Uint64", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.FLOAT, "Float", "Float", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DOUBLE, "Double", "Double", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.BYTES, "Bytes", "Bytes", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.TEXT, "Text", "Text", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.YSON, "Yson", "Yson", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.UUID, "Uuid", "Uuid", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DATE, "Date", "Date", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.DATETIME, "Datetime", "Datetime", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.TIMESTAMP, "Timestamp", "Timestamp", this));
ddlTypeRegistry.addDescriptor(new DdlTypeImpl(YdbJdbcCode.INTERVAL, "Interval", "Interval", this));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package tech.ydb.hibernate.types;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.cfg.AvailableSettings;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import tech.ydb.hibernate.TestUtils;
import static tech.ydb.hibernate.TestUtils.basedConfiguration;
import static tech.ydb.hibernate.TestUtils.inTransaction;
import static tech.ydb.hibernate.TestUtils.jdbcUrl;
import tech.ydb.hibernate.dialect.code.YdbJdbcCode;
import tech.ydb.test.junit5.YdbHelperExtension;

/**
* @author Kirill Kurdyukov
*/
public class YdbJdbcCodeTest {

@RegisterExtension
private static final YdbHelperExtension ydb = new YdbHelperExtension();

@BeforeAll
static void beforeAll() {
TestUtils.SESSION_FACTORY = basedConfiguration()
.addAnnotatedClass(YdbAllTypes.class)
.setProperty(AvailableSettings.URL, jdbcUrl(ydb))
.buildSessionFactory();
}

@Test
public void integrationTest() {
/*
* create table ydb_all_types (
* aDouble Double,
* aFloat Float,
* bool Bool,
* bytes Bytes,
* date Date,
* date32 Date32,
* datetime Datetime,
* datetime64 Datetime64,
* int16 Int16,
* int32 Int32,
* int64 Int64,
* int8 Int8,
* interval Interval,
* interval64 Interval64,
* json Json,
* jsonDocument JsonDocument,
* text Text,
* timestamp Timestamp,
* timestamp64 Timestamp64,
* uint16 Uint16,
* uint32 Uint32,
* uint64 Uint64,
* uint8 Uint8,
* uuid Uuid not null,
* yson Yson,
* primary key (uuid)
* )
*/
var ydbAllEntity = new YdbAllTypes(
UUID.randomUUID(),
true, 1, 1, 1, 1, 1, 1, 1, 1,
LocalDate.now(),
LocalDateTime.of(2000, 1, 1, 1, 1, 1),
Instant.parse("2025-10-02T11:06:32.779087Z"),
Duration.ofSeconds(1),
LocalDate.ofYearDay(1000, 1),
LocalDateTime.of(1000, 1, 1, 1, 1, 1),
LocalDateTime.of(1000, 1, 1, 1, 1, 1).toInstant(ZoneOffset.UTC),
Duration.ofSeconds(-1),
"text",
"{\"a\":\"a\"}",
"{\"a\":\"a\"}",
new byte[]{10, 20},
"{a=1u}".getBytes(StandardCharsets.UTF_8),
1.1f, 1.1
);

inTransaction(session -> session.persist(ydbAllEntity));
inTransaction(session -> assertEquals(ydbAllEntity, session.find(YdbAllTypes.class, ydbAllEntity.getUuid())));

var newYdbAllEntity = new YdbAllTypes(
ydbAllEntity.getUuid(),
false, 2, 2, 2, 2, 2, 2, 2, 2,
LocalDate.now(),
LocalDateTime.of(2000, 2, 2, 2, 2, 2),
Instant.parse("2023-10-02T11:06:32.779087Z"),
Duration.ofSeconds(2),
LocalDate.ofYearDay(1000, 2),
LocalDateTime.of(1000, 2, 2, 2, 2, 2),
LocalDateTime.of(1000, 2, 2, 2, 2, 2).toInstant(ZoneOffset.UTC),
Duration.ofSeconds(-2),
"new_text",
"{\"b\":\"b\"}",
"{\"b\":\"b\"}",
new byte[]{20, 20},
"{a=2u}".getBytes(StandardCharsets.UTF_8),
2.2f, 2.2
);
inTransaction(session -> {
session.createQuery(
"""
UPDATE YdbAllTypes e
SET
e.bool = :bool,
e.uint8 = :uint8,
e.int8 = :int8,
e.uint16 = :uint16,
e.int16 = :int16,
e.uint32 = :uint32,
e.int32 = :int32,
e.uint64 = :uint64,
e.int64 = :int64,
e.date = :date,
e.datetime = :datetime,
e.timestamp = :timestamp,
e.interval = :interval,
e.date32 = :date32,
e.datetime64 = :datetime64,
e.timestamp64 = :timestamp64,
e.interval64 = :interval64,
e.text = :text,
e.json = :json,
e.jsonDocument = :jsonDocument,
e.bytes = :bytes,
e.yson = :yson,
e.aFloat = :aFloat,
e.aDouble = :aDouble
""")
.setParameter("bool", newYdbAllEntity.isBool())
.setParameter("uint8", newYdbAllEntity.getUint8())
.setParameter("int8", newYdbAllEntity.getInt8())
.setParameter("uint16", newYdbAllEntity.getUint16())
.setParameter("int16", newYdbAllEntity.getInt16())
.setParameter("uint32", newYdbAllEntity.getUint32())
.setParameter("int32", newYdbAllEntity.getInt32())
.setParameter("uint64", newYdbAllEntity.getUint64())
.setParameter("int64", newYdbAllEntity.getInt64())
.setParameter("date", newYdbAllEntity.getDate())
.setParameter("datetime", newYdbAllEntity.getDatetime())
.setParameter("timestamp", newYdbAllEntity.getTimestamp())
.setParameter("interval", newYdbAllEntity.getInterval())
.setParameter("date32", newYdbAllEntity.getDate32())
.setParameter("datetime64", newYdbAllEntity.getDatetime64())
.setParameter("timestamp64", newYdbAllEntity.getTimestamp64())
.setParameter("interval64", newYdbAllEntity.getInterval64())
.setParameter("text", newYdbAllEntity.getText())
.setParameter("json", newYdbAllEntity.getJson())
.setParameter("jsonDocument", newYdbAllEntity.getJsonDocument())
.setParameter("bytes", newYdbAllEntity.getBytes())
.setParameter("yson", newYdbAllEntity.getYson())
.setParameter("aFloat", newYdbAllEntity.getAFloat())
.setParameter("aDouble", newYdbAllEntity.getADouble())
.executeUpdate();
assertEquals(newYdbAllEntity, session.find(YdbAllTypes.class, newYdbAllEntity.getUuid()));
});
}

@Entity(name = "YdbAllTypes")
@Table(name = "ydb_all_types")
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class YdbAllTypes {
@Id
@JdbcTypeCode(YdbJdbcCode.UUID)
private UUID uuid;

@Column
@JdbcTypeCode(YdbJdbcCode.BOOL)
private boolean bool;

@Column
@JdbcTypeCode(YdbJdbcCode.UINT8)
private int uint8;

@Column
@JdbcTypeCode(YdbJdbcCode.INT8)
private int int8;

@Column
@JdbcTypeCode(YdbJdbcCode.UINT16)
private int uint16;

@Column
@JdbcTypeCode(YdbJdbcCode.INT16)
private int int16;

@Column
@JdbcTypeCode(YdbJdbcCode.UINT32)
private int uint32;

@Column
@JdbcTypeCode(YdbJdbcCode.INT32)
private int int32;

@Column
@JdbcTypeCode(YdbJdbcCode.UINT64)
private int uint64;

@Column
@JdbcTypeCode(YdbJdbcCode.INT64)
private int int64;

@Column
@JdbcTypeCode(YdbJdbcCode.DATE)
private LocalDate date;

@Column
@JdbcTypeCode(YdbJdbcCode.DATETIME)
private LocalDateTime datetime;

@Column
@JdbcTypeCode(YdbJdbcCode.TIMESTAMP)
private Instant timestamp;

@Column
@JdbcTypeCode(YdbJdbcCode.INTERVAL)
private Duration interval;

@Column
@JdbcTypeCode(YdbJdbcCode.DATE_32)
private LocalDate date32;

@Column
@JdbcTypeCode(YdbJdbcCode.DATETIME_64)
private LocalDateTime datetime64;

@Column
@JdbcTypeCode(YdbJdbcCode.TIMESTAMP_64)
private Instant timestamp64;

@Column
@JdbcTypeCode(YdbJdbcCode.INTERVAL_64)
private Duration interval64;

@Column
@JdbcTypeCode(YdbJdbcCode.TEXT)
private String text;

@Column
@JdbcTypeCode(YdbJdbcCode.JSON)
private String json;

@Column
@JdbcTypeCode(YdbJdbcCode.JSON_DOCUMENT)
private String jsonDocument;

@Column
@JdbcTypeCode(YdbJdbcCode.BYTES)
private byte[] bytes;

@Column
@JdbcTypeCode(YdbJdbcCode.YSON)
private byte[] yson;

@Column
@JdbcTypeCode(YdbJdbcCode.FLOAT)
private float aFloat;

@Column
@JdbcTypeCode(YdbJdbcCode.DOUBLE)
private double aDouble;
}
}