- java.lang.Object
-
- org.jooq.impl.DefaultRecordMapper<R,E>
-
- All Implemented Interfaces:
RecordMapper<R,E>
public class DefaultRecordMapper<R extends Record,E> extends Object implements RecordMapper<R,E>
This is the default implementation forRecordMapper
types.The mapping algorithm is this:
If
<E>
is an array type:The resulting array is of the nature described in
Record.intoArray()
. Arrays more specific thanObject[]
can be specified as well, e.g.String[]
. If conversion to the element type of more specific arrays fails, aMappingException
is thrown, wrapping conversion exceptions.If
<E>
is a field "value type" and<R>
has exactly one column:Any Java type available from
SQLDataType
qualifies as a well-known "value type" that can be converted from a single-fieldRecord1
. The following rules apply:- If
<E>
is a reference type likeString
,Integer
,Long
,Timestamp
, etc., then converting from<R>
to<E>
is mere convenience for callingRecord.getValue(int, Class)
withfieldIndex = 0
- If
<E>
is a primitive type, the mapping result will be the corresponding wrapper type.null
will map to the primitive type's initialisation value, e.g.0
forint
,0.0
fordouble
,false
forboolean
.
If a default constructor is available and any JPA
Column
annotations are found on the provided<E>
, only those are used:- If
<E>
contains single-argument instance methods of any visibility annotated withColumn
, those methods are invoked - If
<E>
contains no-argument instance methods of any visibility starting withgetXXX
orisXXX
, annotated withColumn
, then matchingsetXXX()
instance methods of any visibility are invoked - If
<E>
contains instance member fields of any visibility annotated withColumn
, those members are set
- The same annotation can be re-used for several methods/members
Column.name()
must matchField.getName()
. All other annotation attributes are ignored- Static methods / member fields are ignored
- Final member fields are ignored
If a default constructor is available and if there are no JPA
Column
annotations, or jOOQ can't find thejavax.persistence
API on the classpath, jOOQ will mapRecord
values by naming convention:If
Field.getName()
isMY_field
(case-sensitive!), then this field's value will be set on all of these (regardless of visibility):- Single-argument instance method
MY_field(...)
- Single-argument instance method
myField(...)
- Single-argument instance method
setMY_field(...)
- Single-argument instance method
setMyField(...)
- Non-final instance member field
MY_field
- Non-final instance member field
myField
If
Field.getName()
isMY_field.MY_nested_field
(case-sensitive!), then this field's value will be considered a nested valueMY_nested_field
, which is set on a nested POJO that is passed to all of these (regardless of visibility):- Single-argument instance method
MY_field(...)
- Single-argument instance method
myField(...)
- Single-argument instance method
setMY_field(...)
- Single-argument instance method
setMyField(...)
- Non-final instance member field
MY_field
- Non-final instance member field
myField
If no default constructor is available, but at least one constructor annotated with
ConstructorProperties
is available, that one is used- The standard JavaBeans
ConstructorProperties
annotation is used to match constructor arguments against POJO members or getters. - If the property names provided to the constructor match the record's columns via the aforementioned naming conventions, that information is used.
- If those POJO members or getters have JPA annotations, those will be used
according to the aforementioned rules, in order to map
Record
values onto constructor arguments. - If those POJO members or getters don't have JPA annotations, the
aforementioned naming conventions will be used, in order to map
Record
values onto constructor arguments. - When several annotated constructors are found, the first one is chosen, randomly.
- When invoking the annotated constructor, values are converted onto constructor argument types
If no default constructor is available, but at least one "matching" constructor is available, that one is used
- A "matching" constructor is one with exactly as many arguments as this record holds fields
- When several "matching" constructors are found, the first one is chosen
(as reported by
Class.getDeclaredConstructors()
). This choice is non-deterministic as neither the JVM nor the JDK guarantee any order of methods or constructors. - When
Settings.isMapConstructorParameterNames()
is turned on, and parameter names are available through reflection onExecutable.getParameters()
, then values are mapped by name, otherwise by index. (see #4627) - When invoking the "matching" constructor, values are converted onto constructor argument types
If no default constructor is available, no "matching" constructor is available, but
Settings.isMapConstructorParameterNames()
is turned on, and parameter names are available through reflection onExecutable.getParameters()
, the first constructor is used- The first constructor is chosen (as reported by
Class.getDeclaredConstructors()
). This choice is non-deterministic as neither the JVM nor the JDK guarantee any order of methods or constructors. - When invoking that constructor, values are converted onto constructor argument types
If the supplied type is an interface or an abstract class
Abstract types are instantiated using Java reflection
Proxy
mechanisms. The returned proxy will wrap aHashMap
containing properties mapped by getters and setters of the supplied type. Methods (even JPA-annotated ones) other than standard POJO getters and setters are not supported. Details can be seen inReflect.as(Class)
.Other restrictions
<E>
must provide a default or a "matching" constructor. Non-public default constructors are made accessible usingConstructor.setAccessible(boolean)
- primitive types are supported. If a value is
null
, this will result in setting the primitive type's default value (zero for numbers, orfalse
for booleans). Hence, there is no way of distinguishingnull
and0
in that case.
This mapper is returned by the
DefaultRecordMapperProvider
. You can override this behaviour by specifying your own customRecordMapperProvider
inConfiguration.recordMapperProvider()
- Author:
- Lukas Eder
- See Also:
RecordMapper
,DefaultRecordMapperProvider
,Configuration
-
-
Constructor Summary
Constructors Constructor Description DefaultRecordMapper(RecordType<R> rowType, Class<? extends E> type)
Create a newDefaultRecordMapper
.DefaultRecordMapper(RecordType<R> rowType, Class<? extends E> type, Configuration configuration)
Create a newDefaultRecordMapper
.
-
-
-
Constructor Detail
-
DefaultRecordMapper
public DefaultRecordMapper(RecordType<R> rowType, Class<? extends E> type)
Create a newDefaultRecordMapper
.This constructor uses a new
DefaultConfiguration
internally to cache various reflection methods. For better performance, useDefaultRecordMapper(RecordType, Class, Configuration)
instead.
-
DefaultRecordMapper
public DefaultRecordMapper(RecordType<R> rowType, Class<? extends E> type, Configuration configuration)
Create a newDefaultRecordMapper
.
-
-
Method Detail
-
map
public final E map(R record)
Description copied from interface:RecordMapper
Map a record into a POJO.- Specified by:
map
in interfaceRecordMapper<R extends Record,E>
- Parameters:
record
- The record to be mapped. This is never null.
-
-