org.simpleflatmapper.jooq.SelectQueryMapper Maven / Gradle / Ivy
package org.simpleflatmapper.jooq;
import org.jooq.*;
import org.jooq.exception.DataAccessException;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingException;
import org.simpleflatmapper.map.SetRowMapper;
import org.simpleflatmapper.map.mapper.MapperCache;
import org.simpleflatmapper.map.mapper.MapperKey;
import org.simpleflatmapper.map.mapper.MapperKeyComparator;
import org.simpleflatmapper.map.property.KeyProperty;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.util.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//IFJAVA8_START
import java.util.stream.Stream;
//IFJAVA8_END
public final class SelectQueryMapper {
private final MapperCache> mapperCache = new MapperCache>(JdbcColumnKeyMapperKeyComparator.INSTANCE);
private final ClassMeta classMeta;
private final MapperConfig mapperConfig;
protected SelectQueryMapper(ClassMeta classMeta, MapperConfig mapperConfig) {
this.classMeta = classMeta;
this.mapperConfig = mapperConfig;
}
public List asList(final SET source)
throws MappingException {
SetRowMapper mapper = getMapper(source);
try {
final ArrayList list = new ArrayList();
ResultSet rs = source.fetchResultSet();
try {
mapper.forEach(rs, new Consumer() {
@Override
public void accept(T t) {
list.add(t);
}
});
} finally {
rs.close();
}
return list;
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
/**
* Loop over the resultSet, map each row to a new newInstance of T and call back the handler
*
* The method will return the handler passed as an argument so you can easily chain the calls like
*
* List<T> list = jdbcMapper.forEach(rs, new ListHandler<T>()).getList();
*
*
*
* @param source the source
* @param handler the handler that will get the callback
* @param the row handler type
* @return the handler passed in
* @throws MappingException if an error occurs during the mapping
*
*/
public > H forEach(final SET source, final H handler)
throws MappingException {
SetRowMapper mapper = getMapper(source);
try {
ResultSet rs = source.fetchResultSet();
try {
mapper.forEach(rs, handler);
} finally {
rs.close();
}
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
return handler;
}
/**
*
* @param source the source
* @return an iterator that will return a map object for each row of the result set.
* @throws MappingException if an error occurs during the mapping
*/
public AutoCloseableIterator iterator(SET source)
throws MappingException {
SetRowMapper mapper = getMapper(source);
try {
final ResultSet rs = source.fetchResultSet();
final Iterator iterator = mapper.iterator(rs);
return new AutoCloseableIterator(iterator, closer(rs));
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
/**
*
* @param source the source
* @return a stream that will contain a map object for each row of the result set.
* @throws MappingException if an error occurs during the mapping
*/
//IFJAVA8_START
public Stream stream(SET source) throws MappingException {
SetRowMapper mapper = getMapper(source);
try {
final ResultSet rs = source.fetchResultSet();
final Stream enumerable = mapper.stream(rs);
return enumerable.onClose(new Runnable() {
@Override
public void run() {
try {
rs.close();
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
});
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
//IFJAVA8_END
public AutoCloseableEnumerable enumerate(SET source)
throws MappingException {
SetRowMapper mapper = getMapper(source);
try {
final ResultSet rs = source.fetchResultSet();
final Enumerable enumerable = mapper.enumerate(rs);
return new AutoCloseableEnumerable(enumerable, closer(rs));
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
private SetRowMapper getMapper(SET source) {
Field[] fields = getFields(source);
JooqFieldKey[] keys = new JooqFieldKey[fields.length];
for(int i = 0; i < fields.length; i ++) {
keys[i] = new JooqFieldKey(fields[i], i);
}
MapperKey mapperKey = new MapperKey(keys);
SetRowMapper mapper = mapperCache.get(mapperKey);
if (mapper == null) {
mapper = buildMapper(fields);
mapperCache.add(mapperKey, mapper);
}
return mapper;
}
private Field[] getFields(SET source) {
if (source instanceof Select) {
List> select = ((Select>) source).getSelect();
return select.toArray(new Field[0]);
}
return source.fields();
}
private SetRowMapper buildMapper(Field[] fields) {
JooqJdbcMapperBuilder mapperBuilder = new JooqJdbcMapperBuilder(classMeta, mapperConfig);
for(int i = 0; i < fields.length; i ++) {
Field field = fields[i];
Object[] properties = isKey(field) ? new Object[]{KeyProperty.DEFAULT} : new Object[0];
JooqFieldKey key = new JooqFieldKey(field, i + 1);
mapperBuilder.addMapping(key, properties);
}
return mapperBuilder.mapper();
}
private boolean isKey(Field> field) {
if (field instanceof TableField) {
TableField, ?> tf = (TableField, ?>) field;
List extends UniqueKey>> keys = tf.getTable().getKeys();
if (keys != null) {
for (UniqueKey key : keys) {
if (key.getFields().contains(field)) return true;
}
}
}
return false;
}
private Closer closer(final ResultSet rs) {
return new Closer() {
@Override
public void close() {
try {
rs.close();
} catch (SQLException e) {
throw new DataAccessException(e.getMessage(), e);
}
}
};
}
private static final class JdbcColumnKeyMapperKeyComparator extends MapperKeyComparator {
public final static JdbcColumnKeyMapperKeyComparator INSTANCE = new JdbcColumnKeyMapperKeyComparator();
private JdbcColumnKeyMapperKeyComparator() {
}
@Override
public int compare(MapperKey m1, MapperKey m2) {
JooqFieldKey[] keys1 = m1.getColumns();
JooqFieldKey[] keys2 = m2.getColumns();
int d = keys1.length - keys2.length;
if (d != 0) {
return d;
}
return compareKeys(keys1, keys2);
}
private int compareKeys(JooqFieldKey[] keys1, JooqFieldKey[] keys2) {
for (int i = 0; i < keys1.length; i++) {
int d = compare(keys1[i], keys2[i]);
if (d != 0) {
return d;
}
}
return 0;
}
protected int compare(JooqFieldKey k1, JooqFieldKey k2) {
int d = k1.getIndex() - k2.getIndex();
if (d != 0) return d;
d = k1.getField().getName().compareTo(k2.getField().getName());
return d;
}
}
}