com.j256.ormlite.stmt.mapped.BaseMappedQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ormlite-core Show documentation
Show all versions of ormlite-core Show documentation
Lightweight Object Relational Model (ORM) for persisting objects to SQL databases.
package com.j256.ormlite.stmt.mapped;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import com.j256.ormlite.dao.BaseForeignCollection;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.ObjectCache;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.stmt.GenericRowMapper;
import com.j256.ormlite.support.DatabaseResults;
import com.j256.ormlite.table.TableInfo;
/**
* Abstract mapped statement for queries which handle the creating of a new object and the row mapping functionality.
*
* @author graywatson
*/
public abstract class BaseMappedQuery extends BaseMappedStatement implements GenericRowMapper {
protected final FieldType[] resultsFieldTypes;
// cache of column names to results position
private Map columnPositions = null;
private Object parent = null;
private Object parentId = null;
protected BaseMappedQuery(Dao dao, TableInfo tableInfo, String statement, FieldType[] argFieldTypes,
FieldType[] resultsFieldTypes) {
super(dao, tableInfo, statement, argFieldTypes);
this.resultsFieldTypes = resultsFieldTypes;
}
@Override
public T mapRow(DatabaseResults results) throws SQLException {
Map colPosMap;
if (columnPositions == null) {
colPosMap = new HashMap();
} else {
colPosMap = columnPositions;
}
ObjectCache objectCache = results.getObjectCacheForRetrieve();
if (objectCache != null) {
Object id = idField.resultToJava(results, colPosMap);
T cachedInstance = objectCache.get(clazz, id);
if (cachedInstance != null) {
// if we have a cached instance for this id then return it
return cachedInstance;
}
}
// create our instance
T instance = dao.createObjectInstance();
// populate its fields
Object id = null;
boolean foreignCollections = false;
for (FieldType fieldType : resultsFieldTypes) {
if (fieldType.isForeignCollection()) {
foreignCollections = true;
} else {
Object val = fieldType.resultToJava(results, colPosMap);
/*
* This is pretty subtle. We introduced multiple foreign fields to the same type which use the {@link
* ForeignCollectionField} foreignColumnName field. The bug that was created was that all the fields
* were then set with the parent class. Only the fields that have a matching id value should be set to
* the parent. We had to add the val.equals logic.
*/
if (val != null && parent != null && fieldType.getField().getType() == parent.getClass()
&& val.equals(parentId)) {
fieldType.assignField(connectionSource, instance, parent, true, objectCache);
} else {
fieldType.assignField(connectionSource, instance, val, false, objectCache);
}
if (fieldType.isId()) {
id = val;
}
}
}
if (foreignCollections) {
// go back and initialize any foreign collections
for (FieldType fieldType : resultsFieldTypes) {
if (fieldType.isForeignCollection()) {
BaseForeignCollection collection = fieldType.buildForeignCollection(instance, id);
if (collection != null) {
fieldType.assignField(connectionSource, instance, collection, false, objectCache);
}
}
}
}
// if we have a cache and we have an id then add it to the cache
objectCache = results.getObjectCacheForStore();
if (objectCache != null && id != null) {
objectCache.put(clazz, id, instance);
}
if (columnPositions == null) {
columnPositions = colPosMap;
}
return instance;
}
/**
* If we have a foreign collection object then this sets the value on the foreign object in the class.
*/
public void setParentInformation(Object parent, Object parentId) {
this.parent = parent;
this.parentId = parentId;
}
}