When persisting a class, a persistence solution needs to know how to persist the types of each field in the class. Clearly a persistence solution can only support a finite number of Java types; it cannot know how to persist every possible type creatable. The JDO specification define lists of types that are required to be supported by all implementations of those specifications. This support can be conveniently split into two parts
An object that can be referred to (object reference, providing a relation) and that has an "identity" is termed a First Class Object (FCO). DataNucleus supports the following Java types as FCO
An object that does not have an "identity" is termed a Second Class Object (SCO). This is something like a String or Date field in a class, or alternatively a Collection (that contains other objects). The table below shows the currently supported SCO java types in DataNucleus. The table shows
Java Type | Extension? | DFG? | Persistent? | Proxied? | PK? | Plugin |
---|---|---|---|---|---|---|
boolean | datanucleus-core | |||||
byte | datanucleus-core | |||||
char | datanucleus-core | |||||
double | datanucleus-core | |||||
float | datanucleus-core | |||||
int | datanucleus-core | |||||
long | datanucleus-core | |||||
short | datanucleus-core | |||||
boolean[] | datanucleus-core | |||||
byte[] | datanucleus-core | |||||
char[] | datanucleus-core | |||||
double[] | datanucleus-core | |||||
float[] | datanucleus-core | |||||
int[] | datanucleus-core | |||||
long[] | datanucleus-core | |||||
short[] | datanucleus-core | |||||
java.lang.Boolean | datanucleus-core | |||||
java.lang.Byte | datanucleus-core | |||||
java.lang.Character | datanucleus-core | |||||
java.lang.Double | datanucleus-core | |||||
java.lang.Float | datanucleus-core | |||||
java.lang.Integer | datanucleus-core | |||||
java.lang.Long | datanucleus-core | |||||
java.lang.Short | datanucleus-core | |||||
java.lang.Boolean[] | datanucleus-core | |||||
java.lang.Byte[] | datanucleus-core | |||||
java.lang.Character[] | datanucleus-core | |||||
java.lang.Double[] | datanucleus-core | |||||
java.lang.Float[] | datanucleus-core | |||||
java.lang.Integer[] | datanucleus-core | |||||
java.lang.Long[] | datanucleus-core | |||||
java.lang.Short[] | datanucleus-core | |||||
java.lang.Number [2] | datanucleus-core | |||||
java.lang.Object | datanucleus-core | |||||
java.lang.String | datanucleus-core | |||||
java.lang.StringBuffer [1] | datanucleus-core | |||||
java.lang.String[] | datanucleus-core | |||||
java.lang.Class | datanucleus-core | |||||
java.math.BigDecimal | datanucleus-core | |||||
java.math.BigInteger | datanucleus-core | |||||
java.math.BigDecimal[] | datanucleus-core | |||||
java.math.BigInteger[] | datanucleus-core | |||||
java.sql.Date | datanucleus-core | |||||
java.sql.Time | datanucleus-core | |||||
java.sql.Timestamp | datanucleus-core | |||||
java.util.ArrayList | datanucleus-core | |||||
java.util.BitSet | datanucleus-core | |||||
java.util.Calendar [5] | datanucleus-core | |||||
java.util.Collection | datanucleus-core | |||||
java.util.Currency | datanucleus-core | |||||
java.util.Date | datanucleus-core | |||||
java.util.Date[] | datanucleus-core | |||||
java.util.GregorianCalendar [5] | datanucleus-core | |||||
java.util.HashMap | datanucleus-core | |||||
java.util.HashSet | datanucleus-core | |||||
java.util.Hashtable | datanucleus-core | |||||
java.util.LinkedHashMap [3] | datanucleus-core | |||||
java.util.LinkedHashSet [4] | datanucleus-core | |||||
java.util.LinkedList | datanucleus-core | |||||
java.util.List | datanucleus-core | |||||
java.util.Locale | datanucleus-core | |||||
java.util.Locale[] | datanucleus-core | |||||
java.util.Map | datanucleus-core | |||||
java.util.Properties | datanucleus-core | |||||
java.util.PriorityQueue | datanucleus-core | |||||
java.util.Queue | datanucleus-core | |||||
java.util.Set | datanucleus-core | |||||
java.util.SortedMap | datanucleus-core | |||||
java.util.SortedSet | datanucleus-core | |||||
java.util.Stack | datanucleus-core | |||||
java.util.TimeZone | datanucleus-core | |||||
java.util.TreeMap | datanucleus-core | |||||
java.util.TreeSet | datanucleus-core | |||||
java.util.UUID | datanucleus-core | |||||
java.util.Vector | datanucleus-core | |||||
java.awt.Color | datanucleus-core | |||||
java.awt.image.BufferedImage | datanucleus-core | |||||
java.awt.Point | datanucleus-geospatial | |||||
java.awt.Rectangle | datanucleus-geospatial | |||||
java.net.URI | datanucleus-core | |||||
java.net.URL | datanucleus-core | |||||
java.io.Serializable | datanucleus-core | |||||
java.io.File [6] | datanucleus-rdbms | |||||
Persistable | datanucleus-core | |||||
Persistable[] | datanucleus-core | |||||
java.lang.Enum | datanucleus-core | |||||
java.lang.Enum[] | datanucleus-core | |||||
java.time.LocalDateTime | datanucleus-java8 | |||||
java.time.LocalTime | datanucleus-java8 | |||||
java.time.LocalDate | datanucleus-java8 | |||||
java.time.MonthDay | datanucleus-java8 | |||||
java.time.YearMonth | datanucleus-java8 | |||||
java.time.Year | datanucleus-java8 | |||||
java.time.Period | datanucleus-java8 | |||||
java.time.Instant | datanucleus-java8 | |||||
java.time.Duration | datanucleus-java8 | |||||
java.time.ZoneId | datanucleus-java8 | |||||
java.time.ZoneOffset | datanucleus-java8 | |||||
org.joda.time.DateTime | datanucleus-jodatime | |||||
org.joda.time.LocalTime | datanucleus-jodatime | |||||
org.joda.time.LocalDate | datanucleus-jodatime | |||||
org.joda.time.LocalDateTime | datanucleus-jodatime | |||||
org.joda.time.Duration | datanucleus-jodatime | |||||
org.joda.time.Interval | datanucleus-jodatime | |||||
org.joda.time.Period | datanucleus-jodatime | |||||
com.google.common.collect.Multiset | datanucleus-guava |
Note that support is available for persisting other types depending on the datastore to which you are persisting
If you have support for any additional types and would either like to contribute them, or have them listed here, let us know
You can add support for other basic Java types quite easily, particularly if you can store it as a String or Long and then retrieve it back into its object form from that - See the Java Types plugin-point You can also define more specific support for it with RDBMS datastores - See the RDBMS Java Types plugin-point
Handling of second-class types uses wrappers and bytecode enhancement with DataNucleus. This contrasts to what Hibernate uses (proxies), and what Hibernate imposes on you. See this blog entry if you have doubts about this approach.
SortedSet (and implementations) allow the user to have a comparator to order the elements of the set. When an object is pulled back from the datastore via query JDO would need to know the class name of the comparator to use. You specify it like this
@Element @Extension(vendorName="datanucleus", key="comparator-name", value="mydomain.model.MyComparator") SortedSet<MyElementType> elements;
and when instantiating the SortedSet field will create it with a comparator of the specified class (which must have a default constructor). Same for Queue, PriorityQueue and SortedMap.
By default an Enum is persisted as either a String form (the name), or as an integer form (the ordinal). You control which form by specifying the column jdbc-type.
An extension to this for RDBMS is where you have an Enum that defines its own "value"s for the different enum options.
public enum MyColour { RED((short)1), GREEN((short)3), BLUE((short)5), YELLOW((short)8); private short value; private MyColour(short value) { this.value = value; } public short getValue() { return value; } public static MyColour getEnumByValue(short value) { switch (value) { case 1: return RED; case 3: return GREEN; case 5: return BLUE; default: return YELLOW; } } }
With the default persistence it would persist as String-based, so persisting "RED" "GREEN" "BLUE" etc. With jdbc-type as INTEGER it would persist 0, 1, 2, 3 being the ordinal values. If you define the metadata as
@Extensions({ @Extension(vendorName="datanucleus", key="enum-getter-by-value", value="getEnumByValue"), @Extension(vendorName="datanucleus", key="enum-value-getter", value="getValue") }) MyColour colour;
this will now persist 1, 3, 5, 8, being the "value" of each of the enum options.
By default DataNucleus will store the value using its own internal configuration/default for the java type and for the datastore. The user can, however, change that by making use of a TypeConverter. You firstly need to define the TypeConverter class (assuming you aren't going to use an internal DataNucleus converter, and for this you should refer to the TypeConverter plugin-point. Once you have the converter defined, and registered in a plugin.xml under a name you then mark the field/property to use it
@Extension(vendorName="datanucleus", key="type-converter-name", value="kryo-serialise") String longString;
In this case we have a String field but we want to serialise it, not using normal Java serialisation but using the "Kryo" library. When it is stored it will be converted into a serialised form and when read back in will be deserialised. You can see the example Kryo TypeConverter over on GitHub.
You could try to persist Eclipse EMF models using the Texo project to generate POJOs