DataNucleus allows you to provide alternate ways of persisting Java types. Whilst it includes the majority of normal converters built-in, you can extend DataNucleus capabilities using the plugin extension org.datanucleus.type_converter.
This guide relates to current DataNucleus GitHub. Please consult the DataNucleus source code if you are using an earlier version since things may be different in other versions.
Any type converter plugin will need to implement org.datanucleus.store.types.converters.TypeConverter . So you need to implement the following interface
public interface TypeConverter<X, Y> extends Serializable { /** * Method to convert the passed member value to the datastore type. * @param memberValue Value from the member * @return Value for the datastore */ Y toDatastoreType(X memberValue); /** * Method to convert the passed datastore value to the member type. * @param datastoreValue Value from the datastore * @return Value for the member */ X toMemberType(Y datastoreValue); }
Lets take an example. If we look at the Java type URI we want to persist it as a String since a native URI type isnt present in datastores. We define our class as
public class URIStringConverter implements TypeConverter<URI, String> { public URI toMemberType(String str) { if (str == null) { return null; } return java.net.URI.create(str.trim()); } public String toDatastoreType(URI uri) { return uri != null ? uri.toString() : null; } }
So when converting it for the datastore it will use the toString() form of the URI, and will be converted back to a URI (on retrieval from the datastore) using the URI.create method. Obviously this particular TypeConverter is included in DataNucleus, but hopefully it gives an idea of what to do to provide your own.
Some datastore plugins may support schemas where you can put an upper limit on the length of columns (e.g RDBMS). You can build this information into your TypeConverter plugin by also implementing the interface ColumnLengthDefiningTypeConverter which simply means adding the method int getDefaultColumnLength(int columnPosition).
The default is to convert a member type to a single column type in the datastore. DataNucleus allows you to convert to multiple columns, for example imagine a type Point that has an x and y. You want to persist this into 2 columns, the x stored in column 0, and the y stored in column 1. So now you update your TypeConverter to also implement MultiColumnConverter which simply means adding the method Class[] getDatastoreColumnTypes().
So we now have our custom value generator and we just need to make this into a DataNucleus plugin. To do this you simply add a file plugin.xml to your JAR at the root. The file plugin.xml should look like this
<?xml version="1.0"?> <plugin id="mydomain" name="DataNucleus plug-ins" provider-name="My Company"> <extension point="org.datanucleus.type_converter"> <type-converter name="dn.uri-string" member-type="java.net.URI" datastore-type="java.lang.String" converter-class="mydomain.converters.URIStringConverter"/> </extension> </plugin>
Note that you also require a MANIFEST.MF file as per the Extensions Guide.
The name dn.uri-string can be used to refer to this converter from within a java_types extension point definition for the default converter to use for a Java type.