All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dbflute.s2dao.rowcreator.TnRelationRowCache Maven / Gradle / Ivy

There is a newer version: 1.2.8
Show newest version
/*
 * Copyright 2014-2019 the original author or authors.
 *
 * Licensed 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.
 */
package org.dbflute.s2dao.rowcreator;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dbflute.bhv.core.context.ResourceContext;
import org.dbflute.jdbc.ValueType;
import org.dbflute.s2dao.metadata.TnPropertyType;
import org.dbflute.s2dao.metadata.TnRelationPropertyType;
import org.dbflute.s2dao.rowcreator.impl.TnRelationKeyCompound;
import org.dbflute.s2dao.rowcreator.impl.TnRelationKeyEmpty;
import org.dbflute.s2dao.rowcreator.impl.TnRelationKeySimple;

/**
 * The cache of relation row. 
* This is not thread safe so you should create per one select. * @author modified by jflute (originated in S2Dao) */ public class TnRelationRowCache { // =================================================================================== // Definition // ========== private static final TnRelationKey EMPTY_KEY = new TnRelationKeyEmpty(); // =================================================================================== // Attribute // ========= /** The list of row map. map:{relationPath = map:{relationKey = row}} (NotNull: if canCache is true) */ protected final Map> _rowMap; /** Can the relation row cache? */ protected final boolean _canCache; // =================================================================================== // Constructor // =========== /** * @param relSize The size of relation. * @param canCache Can the relation row cache? */ public TnRelationRowCache(int relSize, boolean canCache) { _rowMap = canCache ? new HashMap>(relSize) : null; _canCache = canCache; } // =================================================================================== // Cache Handling // ============== /** * Get relation row from cache by relation key. * @param relationNoSuffix The relation No suffix that indicates the location of the relation. * @param relKey The key of relation. (NotNull) * @return The relation row. (NullAllowed) */ public Object getRelationRow(String relationNoSuffix, TnRelationKey relKey) { if (!_canCache) { return null; } final Map elementMap = _rowMap.get(relationNoSuffix); if (elementMap == null) { return null; } return elementMap.get(relKey); } /** * Add relation row to cache. * @param relationNoSuffix The relation No suffix that indicates the location of the relation. * @param relKey The key of relation. (NotNull) * @param relationRow The relation row. (NullAllowed) */ public void addRelationRow(String relationNoSuffix, TnRelationKey relKey, Object relationRow) { if (!_canCache) { return; } Map elementMap = _rowMap.get(relationNoSuffix); if (elementMap == null) { elementMap = new HashMap(); _rowMap.put(relationNoSuffix, elementMap); } elementMap.put(relKey, relationRow); } // =================================================================================== // Key Creation // ============ /** * Create the key of relation. * @param rs The result set. (NotNull) * @param rpt The property type of relation. (NotNull) * @param selectColumnMap The name map of select column. {flexible-name = column-DB-name} (NotNull) * @param selectIndexMap The map of select index. map:{entityNo(e.g. loc00 or _0_3) = map:{selectColumnKeyName = selectIndex}} (NullAllowed: If it's null, it doesn't use select index.) * @param relationNoSuffix The suffix of relation No. (NotNull) * @return The key of relation. (NullAllowed: null means no data of the relation) * @throws SQLException When it fails to handle the SQL. */ public TnRelationKey createRelationKey(ResultSet rs, TnRelationPropertyType rpt // basic resource , Map selectColumnMap, Map> selectIndexMap // select resource , String relationNoSuffix) throws SQLException { // relation resource if (!_canCache) { return EMPTY_KEY; } final TnRelationKey relKey; if (rpt.hasSimpleUniqueKey()) { relKey = doCreateRelationKeySimple(rs, rpt, selectColumnMap, selectIndexMap, relationNoSuffix); } else if (rpt.hasCompoundUniqueKey()) { relKey = doCreateRelationKeyCompound(rs, rpt, selectColumnMap, selectIndexMap, relationNoSuffix); } else { // empty relKey = null; // treated as no data of the relation } return relKey; } protected TnRelationKey doCreateRelationKeySimple(ResultSet rs, TnRelationPropertyType rpt, Map selectColumnMap, Map> selectIndexMap, String relationNoSuffix) throws SQLException { final TnPropertyType pt = rpt.getSimpleUniquePropertyType(); final String columnKeyName = buildColumnKeyName(pt, relationNoSuffix); final Object keyValue = setupKeyElement(rs, rpt, selectColumnMap, selectIndexMap, columnKeyName, pt, relationNoSuffix); return keyValue != null ? new TnRelationKeySimple(columnKeyName, keyValue) : null; } protected TnRelationKey doCreateRelationKeyCompound(ResultSet rs, TnRelationPropertyType rpt, Map selectColumnMap, Map> selectIndexMap, String relationNoSuffix) throws SQLException { final List uniquePropertyTypeList = rpt.getUniquePropertyTypeList(); Map relKeyValues = null; for (TnPropertyType pt : uniquePropertyTypeList) { final String columnKeyName = buildColumnKeyName(pt, relationNoSuffix); final Object keyValue = setupKeyElement(rs, rpt, selectColumnMap, selectIndexMap, columnKeyName, pt, relationNoSuffix); if (keyValue == null) { if (relKeyValues != null) { relKeyValues.clear(); } break; // if either one is null, treated as no data } if (relKeyValues == null) { // lazy-load for performance relKeyValues = new HashMap(uniquePropertyTypeList.size()); } relKeyValues.put(columnKeyName, keyValue); } return (relKeyValues != null && !relKeyValues.isEmpty()) ? new TnRelationKeyCompound(relKeyValues) : null; } protected String buildColumnKeyName(TnPropertyType pt, String relationNoSuffix) { return pt.getColumnDbName() + relationNoSuffix; } protected Object setupKeyElement(ResultSet rs, TnRelationPropertyType rpt, Map selectColumnMap, Map> selectIndexMap, String columnKeyName, TnPropertyType pt, String relationNoSuffix) throws SQLException { if (isOutOfRelationSelectIndex(relationNoSuffix, columnKeyName, selectIndexMap)) { // basically unreachable, same reason with next if statement, check just in case return null; } if (!selectColumnMap.containsKey(columnKeyName)) { // basically unreachable // because the referred column (basically PK or FK) must exist // if the relation's select clause is specified return null; } final ValueType valueType = pt.getValueType(); final Object value; if (selectIndexMap != null) { value = ResourceContext.getRelationValue(rs, relationNoSuffix, columnKeyName, valueType, selectIndexMap); } else { value = valueType.getValue(rs, columnKeyName); } // null-able when the referred column data is null // (treated as no relation data) return value; } protected boolean isOutOfRelationSelectIndex(String relationNoSuffix, String columnDbName, Map> selectIndexMap) throws SQLException { return ResourceContext.isOutOfRelationSelectIndex(relationNoSuffix, columnDbName, selectIndexMap); } // =================================================================================== // Accessor // ======== public Map> getRowMap() { return _rowMap; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy