Author: gk
Date: Fri Oct 24 08:10:46 2025
New Revision: 1929318
Log:
Merged patch "Thread-safe record mapper speed-ups" from Max Philipp Wriedt,
cft. Torque-dev mailing list entry
https://lists.apache.org/thread/225tjo3y27n0gdtrt2yj3ntr7z4lx4g5.
Added:
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/mappingStrategyPath.vm
Modified:
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/MappingStrategy.java
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/RecordMapper.java
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/util/ResultsetSpliterator.java
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/outlets/recordMapper.xml
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/recordMapperBase.vm
Modified:
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/MappingStrategy.java
==============================================================================
---
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/MappingStrategy.java
Fri Oct 24 05:04:10 2025 (r1929317)
+++
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/MappingStrategy.java
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -28,78 +28,73 @@ import org.apache.commons.lang3.function
import org.apache.commons.lang3.tuple.Pair;
import org.apache.torque.TorqueException;
-
-/**
- * Mapping strategy used in processRow method of generated mappers.
- *
- * @param <T>
- */
-public class MappingStrategy<T> {
-
- /**
- * The {@link Pair#getLeft()} is to allow lazy sorting, {@link
Pair#getRight()} contains the object to be mapped
- */
- private final List<Pair<Integer, FailableBiConsumer<ResultSet, T,
TorqueException>>> tasks;
-
- private boolean allSet;
-
- public MappingStrategy()
- {
- this.tasks = new ArrayList<>();
- this.allSet = false;
- }
-
- public void addColumn(int offset, FailableBiConsumer<ResultSet, T,
TorqueException> setter)
- {
- this.tasks.add(Pair.of(offset, setter));
- }
-
- /**
- * Last finishing steps before execute.
- *
- * @param num_fields the total column size of the object
- * @param sort <code>true</code> explicitely sort with {@link
Pair#getLeft()} of the {@link #tasks}.
- */
- public void finish(int num_fields, boolean sort)
- {
- // The list should already be in the correct order because Criteria
loops through the columns
- // in the same order in which they are added to the SQL statement but
just in case something weird
+
+/**
+ * Mapping strategy used in processRow method of generated mappers.
+ *
+ * @param <T>
+ */
+public class MappingStrategy<T> {
+
+ /**
+ * The {@link Pair#getLeft()} is to allow lazy sorting, {@link
Pair#getRight()} contains the object to be mapped
+ */
+ private final List<Pair<Long, FailableBiConsumer<ResultSet, T,
TorqueException>>> tasks;
+
+ public MappingStrategy() {
+ this.tasks = new ArrayList<>();
+ }
+
+ /**
+ * Add a column to be set at the given offset (column).
+ * @param offset the column offset inside a Resultset at which the value
can be found.
+ * @param setter a method or lambda which actually sets the value.
+ */
+ public void addColumn(long offset, FailableBiConsumer<ResultSet, T,
TorqueException> setter)
+ {
+ this.tasks.add(Pair.of(offset, setter));
+ }
+
+ /**
+ * Last finishing steps before this strategy can be executed.
+ *
+ * @param sort <code>true</code> explicitly sort with {@link
Pair#getLeft()} of the {@link #tasks}.
+ */
+ public void finish(boolean sort)
+ {
+ // The list should already be in the correct order because Criteria
loops through the columns
+ // in the same order in which they are added to the SQL statement but
just in case something weird
// is being done this gets us closer to the desired contract of
ResultSet of looping over monotonically
// increasing indices of columns only.
- if (sort) {
- this.tasks.sort(Comparator.comparing(Pair::getLeft));
- }
- this.allSet = this.tasks.size() == num_fields;
- }
-
- public boolean isEmpty()
- {
- return this.tasks.isEmpty();
- }
-
- public boolean isAllSet() {
- return this.allSet;
- }
-
- public void reset()
- {
- // to use this and to use only a single strategy we might need to
Collections.sync(ArrayList).
+ if (sort) {
+ this.tasks.sort(Comparator.comparing(Pair::getLeft));
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return this.tasks.isEmpty();
+ }
+
+ public void reset()
+ {
+ // to use this and to use only a single strategy we might need to
Collections.sync(ArrayList).
this.tasks.clear();
}
-
- /**
- * Iterates through the {@link #tasks} list and executes each task.
- *
- * @param result Resultset
- * @param instance target object
- *
- */
- public void execute(ResultSet result, T instance)
- {
- this.tasks.stream().forEach( strategy ->
- {
- try
- {
+
+ /**
+ * Iterates through the {@link #tasks} list and executes each task.
+ *
+ * @param result Resultset
+ * @param instance target object
+ *
+ */
+ public void execute(ResultSet result, T instance)
+ {
+ this.tasks.forEach( strategy ->
+ {
+ try
+ {
strategy.getRight().accept( result, instance );
} catch (TorqueException e)
{
Modified:
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/RecordMapper.java
==============================================================================
---
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/RecordMapper.java
Fri Oct 24 05:04:10 2025 (r1929317)
+++
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/om/mapper/RecordMapper.java
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -62,4 +62,43 @@ public interface RecordMapper<T> extends
int rowOffset,
Criteria criteria)
throws TorqueException;
+
+ /**
+ * Constructs the object from the current row in the resultSet.
+ * Implementing methods can be sure that the resultSet contains a row,
+ * but they must only operate on the current row, i.e they must not call
+ * resultSet.next().
+ * This version may also receive a MappingStrategy object to speed up
+ * the processing. However, the default implementation disregards any
+ * passed strategy and simply forwards to processRow(ResultSet, int,
Criteria).
+ *
+ * @param resultSet the resultSet to operate on, already pointing
+ * to the correct row. Not null.
+ * @param rowOffset a possible offset in the columns to be considered
+ * (if previous columns contain other objects), or 0 for no offset.
+ * @param criteria the Criteria which contains the query to process,
+ * or null if not known or the query was not produced by a Criteria.
+ * Can be used by the RecordMapper to determine the columns
+ * contained in the result set.
+ * @param strategy the MappingStrategy which tells the RecordMapper which
+ * offsets in the resultSet correspond to which fields of T.
+ * Nay be null if not known.
+ *
+ * @return the mapped object, not null.
+ *
+ * @throws TorqueException when the mapping fails.
+ */
+ default T processRow(
+ ResultSet resultSet,
+ int rowOffset,
+ Criteria criteria,
+ MappingStrategy<T> strategy)
+ throws TorqueException {
+ return this.processRow(resultSet, rowOffset, criteria);
+ }
+
+ default MappingStrategy<T> generateStrategy(long rowOffset, Criteria
criteria)
+ {
+ return null;
+ }
}
Modified:
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/util/ResultsetSpliterator.java
==============================================================================
---
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/util/ResultsetSpliterator.java
Fri Oct 24 05:04:10 2025 (r1929317)
+++
db/torque/trunk/torque-runtime/src/main/java/org/apache/torque/util/ResultsetSpliterator.java
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -28,48 +28,53 @@ import java.util.function.Consumer;
import org.apache.torque.Database;
import org.apache.torque.Torque;
-import org.apache.torque.TorqueException;
-import org.apache.torque.TorqueRuntimeException;
-import org.apache.torque.criteria.Criteria;
-import org.apache.torque.om.mapper.RecordMapper;
-
-/**
+import org.apache.torque.TorqueException;
+import org.apache.torque.TorqueRuntimeException;
+import org.apache.torque.criteria.Criteria;
+import org.apache.torque.om.mapper.MappingStrategy;
+import org.apache.torque.om.mapper.RecordMapper;
+
+/**
* Stream support: Encapsulate iteration over a JDBC ResultSet
*
* @author <a href="mailto:[email protected]">Thomas Vandahl</a>
*/
-public class ResultsetSpliterator<T> extends AbstractSpliterator<T> implements
Runnable
-{
- private final RecordMapper<T> recordMapper;
- private final Criteria criteria;
- private final Statement statement;
- private final ResultSet resultSet;
+public class ResultsetSpliterator<T> extends AbstractSpliterator<T> implements
Runnable
+{
+ private final RecordMapper<T> recordMapper;
+ private final MappingStrategy<T> mappingStrategy;
+ private final Criteria criteria;
+ private final Statement statement;
+ private final ResultSet resultSet;
private long offset;
private long limit;
- private long rowNumber;
-
- /**
- * Constructor
- *
- * @param recordMapper a RecordMapper to map ResultSet rows to entities of
type T
- * @param criteria a Criteria
- * @param statement the statement that created the ResultSet
- * @param resultSet the JDBC result set
- * @throws TorqueException backend database exception
- */
- public ResultsetSpliterator(RecordMapper<T> recordMapper, Criteria
criteria,
- Statement statement, ResultSet resultSet) throws TorqueException
- {
- super(Long.MAX_VALUE, Spliterator.ORDERED);
-
+ private long rowNumber;
+
+ /**
+ * Constructor with an explicit MappingStrategy.
+ *
+ * @param recordMapper a RecordMapper to map ResultSet rows to entities of
type T
+ * @param criteria a Criteria
+ * @param statement the statement that created the ResultSet
+ * @param resultSet the JDBC result set
+ * @param mappingStrategy a MappingStrategy to use
+ * @throws TorqueException backend database exception
+ */
+ public ResultsetSpliterator(RecordMapper<T> recordMapper, Criteria
criteria,
+ Statement statement, ResultSet resultSet, MappingStrategy<T>
mappingStrategy) throws TorqueException
+ {
+ super(Long.MAX_VALUE, Spliterator.ORDERED);
+
this.recordMapper = recordMapper;
- this.criteria = criteria;
- this.statement = statement;
- this.resultSet = resultSet;
- this.offset = 0; //database takes care of offset
- this.limit = -1; //database takes care of limit
- this.rowNumber = 0;
+ this.criteria = criteria;
+ this.statement = statement;
+ this.resultSet = resultSet;
+ MappingStrategy<T> myMappingStrategy = mappingStrategy;
+
+ this.offset = 0; //database takes care of offset
+ this.limit = -1; //database takes care of limit
+ this.rowNumber = 0;
// Set offset and limit
if (criteria != null)
@@ -88,13 +93,34 @@ public class ResultsetSpliterator<T> ext
}
else if (criteria.getLimit() != -1)
{
- limit = offset + criteria.getLimit();
- }
- }
- }
- }
-
- /* (non-Javadoc)
+ limit = offset + criteria.getLimit();
+ }
+ }
+
+ // generate a strategy, if not already provided
+ if (mappingStrategy == null) {
+ myMappingStrategy = recordMapper.generateStrategy(offset,
criteria);
+ }
+ }
+ this.mappingStrategy = myMappingStrategy;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param recordMapper a RecordMapper to map ResultSet rows to entities of
type T
+ * @param criteria a Criteria
+ * @param statement the statement that created the ResultSet
+ * @param resultSet the JDBC result set
+ * @throws TorqueException backend database exception
+ */
+ public ResultsetSpliterator(RecordMapper<T> recordMapper, Criteria
criteria,
+ Statement statement, ResultSet resultSet)
throws TorqueException
+ {
+ this(recordMapper, criteria, statement, resultSet, null);
+ }
+
+ /* (non-Javadoc)
* @see java.util.Spliterator#tryAdvance(java.util.function.Consumer)
*
* Advance ResultSet and map row to entity <T>
@@ -114,13 +140,13 @@ public class ResultsetSpliterator<T> ext
if (limit >= 0 && rowNumber >= limit)
{
return false;
- }
-
- rowNumber++;
- T result = recordMapper.processRow(resultSet, 0, criteria);
- action.accept(result);
- return true;
- }
+ }
+
+ rowNumber++;
+ T result = recordMapper.processRow(resultSet, 0, criteria,
mappingStrategy);
+ action.accept(result);
+ return true;
+ }
}
catch (SQLException e)
{
Modified:
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/outlets/recordMapper.xml
==============================================================================
---
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/outlets/recordMapper.xml
Fri Oct 24 05:04:10 2025 (r1929317)
+++
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/outlets/recordMapper.xml
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -48,6 +48,10 @@
element="column"
outlet="torque.om.recordmapper.base.dbObjectFieldGetter"/>
</mergepoint>
+ <mergepoint name="mappingStrategyPath">
+ <action xsi:type="applyAction"
+ outlet="torque.om.recordmapper.base.mappingStrategyPath"/>
+ </mergepoint>
</outlet>
<outlet name="torque.om.recordmapper.base.dbObjectFieldGetter"
@@ -59,4 +63,18 @@
xsi:type="velocityOutlet"
path="recordmapper/base/createDbObjectInstanceFromInheritance.vm">
</outlet>
+
+ <outlet name="torque.om.recordmapper.base.mappingStrategyPath"
+ xsi:type="velocityOutlet"
+ path="recordmapper/base/mappingStrategyPath.vm">
+ <mergepoint name="createDbObjectInstance">
+ <action xsi:type="applyAction"
+ outlet="torque.om.createDbObjectInstance"/>
+ </mergepoint>
+ <mergepoint name="createDbObjectInstanceFromInheritance">
+ <action xsi:type="traverseAllAction"
+ element="inheritance-column"
+
outlet="torque.om.recordmapper.basecreateDbObjectInstanceFromInheritance"/>
+ </mergepoint>
+ </outlet>
</outlets>
\ No newline at end of file
Added:
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/mappingStrategyPath.vm
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/mappingStrategyPath.vm
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -0,0 +1,133 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+######
+##
+## version $Id: mappingStrategyPath.vm TIMESTAMP mwriedt $
+##
+## Creates the MappingStrategy flow for a RecordMapper.
+##
+## This template expects the current source element to be a "table" element
+## from the torque schema.
+## The schema needs to be processed by the OMTransformer.
+## The attributes of the current source element must be set
+## as velocity variables.
+##
+
+ @Override
+ public MappingStrategy<$dbObjectClassName> generateStrategy(long
rowOffset, Criteria criteria) {
+ if (criteria == null || criteria.isComposite())
+ {
+ return null;
+ }
+ List<Column> selectColumns = criteria.getSelectColumns();
+ List<Column> columnsWithoutOffset =
selectColumns.stream().skip(rowOffset).toList();
+ ## The selectColumns should not be empty here if we are called by the
usual ResultsetSpliterator.
+ if (columnsWithoutOffset.isEmpty())
+ {
+ return null;
+ }
+ MappingStrategy<$dbObjectClassName> strategy = new MappingStrategy<>();
+
+ Set<String> columnsMapped = new HashSet<>();
+ long physicalColumnIndex = rowOffset + 1;
+ for (Column column : columnsWithoutOffset)
+ {
+ #set ( $else = "" )
+ #foreach ($columnElement in $torqueGen.getChildren("column"))
+ #set ( $setter = $columnElement.getAttribute("setter") )
+ #set ( $getter = $columnElement.getAttribute("getter") )
+ #set ( $peerColumnName =
$columnElement.getAttribute("peerColumnName") )
+ ${else}if
(!columnsMapped.contains(${peerColumnName}_EXPRESSION ) &&
${peerColumnName}_EXPRESSION.equals(
+ column.getSqlExpression()))
+ {
+ int currentIndex = Math.toIntExact(physicalColumnIndex);
+ strategy.addColumn(physicalColumnIndex,
+ (res, inst) -> inst.${setter}(${getter}(res,
currentIndex)));
+ columnsMapped.add( ${peerColumnName}_EXPRESSION );
+ }
+ #set ( $else = "else " )
+ #end
+ physicalColumnIndex++;
+ }
+ if (columnsMapped.isEmpty())
+ {
+ return null;
+ }
+ return strategy;
+ }
+
+ /**
+ * Constructs the object from the current row in the resultSet.
+ * Implementing methods can be sure that the resultSet contains a row,
+ * but they must only operate on the current row, i.e they must not call
+ * resultSet.next().
+ * This version may also receive a MappingStrategy object to speed up
+ * the processing. However, the default implementation disregards any
+ * passed strategy and simply forwards to processRow(ResultSet, int,
Criteria). //FIXME: Fix doclink!
+ *
+ * @param resultSet the resultSet to operate on, already pointing
+ * to the correct row. Not null.
+ * @param offset a possible offset in the columns to be considered
+ * (if previous columns contain other objects), or 0 for no offset.
+ * @param criteria the Criteria which contains the query to process,
+ * or null if not known or the query was not produced by a Criteria.
+ * Can be used by the RecordMapper to determine the columns
+ * contained in the result set.
+ * @param strategy the MappingStrategy which tells the RecordMapper which
+ * offsets in the resultSet correspond to which fields of T.
+ * Nay be null if not known.
+ *
+ * @return the mapped object, not null.
+ *
+ * @throws TorqueException when the mapping fails.
+ */
+ @Override
+ public ${dbObjectClassName} processRow(
+ ResultSet resultSet,
+ int offset,
+ Criteria criteria,
+ MappingStrategy<${dbObjectClassName}> strategy)
+ throws TorqueException {
+ if (strategy != null)
+ {
+#set ( $inheritanceBaseColumnElement =
$torqueGen.getChild("inheritance-column") )
+#if ($inheritanceBaseColumnElement)
+ $torqueGen.mergepoint("createDbObjectInstanceFromInheritance")
+#else
+ $torqueGen.mergepoint("createDbObjectInstance")
+#end
+
+#if ($torqueGen.booleanOption("torque.om.trackLoading"))
+ try
+ {
+ ${field}.setLoading(true);
+#end
+ strategy.execute(resultSet, ${field});
+ ${field}.setNew(false);
+ ${field}.setModified(false);
+#if ($torqueGen.booleanOption("torque.om.trackLoading"))
+ }
+ finally
+ {
+ ${field}.setLoading(false);
+ }
+#end
+ return ${field};
+ }
+ return this.processRow(resultSet, offset, criteria);
+ }
\ No newline at end of file
Modified:
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/recordMapperBase.vm
==============================================================================
---
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/recordMapperBase.vm
Fri Oct 24 05:04:10 2025 (r1929317)
+++
db/torque/trunk/torque-templates/src/main/resources/org/apache/torque/templates/om/templates/recordmapper/base/recordMapperBase.vm
Fri Oct 24 08:10:46 2025 (r1929318)
@@ -16,42 +16,44 @@
## under the License.
##
######
-##
-## version $Id$
-##
-## Creates the base peer's mapper class.
-##
-## This template expects the current source element to be a "table" element
-## from the torque schema.
-## The schema needs to be processed by the OMTransformer.
-## The attributes of the current source element must be set
-## as velocity variables.
-##
-package ${baseRecordMapperPackage};
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+##
+## version $Id$
+##
+## Creates the base peer's mapper class.
+##
+## This template expects the current source element to be a "table" element
+## from the torque schema.
+## The schema needs to be processed by the OMTransformer.
+## The attributes of the current source element must be set
+## as velocity variables.
+##
+package ${baseRecordMapperPackage};
+
+import java.io.Serial;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.torque.Column;
import org.apache.torque.TorqueException;
import org.apache.torque.criteria.Criteria;
import org.apache.torque.om.mapper.RecordMapper;
-import org.apache.torque.om.mapper.MappingStrategy;
-
-#foreach ($columnElement in
$torqueGen.getSourceElement().getChildren("column"))
- #set ($colEnumPackage = $columnElement.getAttribute("enumPackage"))
- #set ($colEnumClassName = $columnElement.getAttribute("enumClassName"))
- #if ($columnElement.getAttribute("isEnum") == "true" && $colEnumPackage !=
$baseRecordMapperPackage)
-import ${colEnumPackage}.${colEnumClassName};
- #end
-#end
-#if (${baseRecordMapperPackage} != $dbObjectPackage)
-import ${dbObjectPackage}.${dbObjectClassName};
+import org.apache.torque.om.mapper.MappingStrategy;
+
+#foreach ($columnElement in
$torqueGen.getSourceElement().getChildren("column"))
+ #set ($colEnumPackage = $columnElement.getAttribute("enumPackage"))
+ #set ($colEnumClassName = $columnElement.getAttribute("enumClassName"))
+ #if ($columnElement.getAttribute("isEnum") == "true" && $colEnumPackage !=
$baseRecordMapperPackage)
+ import ${colEnumPackage}.${colEnumClassName};
+ #end
+#end
+#if (${baseRecordMapperPackage} != $dbObjectPackage)
+import ${dbObjectPackage}.${dbObjectClassName};
#end
#if (${baseRecordMapperPackage} != $peerPackage)
import ${peerPackage}.${peerClassName};
@@ -60,179 +62,126 @@ import ${peerPackage}.${peerClassName};
import ${basePeerPackage}.${basePeerClassName};
#end
-#set ( $inheritanceBaseColumnElements =
$torqueGen.getChildren("inheritance-column"))
-## there should at most be one inheritance-column in each table
-#foreach ($inheritanceBaseColumnElement in $inheritanceBaseColumnElements)
- #set ( $columnElement = $inheritanceBaseColumnElement.getChild("column") )
- #set ( $inheritanceElements = $columnElement.getChildren("inheritance"))
- #if ($inheritanceElements.size() > 0)
- #if (${baseRecordMapperPackage} != $dbObjectPackage)
- #foreach ($inheritanceElement in $inheritanceElements)
- #set ( $inheritanceClassName =
$inheritanceElement.getAttribute("className") )
-import ${dbObjectPackage}.${inheritanceClassName};
- #end
- #end
- #end
-#end
-/**
- * Maps ResultSet rows into ${dbObjectClassName} objects.
- *
-#if ($torqueGen.booleanOption("torque.om.addTimeStamp"))
- * The skeleton for this class was autogenerated by Torque on:
- *
- * [${torqueGen.now()}]
- *
-#end
- */
-@SuppressWarnings("unused")
-public class ${baseRecordMapperClassName} implements
RecordMapper<${dbObjectClassName}>
-{
-#if ($torqueGen.booleanOption("torque.om.addTimeStamp"))
- /** Serial version */
- private static final long serialVersionUID = ${torqueGen.now().Time}L;
-
-#else
- /** Serial version */
- private static final long serialVersionUID = 1L;
-
-#end
- /** The class log. */
- private static Log log
- = LogFactory.getLog(${baseRecordMapperClassName}.class);
-
- ## TORQUE-364: Cached SQL expressions to speed up looking for columns
selected by a given Criteria
-#foreach ($columnElement in $torqueGen.getChildren("column"))
- #set ( $peerColumnName = $columnElement.getAttribute("peerColumnName") )
- private static final String ${peerColumnName}_EXPRESSION =
${basePeerClassName}.${peerColumnName}.getSqlExpression();
-#end
-
- ## TORQUE-364: Removed strategy instance variable as this be cached per
RecordMapper (Thread safety/Multi query safety?)
-
- ## TORQUE-364: init a new Strategy implementation
- ## TORQUE-372: init is not Thread save cause Array
ConcurrentModificationException
- public MappingStrategy<${dbObjectClassName}> initStrategy()
- {
- #if("${useMappingStrategy}" == "true")
- return new MappingStrategy<${dbObjectClassName}>();
- #else
- // no MappingStrategy since useMappingStrategy not set
- return null;
- #end
- }
-#if("${simpleMapping}" == "true") #set( $useSimpleMapping=1 ) #end
-
- /**
- * Constructs the object from the current row in the resultSet.
- *
- * @param resultSet the resultSet to operate on, already pointing
- * to the correct row. Not null.
- * @param offset a possible offset in the columns to be considered
- * (if previous columns contain other objects),
- * or 0 for no offset.
- * @param criteria The criteria which created the result set.
- * If set, the attributes to set in the data object
- * are determined from the select columns in the criteria;
- * if no matching column can be found, null is returned.
- * If not set, all of the table's columns are read from the
- * result set in the order defined in the table definition.
- *
- * @return the mapped object, not null.
- *
- * @throws TorqueException when reading fields from the RecordSet fails
- * or if a Criteria is passed which contains select columns other
- * than the columns in the ${name} table.
- */
- public $dbObjectClassName processRow(
- ResultSet resultSet,
- int offset,
- Criteria criteria)
- throws TorqueException
- {
-#set ( $inheritanceBaseColumnElement =
$torqueGen.getChild("inheritance-column") )
-#if ($inheritanceBaseColumnElement)
-$torqueGen.mergepoint("createDbObjectInstanceFromInheritance")
-#else
-$torqueGen.mergepoint("createDbObjectInstance")
-#end
-#if ($torqueGen.booleanOption("torque.om.trackLoading"))
- try
- {
- ${field}.setLoading(true);
-#end
- ## TORQUE-364 - simple mapping if we got the exact column size we
assume the full table is used in criteria - skipping the mapping of every column
- if (criteria == null #if ($useSimpleMapping) ||
(criteria.getJoins().isEmpty() && criteria.getSelectColumns().size() - offset
== ${basePeerClassName}.numColumns) #end)
- {
-#set ( $n = 1 )
-#foreach ($columnElement in $torqueGen.getChildren("column"))
- #set ( $setter = $columnElement.getAttribute("setter") )
- #set ( $getter = $columnElement.getAttribute("getter") )
- ${field}.${setter}(
- ${getter}(resultSet, offset + $n));
- #set ( $n = $n + 1 )
-#end
- }
- else
- {
- ## TORQUE-372: thread save
- MappingStrategy<${dbObjectClassName}> strategyLoc=
initStrategy();
-
- // try to get columns to be mapped
- // from criteria's select columns
- int totalOffset = offset + 1;
- List<Column> selectColumns = criteria.getSelectColumns();
- List<Column> columnsWithoutOffset = selectColumns.subList(
- offset,
- selectColumns.size());
- Set<String> columnsMapped = new HashSet<String>();
- for (Column column : columnsWithoutOffset)
- {
- final int nextOffset = totalOffset; ## leaking assignment
-#set ( $else = "" )
-#foreach ($columnElement in $torqueGen.getChildren("column"))
- #set ( $setter = $columnElement.getAttribute("setter") )
- #set ( $getter = $columnElement.getAttribute("getter") )
- #set ( $peerColumnName = $columnElement.getAttribute("peerColumnName") )
- ${else}
- if (!columnsMapped.contains(${peerColumnName}_EXPRESSION )
&& ${peerColumnName}_EXPRESSION.equals(
- column.getSqlExpression()))
- {
- if (strategyLoc!=null)
- {
- strategyLoc.addColumn(nextOffset,
- (res, inst) -> inst.${setter}( ${getter}(res,
nextOffset)));
- } else
- {
- ${field}.${setter}( ${getter}(resultSet,
totalOffset));
- }
- columnsMapped.add( ${peerColumnName}_EXPRESSION );
- }
- #set ( $else = "else ")
-#end
- totalOffset++;
- }
- if (columnsMapped.isEmpty())
- {
- log.debug("no columns to map found in criteria, "
- + "returning null");
- return null;
- }
- if (strategyLoc!=null)
- {
- strategyLoc.finish($torqueGen.getChildren("column").size(),
#if("${mappingStrategySort}"=="true")true#{else}false#end);
- strategyLoc.execute(resultSet, $field);
- }
- }
- ${field}.setNew(false);
- ${field}.setModified(false);
-#if ($torqueGen.booleanOption("torque.om.trackLoading"))
- }
- finally
- {
- ${field}.setLoading(false);
- }
-#end
- return ${field};
- }
-
-$torqueGen.mergepoint("dbObjectFieldGetters")
-}
+#set ( $inheritanceBaseColumnElements =
$torqueGen.getChildren("inheritance-column"))
+## there should at most be one inheritance-column in each table
+#foreach ($inheritanceBaseColumnElement in $inheritanceBaseColumnElements)
+ #set ( $columnElement = $inheritanceBaseColumnElement.getChild("column") )
+ #set ( $inheritanceElements = $columnElement.getChildren("inheritance"))
+ #if ($inheritanceElements.size() > 0)
+ #if (${baseRecordMapperPackage} != $dbObjectPackage)
+ #foreach ($inheritanceElement in $inheritanceElements)
+ #set ( $inheritanceClassName =
$inheritanceElement.getAttribute("className") )
+ import ${dbObjectPackage}.${inheritanceClassName};
+ #end
+ #end
+ #end
+#end
+/**
+ * Maps ResultSet rows into ${dbObjectClassName} objects.
+ *
+ #if ($torqueGen.booleanOption("torque.om.addTimeStamp"))
+ * The skeleton for this class was autogenerated by Torque on:
+ *
+ * [${torqueGen.now()}]
+ *
+ #end
+ */
+@SuppressWarnings("unused")
+public class ${baseRecordMapperClassName} implements
RecordMapper<${dbObjectClassName}>
+{
+ /** Serial version */
+@Serial
+ #if ($torqueGen.booleanOption("torque.om.addTimeStamp"))
+ private static final long serialVersionUID = ${torqueGen.now().Time}L;
+
+ #else
+ private static final long serialVersionUID = 1L;
+
+ #end
+ /** The class log. */
+ private static final Log log
+ = LogFactory.getLog(${baseRecordMapperClassName}.class);
+
+ ## TORQUE-364: Cached SQL expressions to speed up looking for columns
selected by a given Criteria
+ #foreach ($columnElement in $torqueGen.getChildren("column"))
+ #set ( $peerColumnName = $columnElement.getAttribute("peerColumnName")
)
+ private static final String ${peerColumnName}_EXPRESSION =
${basePeerClassName}.${peerColumnName}.getSqlExpression();
+ #end
+
+ /**
+ * Constructs the object from the current row in the resultSet.
+ *
+ * @param resultSet the resultSet to operate on, already pointing
+ * to the correct row. Not null.
+ * @param offset a possible offset in the columns to be considered
+ * (if previous columns contain other objects),
+ * or 0 for no offset.
+ * @param criteria The criteria which created the result set.
+ * If set, the attributes to set in the data object
+ * are determined from the select columns in the criteria;
+ * if no matching column can be found, null is returned.
+ * If not set, all of the table's columns are read from the
+ * result set in the order defined in the table definition.
+ *
+ * @return the mapped object, not null.
+ *
+ * @throws TorqueException when reading fields from the RecordSet fails
+ * or if a Criteria is passed which contains select columns other
+ * than the columns in the ${name} table.
+ */
+ public $dbObjectClassName processRow(
+ ResultSet resultSet,
+ int offset,
+ Criteria criteria)
+ throws TorqueException
+ {
+ #set ( $inheritanceBaseColumnElement =
$torqueGen.getChild("inheritance-column") )
+ #if ($inheritanceBaseColumnElement)
+ $torqueGen.mergepoint("createDbObjectInstanceFromInheritance")
+ #else
+ $torqueGen.mergepoint("createDbObjectInstance")
+ #end
+ #if ($torqueGen.booleanOption("torque.om.trackLoading"))
+ try
+ {
+ ${field}.setLoading(true);
+ #end
+ if (criteria == null)
+ {
+ #set ( $n = 1 )
+ #foreach ($columnElement in $torqueGen.getChildren("column"))
+ #set ( $setter = $columnElement.getAttribute("setter") )
+ #set ( $getter = $columnElement.getAttribute("getter") )
+ ${field}.${setter}(
+ ${getter}(resultSet, offset + $n));
+ #set ( $n = $n + 1 )
+ #end
+ }
+ else
+ {
+ ## This is the slow path, but we can reuse the strategy generation
logic
+ ## to avoid duplicating the mapping code.
+ MappingStrategy<${dbObjectClassName}> strategy =
generateStrategy(offset, criteria);
+ if (strategy == null)
+ {
+ log.debug("Could not generate a mapping strategy for the given
criteria, "
+ + "returning null");
+ return null;
+ }
+ strategy.execute(resultSet, ${field});
+ }
+ ${field}.setNew(false);
+ ${field}.setModified(false);
+ #if ($torqueGen.booleanOption("torque.om.trackLoading"))
+ }
+ finally
+ {
+ ${field}.setLoading(false);
+ }
+ #end
+ return ${field};
+ }
+
+ $torqueGen.mergepoint("mappingStrategyPath")
+ $torqueGen.mergepoint("dbObjectFieldGetters")
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]