org.sfm.jdbc.DynamicJdbcMapper Maven / Gradle / Ivy
package org.sfm.jdbc;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.sfm.map.FieldMapperErrorHandler;
import org.sfm.map.MapperBuilderErrorHandler;
import org.sfm.reflect.Setter;
import org.sfm.reflect.SetterFactory;
import org.sfm.utils.Handler;
public final class DynamicJdbcMapper implements JdbcMapper {
private final Map> setters;
private final SetterFactory setterFactory;
private final Class target;
@SuppressWarnings("unchecked")
private final AtomicReference[]> mapperCache = new AtomicReference[]>(new CacheEntry[0]);
private FieldMapperErrorHandler fieldMapperErrorHandler;
private MapperBuilderErrorHandler mapperBuilderErrorHandler;
public DynamicJdbcMapper(final Class target, final SetterFactory setterFactory,
final FieldMapperErrorHandler fieldMapperErrorHandler,
final MapperBuilderErrorHandler mapperBuilderErrorHandler) {
this.setterFactory = setterFactory;
this.setters = setterFactory.getAllSetters(target);
this.target = target;
this.fieldMapperErrorHandler = fieldMapperErrorHandler;
this.mapperBuilderErrorHandler = mapperBuilderErrorHandler;
}
private static final class CacheEntry {
final MapperKey key;
final JdbcMapper mapper;
public CacheEntry(final MapperKey key, final JdbcMapper mapper) {
this.key = key;
this.mapper = mapper;
}
}
@Override
public final T map(final ResultSet source) throws Exception {
final JdbcMapper mapper = buildMapper(source.getMetaData());
return mapper.map(source);
}
@Override
public final > H forEach(final ResultSet rs, final H handle)
throws Exception {
final JdbcMappermapper = buildMapper(rs.getMetaData());
return mapper.forEach(rs, handle);
}
private JdbcMapper buildMapper(final ResultSetMetaData metaData) throws SQLException, NoSuchMethodException, SecurityException, IOException {
final MapperKey key = MapperKey.valueOf(metaData);
JdbcMapper mapper = getMapper(key);
if (mapper == null) {
final CachedResultSetMapperBuilder builder = new CachedResultSetMapperBuilder(target, setters, setterFactory);
builder.fieldMapperErrorHandler(fieldMapperErrorHandler);
builder.mapperBuilderErrorHandler(mapperBuilderErrorHandler);
builder.addMapping(metaData);
mapper = builder.mapper();
addToMapperCache(new CacheEntry<>(key, mapper));
}
return mapper;
}
@SuppressWarnings("unchecked")
private void addToMapperCache(final CacheEntry cacheEntry) {
CacheEntry[] entries;
CacheEntry[] newEntries;
do {
entries = mapperCache.get();
for(int i = 0; i < entries.length; i++) {
if (entries[0].key.equals(cacheEntry.key)) {
// already added
return;
}
}
newEntries = new CacheEntry[entries.length + 1];
System.arraycopy(entries, 0, newEntries, 0, entries.length);
newEntries[entries.length] = cacheEntry;
} while(!mapperCache.compareAndSet(entries, newEntries));
}
protected JdbcMapper getMapper(MapperKey key) {
final CacheEntry[] entries = mapperCache.get();
for(int i = 0; i < entries.length; i++) {
final CacheEntry entry = entries[i];
if (entry.key.equals(key)) {
return entry.mapper;
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy