Oracle Type Support
Foundations JDBC provides comprehensive support for Oracle data types, including OBJECT types, nested tables, intervals, and LOB types.
Numeric Types
Universal NUMBER Type
| Oracle Type | Java Type | Notes |
|---|---|---|
NUMBER | BigDecimal | Arbitrary precision |
NUMBER(p,0) where p <= 9 | Integer | 32-bit integer |
NUMBER(p,0) where 9 < p <= 18 | Long | 64-bit integer |
NUMBER(p,s) | BigDecimal | Fixed precision/scale |
- Kotlin
- Java
- Scala
val numberType: OracleType<BigDecimal> = OracleTypes.number
val decimal: OracleType<BigDecimal> = OracleTypes.number(10, 2) // NUMBER(10,2)
val intType: OracleType<Int> = OracleTypes.numberAsInt(9) // NUMBER(9)
val longType: OracleType<Long> = OracleTypes.numberAsLong(18) // NUMBER(18)
OracleType<BigDecimal> numberType = OracleTypes.number;
OracleType<BigDecimal> decimal = OracleTypes.number(10, 2); // NUMBER(10,2)
OracleType<Integer> intType = OracleTypes.numberAsInt(9); // NUMBER(9)
OracleType<Long> longType = OracleTypes.numberAsLong(18); // NUMBER(18)
val numberType: OracleType[BigDecimal] = OracleTypes.number
val decimal: OracleType[BigDecimal] = OracleTypes.number(10, 2) // NUMBER(10,2)
val intType: OracleType[Int] = OracleTypes.numberAsInt(9) // NUMBER(9)
val longType: OracleType[Long] = OracleTypes.numberAsLong(18) // NUMBER(18)
IEEE 754 Floating Point
| Oracle Type | Java Type | Notes |
|---|---|---|
BINARY_FLOAT | Float | 32-bit IEEE 754 |
BINARY_DOUBLE | Double | 64-bit IEEE 754 |
FLOAT(p) | Double | Maps to NUMBER internally |
- Kotlin
- Java
- Scala
val binaryFloat: OracleType<Float> = OracleTypes.binaryFloat
val binaryDouble: OracleType<Double> = OracleTypes.binaryDouble
val floatType: OracleType<Double> = OracleTypes.float_(126) // FLOAT(126)
OracleType<Float> binaryFloat = OracleTypes.binaryFloat;
OracleType<Double> binaryDouble = OracleTypes.binaryDouble;
OracleType<Double> floatType = OracleTypes.float_(126); // FLOAT(126)
val binaryFloat: OracleType[Float] = OracleTypes.binaryFloat
val binaryDouble: OracleType[Double] = OracleTypes.binaryDouble
val floatType: OracleType[Double] = OracleTypes.float_(126) // FLOAT(126)
Boolean Type
| Oracle Type | Java Type | Notes |
|---|---|---|
BOOLEAN | Boolean | Oracle 23c+ native |
NUMBER(1) | Boolean | Traditional 0/1 convention |
- Kotlin
- Java
- Scala
val boolNative: OracleType<Boolean> = OracleTypes.boolean_ // Oracle 23c+
val boolNumber: OracleType<Boolean> = OracleTypes.numberAsBoolean // NUMBER(1)
OracleType<Boolean> boolNative = OracleTypes.boolean_; // Oracle 23c+
OracleType<Boolean> boolNumber = OracleTypes.numberAsBoolean; // NUMBER(1)
val boolNative: OracleType[Boolean] = OracleTypes.boolean_ // Oracle 23c+
val boolNumber: OracleType[Boolean] = OracleTypes.numberAsBoolean // NUMBER(1)
Character Types
| Oracle Type | Java Type | Max Length | Notes |
|---|---|---|---|
VARCHAR2(n) | String | 4000 bytes | Variable-length |
CHAR(n) | String | 2000 bytes | Fixed-length, blank-padded |
NVARCHAR2(n) | String | 4000 bytes | National character set |
NCHAR(n) | String | 2000 bytes | National fixed-length |
LONG | String | 2 GB | Deprecated, use CLOB |
- Kotlin
- Java
- Scala
val varcharType: OracleType<String> = OracleTypes.varchar2
val varchar100: OracleType<String> = OracleTypes.varchar2(100)
val charType: OracleType<String> = OracleTypes.char_(10)
val nvarcharType: OracleType<String> = OracleTypes.nvarchar2(100)
OracleType<String> varcharType = OracleTypes.varchar2;
OracleType<String> varchar100 = OracleTypes.varchar2(100);
OracleType<String> charType = OracleTypes.char_(10);
OracleType<String> nvarcharType = OracleTypes.nvarchar2(100);
val varcharType: OracleType[String] = OracleTypes.varchar2
val varchar100: OracleType[String] = OracleTypes.varchar2(100)
val charType: OracleType[String] = OracleTypes.char_(10)
val nvarcharType: OracleType[String] = OracleTypes.nvarchar2(100)
Non-Empty String Variants
For NOT NULL columns, use NonEmptyString to guarantee non-empty values:
- Kotlin
- Java
- Scala
val nonEmpty: OracleType<NonEmptyString> = OracleTypes.varchar2NonEmpty(100)
val nvarNonEmpty: OracleType<NonEmptyString> = OracleTypes.nvarchar2NonEmpty(100)
OracleType<NonEmptyString> nonEmpty = OracleTypes.varchar2NonEmpty(100);
OracleType<NonEmptyString> nvarNonEmpty = OracleTypes.nvarchar2NonEmpty(100);
val nonEmpty: OracleType[NonEmptyString] = OracleTypes.varchar2NonEmpty(100)
val nvarNonEmpty: OracleType[NonEmptyString] = OracleTypes.nvarchar2NonEmpty(100)
Padded String for CHAR
For CHAR columns preserving padding:
- Kotlin
- Java
- Scala
val padded: OracleType<PaddedString> = OracleTypes.charPadded(10) // CHAR(10)
val npadded: OracleType<PaddedString> = OracleTypes.ncharPadded(10) // NCHAR(10)
OracleType<PaddedString> padded = OracleTypes.charPadded(10); // CHAR(10)
OracleType<PaddedString> npadded = OracleTypes.ncharPadded(10); // NCHAR(10)
val padded: OracleType[PaddedString] = OracleTypes.charPadded(10) // CHAR(10)
val npadded: OracleType[PaddedString] = OracleTypes.ncharPadded(10) // NCHAR(10)
Large Object (LOB) Types
| Oracle Type | Java Type | Max Size | Notes |
|---|---|---|---|
CLOB | String | 4 GB | Character LOB |
NCLOB | String | 4 GB | National character LOB |
BLOB | byte[] | 4 GB | Binary LOB |
- Kotlin
- Java
- Scala
val clobType: OracleType<String> = OracleTypes.clob
val nclobType: OracleType<String> = OracleTypes.nclob
val blobType: OracleType<ByteArray> = OracleTypes.blob
// Non-empty variants
val clobNonEmpty: OracleType<NonEmptyString> = OracleTypes.clobNonEmpty
val blobNonEmpty: OracleType<NonEmptyBlob> = OracleTypes.blobNonEmpty
OracleType<String> clobType = OracleTypes.clob;
OracleType<String> nclobType = OracleTypes.nclob;
OracleType<byte[]> blobType = OracleTypes.blob;
// Non-empty variants
OracleType<NonEmptyString> clobNonEmpty = OracleTypes.clobNonEmpty;
OracleType<NonEmptyBlob> blobNonEmpty = OracleTypes.blobNonEmpty;
val clobType: OracleType[String] = OracleTypes.clob
val nclobType: OracleType[String] = OracleTypes.nclob
val blobType: OracleType[Array[Byte]] = OracleTypes.blob
// Non-empty variants
val clobNonEmpty: OracleType[NonEmptyString] = OracleTypes.clobNonEmpty
val blobNonEmpty: OracleType[NonEmptyBlob] = OracleTypes.blobNonEmpty
Binary Types
| Oracle Type | Java Type | Max Length | Notes |
|---|---|---|---|
RAW(n) | byte[] | 2000 bytes | Variable-length binary |
LONG RAW | byte[] | 2 GB | Deprecated, use BLOB |
- Kotlin
- Java
- Scala
val rawType: OracleType<ByteArray> = OracleTypes.raw
val raw100: OracleType<ByteArray> = OracleTypes.raw(100) // RAW(100)
// Non-empty variant
val rawNonEmpty: OracleType<NonEmptyBlob> = OracleTypes.rawNonEmpty(100)
OracleType<byte[]> rawType = OracleTypes.raw;
OracleType<byte[]> raw100 = OracleTypes.raw(100); // RAW(100)
// Non-empty variant
OracleType<NonEmptyBlob> rawNonEmpty = OracleTypes.rawNonEmpty(100);
val rawType: OracleType[Array[Byte]] = OracleTypes.raw
val raw100: OracleType[Array[Byte]] = OracleTypes.raw(100) // RAW(100)
// Non-empty variant
val rawNonEmpty: OracleType[NonEmptyBlob] = OracleTypes.rawNonEmpty(100)
Date/Time Types
| Oracle Type | Java Type | Notes |
|---|---|---|
DATE | LocalDateTime | Date + time (second precision) |
TIMESTAMP | LocalDateTime | Fractional seconds (default: 6) |
TIMESTAMP WITH TIME ZONE | OffsetDateTime | Explicit timezone |
TIMESTAMP WITH LOCAL TIME ZONE | Instant | Session timezone |
- Kotlin
- Java
- Scala
val dateType: OracleType<LocalDateTime> = OracleTypes.date
val tsType: OracleType<LocalDateTime> = OracleTypes.timestamp
val ts3: OracleType<LocalDateTime> = OracleTypes.timestamp(3) // TIMESTAMP(3)
val tstz: OracleType<OffsetDateTime> = OracleTypes.timestampWithTimeZone
val tsltz: OracleType<Instant> = OracleTypes.timestampWithLocalTimeZone
OracleType<LocalDateTime> dateType = OracleTypes.date;
OracleType<LocalDateTime> tsType = OracleTypes.timestamp;
OracleType<LocalDateTime> ts3 = OracleTypes.timestamp(3); // TIMESTAMP(3)
OracleType<OffsetDateTime> tstz = OracleTypes.timestampWithTimeZone;
OracleType<Instant> tsltz = OracleTypes.timestampWithLocalTimeZone;
val dateType: OracleType[LocalDateTime] = OracleTypes.date
val tsType: OracleType[LocalDateTime] = OracleTypes.timestamp
val ts3: OracleType[LocalDateTime] = OracleTypes.timestamp(3) // TIMESTAMP(3)
val tstz: OracleType[OffsetDateTime] = OracleTypes.timestampWithTimeZone
val tsltz: OracleType[Instant] = OracleTypes.timestampWithLocalTimeZone
Note: Oracle DATE includes time (unlike SQL standard), so it maps to LocalDateTime, not LocalDate.
Interval Types
| Oracle Type | Java Type | Notes |
|---|---|---|
INTERVAL YEAR TO MONTH | OracleIntervalYM | Years and months |
INTERVAL DAY TO SECOND | OracleIntervalDS | Days, hours, minutes, seconds |
- Kotlin
- Java
- Scala
val ymType: OracleType<OracleIntervalYM> = OracleTypes.intervalYearToMonth
val ym4: OracleType<OracleIntervalYM> = OracleTypes.intervalYearToMonth(4)
val dsType: OracleType<OracleIntervalDS> = OracleTypes.intervalDayToSecond
val ds96: OracleType<OracleIntervalDS> = OracleTypes.intervalDayToSecond(9, 6)
// Create and use intervals
val interval: OracleIntervalYM = OracleIntervalYM.parse("+02-05") // 2 years, 5 months
val oracle: String = interval.toOracleFormat() // "+02-05"
val iso: String = interval.toIso8601() // "P2Y5M"
OracleType<OracleIntervalYM> ymType = OracleTypes.intervalYearToMonth;
OracleType<OracleIntervalYM> ym4 = OracleTypes.intervalYearToMonth(4);
OracleType<OracleIntervalDS> dsType = OracleTypes.intervalDayToSecond;
OracleType<OracleIntervalDS> ds96 = OracleTypes.intervalDayToSecond(9, 6);
// Create and use intervals
OracleIntervalYM interval = OracleIntervalYM.parse("+02-05"); // 2 years, 5 months
String oracle = interval.toOracleFormat(); // "+02-05"
String iso = interval.toIso8601(); // "P2Y5M"
val ymType: OracleType[OracleIntervalYM] = OracleTypes.intervalYearToMonth
val ym4: OracleType[OracleIntervalYM] = OracleTypes.intervalYearToMonth(4)
val dsType: OracleType[OracleIntervalDS] = OracleTypes.intervalDayToSecond
val ds96: OracleType[OracleIntervalDS] = OracleTypes.intervalDayToSecond(9, 6)
// Create and use intervals
val interval: OracleIntervalYM = OracleIntervalYM.parse("+02-05") // 2 years, 5 months
val oracle: String = interval.toOracleFormat() // "+02-05"
val iso: String = interval.toIso8601() // "P2Y5M"
ROWID Types
| Oracle Type | Java Type | Notes |
|---|---|---|
ROWID | String | Physical row address (18 chars) |
UROWID | String | Universal ROWID (max 4000 bytes) |
- Kotlin
- Java
- Scala
val rowidType: OracleType<String> = OracleTypes.rowId
val urowidType: OracleType<String> = OracleTypes.uRowId
val urowid1000: OracleType<String> = OracleTypes.uRowId(1000)
OracleType<String> rowidType = OracleTypes.rowId;
OracleType<String> urowidType = OracleTypes.uRowId;
OracleType<String> urowid1000 = OracleTypes.uRowId(1000);
val rowidType: OracleType[String] = OracleTypes.rowId
val urowidType: OracleType[String] = OracleTypes.uRowId
val urowid1000: OracleType[String] = OracleTypes.uRowId(1000)
XML and JSON Types
| Oracle Type | Java Type | Notes |
|---|---|---|
XMLTYPE | String | XML document storage |
JSON | Json | Native JSON (Oracle 21c+) |
- Kotlin
- Java
- Scala
val xmlType: OracleType<String> = OracleTypes.xmlType
val jsonType: OracleType<Json> = OracleTypes.json
val data: Json = Json("{\"name\": \"Oracle\"}")
OracleType<String> xmlType = OracleTypes.xmlType;
OracleType<Json> jsonType = OracleTypes.json;
Json data = new Json("{\"name\": \"Oracle\"}");
val xmlType: OracleType[String] = OracleTypes.xmlType
val jsonType: OracleType[Json] = OracleTypes.json
val data: Json = new Json("{\"name\": \"Oracle\"}")
OBJECT Types
Oracle OBJECT types (user-defined types) are supported via generated code:
// Generated code creates OracleType for your OBJECT type
// Example for ADDRESS_T type:
OracleType<AddressT> addressType = AddressT.oracleType;
// Insert using the generated type
AddressT addr = new AddressT("123 Main St", "City", "12345");
Nested Tables and VARRAYs
Oracle collection types are fully supported:
// Nested tables - generated as List<Element>
OracleType<List<String>> stringTable = // generated
// VARRAYs - generated as arrays
OracleType<String[]> stringVarray = // generated
Nullable Types
Any type can be made nullable using .opt():
- Kotlin
- Java
- Scala
val notNull: OracleType<Int> = OracleTypes.numberInt
val nullable: OracleType<Int?> = OracleTypes.numberInt.opt()
OracleType<Integer> notNull = OracleTypes.numberInt;
OracleType<Optional<Integer>> nullable = OracleTypes.numberInt.opt();
val notNull: OracleType[Int] = OracleTypes.numberInt
val nullable: OracleType[Option[Int]] = OracleTypes.numberInt.opt
Custom Domain Types
Wrap base types with custom Java types using transform:
- Kotlin
- Java
- Scala
// Wrapper type
data class EmployeeId(val value: Long)
// Create OracleType from NUMBER
val empIdType: OracleType<EmployeeId> =
OracleTypes.numberLong.transform(::EmployeeId, EmployeeId::value)
// Wrapper type
public record EmployeeId(Long value) {}
// Create OracleType from NUMBER
OracleType<EmployeeId> empIdType =
OracleTypes.numberLong.transform(EmployeeId::new, EmployeeId::value);
// Wrapper type
case class EmployeeId(value: Long)
// Create OracleType from NUMBER
val empIdType: OracleType[EmployeeId] =
OracleTypes.numberLong.transform(EmployeeId.apply, _.value)