1 3 package jodd.db.orm.mapper; 4 5 import jodd.bean.BeanUtil; 6 import jodd.typeconverter.TypeConverterManager; 7 import jodd.db.orm.DbOrm; 8 import jodd.db.orm.DbOrmException; 9 import jodd.db.orm.DbEntityDescriptor; 10 import jodd.util.collection.HashBag; 11 import jodd.util.collection.Bag; 12 13 import java.sql.ResultSet ; 14 import java.sql.ResultSetMetaData ; 15 import java.sql.SQLException ; 16 import java.util.LinkedHashMap ; 17 import java.util.Map ; 18 19 61 public class DefaultResultSetMapper implements ResultSetMapper { 62 63 protected DbOrm dbOrm; 64 protected ResultSet rs; 65 66 protected int totalColumns; protected String [] columnNames; protected String [] tableNames; 70 private Bag resultColums; 72 74 public DefaultResultSetMapper(ResultSet rs) { 75 this(rs, null, DbOrm.getInstance()); 76 } 77 78 public DefaultResultSetMapper(ResultSet rs, DbOrm orm) { 79 this(rs, null, orm); 80 } 81 82 public DefaultResultSetMapper(ResultSet rs, Map <String , String []> columnAliases) { 83 this(rs, columnAliases, DbOrm.getInstance()); 84 } 85 86 89 public DefaultResultSetMapper(ResultSet rs, Map <String , String []> columnAliases, DbOrm orm) { 90 this.dbOrm = orm; 91 this.rs = rs; 92 this.resultColums = new HashBag(); 93 try { 94 ResultSetMetaData rsMetaData = rs.getMetaData(); 95 if (rsMetaData == null) { 96 throw new DbOrmException("JDBC driver doesn't provide meta-data."); 97 } 98 totalColumns = rsMetaData.getColumnCount(); 99 columnNames = new String [totalColumns]; 100 tableNames = new String [totalColumns]; 101 102 for (int i = 0; i < totalColumns; i++) { 103 String columnName = rsMetaData.getColumnName(i + 1); 104 String tableName = null; 105 106 int sepNdx = columnName.indexOf(dbOrm.getColumnAliasSeparator()); 108 if (sepNdx != -1) { 109 tableName = columnName.substring(0, sepNdx); 111 if (columnAliases != null) { 112 String [] tableData = columnAliases.get(tableName); 113 if (tableData != null) { 114 tableName = tableData[0]; 115 } 116 } 117 columnName = columnName.substring(sepNdx + 1); 118 } else { 119 if (columnAliases != null) { 121 String [] columnData = columnAliases.get(columnName.toLowerCase()); 122 if (columnData != null) { 123 tableName = columnData[0]; 124 columnName = columnData[1]; 125 } 126 } 127 if (tableName == null) { 128 try { 129 tableName = rsMetaData.getTableName(i + 1); 130 } catch (SQLException sex) { 131 } 133 if ((tableName != null) && (tableName.length() == 0)) { 134 tableName = null; 135 } 136 } 137 } 138 139 columnName = columnName.trim(); 140 if (columnName.length() == 0) { 141 columnName = null; 142 } 143 columnNames[i] = columnName; 144 if (tableName != null) { 145 tableName = tableName.trim(); 146 } 147 tableNames[i] = tableName; 148 } 149 } catch (SQLException sex) { 150 throw new DbOrmException("Unable to read ResultSet meta-data.", sex); 151 } 152 } 153 154 156 159 public boolean next() { 160 try { 161 return rs.next(); 162 } catch (SQLException sex) { 163 throw new DbOrmException("Unable to move ResultSet cursor to next position.", sex); 164 } 165 } 166 167 171 public void close() { 172 try { 173 rs.close(); 174 } catch (SQLException sex) { 175 } 177 } 178 179 182 public ResultSet getResultSet() { 183 return rs; 184 } 185 186 187 189 192 protected Object newInstance(Class types) { 193 try { 194 return types.newInstance(); 195 } catch (Exception ex) { 196 throw new DbOrmException("Unable to create new entity instance for type '" + types + "'.", ex); 197 } 198 } 199 200 201 protected Class [] cachedUsedTypes; 202 protected String [] cachedTypesTableNames; 203 204 210 protected String [] createTypesTableNames(Class [] types) { 211 if (types != cachedUsedTypes) { 212 cachedTypesTableNames = new String [types.length]; 213 for (int i = 0; i < types.length; i++) { 214 if (types[i] == null) { 215 cachedTypesTableNames[i] = null; 216 continue; 217 } 218 DbEntityDescriptor ded = dbOrm.lookup(types[i]); 219 if (ded != null) { 220 cachedTypesTableNames[i] = ded.getTableName(); 221 } 222 } 223 cachedUsedTypes = types; 224 } 225 return cachedTypesTableNames; 226 } 227 228 229 protected int cachedColumnNdx; 230 protected Object cachedColumnValue; 231 232 236 protected Object readColumnValue(int colNdx) { 237 if (colNdx != cachedColumnNdx) { 238 try { 239 cachedColumnValue = rs.getObject(colNdx + 1); 240 } catch (SQLException sex) { 241 throw new DbOrmException("Unable to read value for column #" + (colNdx + 1) + '.'); 242 } 243 cachedColumnNdx = colNdx; 244 } 245 return cachedColumnValue; 246 } 247 248 249 public Object [] parseObjects(Class ... types) { 250 int totalTypes = types.length; 251 Object [] result = new Object [totalTypes]; 252 boolean[] resultUsage = new boolean[totalTypes]; 253 String [] typesTableNames = createTypesTableNames(types); 254 255 int currentResult = 0; 256 cachedColumnNdx = -1; 257 int colNdx = 0; 258 while (colNdx < totalColumns) { 259 260 if (currentResult >= totalTypes) { 262 break; 263 } 264 265 Class currentType = types[currentResult]; 267 if (currentType == null) { 268 colNdx++; 269 currentResult++; resultColums.clear(); 270 continue; 271 } 272 273 Object value = readColumnValue(colNdx); 274 String columnName = columnNames[colNdx]; 275 String tableName = tableNames[colNdx]; 276 String resultTableName = typesTableNames[currentResult]; 277 278 if (resultTableName == null) { 279 result[currentResult] = TypeConverterManager.convert(value, currentType); 281 resultUsage[currentResult] = true; 282 colNdx++; 283 currentResult++; resultColums.clear(); 284 continue; 285 } 286 if ((tableName == null) || (resultTableName.equals(tableName) == true)) { 287 if (resultColums.contains(columnName) == false) { 288 String propertyName = dbOrm.lookup(currentType).getPropertyName(columnName); 289 if (propertyName != null) { 290 if (result[currentResult] == null) { 291 result[currentResult] = newInstance(currentType); 292 } 293 300 if (BeanUtil.hasDeclaredProperty(result[currentResult], propertyName) == true) { 301 if (value != null) { 303 BeanUtil.setDeclaredProperty(result[currentResult], propertyName, value); 304 resultUsage[currentResult] = true; 305 } 306 colNdx++; 307 resultColums.add(columnName); 308 continue; 309 } 310 } 311 } 312 } 313 currentResult++; resultColums.clear(); 315 } 316 317 resultColums.clear(); 318 for (int i = 0; i < resultUsage.length; i++) { 319 if (resultUsage[i] == false) { 320 result[i] = null; 321 } 322 } 323 return result; 324 } 325 326 public Object parseOneObject(Class ... types) { 327 return parseObjects(types)[0]; 328 } 329 330 332 public Object [] parseObjects() { 333 Map <String , Class > classesMap = new LinkedHashMap <String , Class >(); 334 for (String tableName : tableNames) { 335 if (tableName == null) { 336 throw new DbOrmException("Table name for one or more columns is not availiable. " + 337 "It may be due JDBC driver that doesn't provide table names in ResultSet meta-data."); 338 } 339 if (classesMap.get(tableName) == null) { 340 Class type = dbOrm.getMappedEntityType(tableName); 341 if (type == null) { 342 throw new DbOrmException("Unable to find entity type for table '" + tableName + "'."); 343 } 344 classesMap.put(tableName, type); 345 } 346 } 347 348 Class [] results = classesMap.values().toArray(new Class [classesMap.size()]); 349 return parseObjects(results); 350 } 351 352 353 public Object parseOneObject() { 354 return parseObjects()[0]; 355 } 356 357 } 358 | Popular Tags |