Custom Data Types
By now we've used Param and Row quite a bit. If you utilized Table, then you also used SqlType
However, as your plugin gets more advanced, you may find yourself needing to store data that does not have an equivalent built into the SQLite API. This guide will walk you through creating your own data type.
Defining a Custom Type
A custom type is simply an implementation of SqlType. You may store these implementations anywhere, but it's recommended to keep them in their own class for modularity's sake. Just like Table, it's also recommended to make these objects static, as they do not store state and are not instantiated.
To create a custom SqlType, first decide what type you want to implement. For this example, we'll create a custom type that handles Instant objects. Let's go ahead and create the entire type now, then break it down piece by piece. Here is the custom type for an Instant:
Breaking It Down
A SqlType must contain two methods:
public void bind(PreparedStatement ps, int index, Instant value) throws SQLException;public T read(ResultSet rs, String column) throws SQLException;
bind()The
bind()method is the method thatParamcalls under the hood, and is responsible for converting the Java object's value to the underlying SQLite data type and binding it to the placeholder at a given index.read()The
read()method is the method thatRowcalls under the hood, and it does the exact opposite ofbind(). It is responsible for reading the value of the object in theResultSetin the given column, and converting it to the respective Java object.
Using a Custom Type
Now that we have our custom types created, we can use them wherever we need. Custom data types are supported with Row, Param, and Table.Column<T>
Use your custom data type in rows when you want to query data and convert a column to your custom type. A special helper method, Row#get() exists specifically for this purpose.
The SQLite API will handle calling CustomTypes.INSTANT.read() when it converts the column to an object
Use your custom data type in params when you want to query the database by a custom data type. A special helper method, Param#of() exists to fulfill this use case.
The SQLite API will handle calling CustomTypes.INSTANT.bind() when it converts the value provided in Param#of() to the respective SQLite datatype.
The last way to use a custom type is with Table Columns. This replaces the need to use Param#of(), but does not replace the need to use Row#get().
As previously discussed in the Convenience Methods guide, the Table.Column<T>#param() method will return the correct Param object for the column.