| ## User-defined types |
| |
| ### Quick overview |
| |
| Ordered set of named, typed fields, e.g. `{ street: '1 Main St', zip: 12345}`. |
| |
| * `row.getUdtValue()` / `boundStatement.setUdtValue()`. |
| * positional or named getters and setters: `udtValue.getString("street")`, |
| `udtValue.setInt(1, 12345)`... |
| * getting hold of the [UserDefinedType]: |
| * statement or session metadata, or `udtValue.getType()`. |
| * `UserDefinedTypeBuilder` (not recommended, dangerous if you build a type that doesn't match the |
| database schema). |
| * creating a value from a type: `userDefinedType.newValue()`. |
| |
| ----- |
| |
| |
| [CQL user-defined types][cql_doc] are ordered sets of named, typed fields. They must be defined in a |
| keyspace: |
| |
| ``` |
| CREATE TYPE ks.type1 ( |
| a int, |
| b text, |
| c float); |
| ``` |
| |
| And can then be used as a column type in tables, or a field type in other user-defined types in that |
| keyspace: |
| |
| ``` |
| CREATE TABLE ks.collect_things ( |
| pk int, |
| ck1 text, |
| ck2 text, |
| v frozen<type1>, |
| PRIMARY KEY (pk, ck1, ck2) |
| ); |
| |
| CREATE TYPE ks.type2 (v frozen<type1>); |
| ``` |
| |
| ### Fetching UDTs from results |
| |
| The driver maps UDT columns to the [UdtValue] class, which exposes getters and setters to access |
| individual fields by index or name: |
| |
| ```java |
| Row row = session.execute("SELECT v FROM ks.collect_things WHERE pk = 1").one(); |
| |
| UdtValue udtValue = row.getUdtValue("v"); |
| int a = udtValue.getInt(0); |
| String b = udtValue.getString("b"); |
| Float c = udtValue.getFloat(2); |
| ``` |
| |
| ### Using UDTs as parameters |
| |
| Statements may contain UDTs as bound values: |
| |
| ```java |
| PreparedStatement ps = |
| session.prepare( |
| "INSERT INTO ks.collect_things (pk, ck1, ck2, v) VALUES (:pk, :ck1, :ck2, :v)"); |
| ``` |
| |
| To create a new UDT value, you must first have a reference to its [UserDefinedType]. There are |
| various ways to get it: |
| |
| * from the statement's metadata |
| |
| ```java |
| UserDefinedType udt = (UserDefinedType) ps.getVariableDefinitions().get("v").getType(); |
| ``` |
| |
| * from the driver's [schema metadata](../metadata/schema/): |
| |
| ```java |
| UserDefinedType udt = |
| session.getMetadata() |
| .getKeyspace("ks") |
| .flatMap(ks -> ks.getUserDefinedType("type1")) |
| .orElseThrow(() -> new IllegalArgumentException("Missing UDT definition")); |
| ``` |
| |
| * from another UDT value: |
| |
| ```java |
| UserDefinedType udt = udtValue.getType(); |
| ``` |
| |
| Note that the driver's official API does not expose a way to build [UserDefinedType] instances |
| manually. This is because the type's internal definition must precisely match the database schema; |
| if it doesn't (for example if the fields are not in the same order), you run the risk of inserting |
| corrupt data, that you won't be able to read back. There is still a way to do it with the driver, |
| but it's part of the [internal API](../../api_conventions/): |
| |
| ```java |
| // Advanced usage: make sure you understand the risks |
| import com.datastax.oss.driver.internal.core.type.UserDefinedTypeBuilder; |
| |
| UserDefinedType udt = |
| new UserDefinedTypeBuilder("ks", "type1") |
| .withField("a", DataTypes.INT) |
| .withField("b", DataTypes.TEXT) |
| .withField("c", DataTypes.FLOAT) |
| .build(); |
| ``` |
| |
| Note that a manually created type is [detached](../detachable_types). |
| |
| |
| Once you have the type, call `newValue()` and set the fields: |
| |
| ```java |
| UdtValue udtValue = udt.newValue().setInt(0, 1).setString(1, "hello").setFloat(2, 2.3f); |
| |
| // Or as a one-liner for convenience: |
| UdtValue udtValue = udt.newValue(1, "hello", 2.3f); |
| ``` |
| |
| And bind your UDT value like any other type: |
| |
| ```java |
| BoundStatement bs = |
| ps.boundStatementBuilder() |
| .setInt("pk", 1) |
| .setString("ck1", "1") |
| .setString("ck2", "1") |
| .setUdtValue("v", udtValue) |
| .build(); |
| session.execute(bs); |
| ``` |
| |
| [cql_doc]: https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlRefUDType.html |
| |
| [UdtValue]: https://docs.datastax.com/en/drivers/java/4.8/com/datastax/oss/driver/api/core/data/UdtValue.html |
| [UserDefinedType]: https://docs.datastax.com/en/drivers/java/4.8/com/datastax/oss/driver/api/core/type/UserDefinedType.html |