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

org.fluentjdbc.DatabaseResult Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
package org.fluentjdbc;

import org.fluentjdbc.DatabaseTable.RowMapper;
import org.fluentjdbc.util.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

@ParametersAreNonnullByDefault
public class DatabaseResult implements AutoCloseable {

    private final static Logger logger = LoggerFactory.getLogger(DatabaseResult.class);

    public interface DatabaseResultMapper {

        T apply(DatabaseResult result) throws SQLException;
    }

    private final PreparedStatement statement;
    protected ResultSet resultSet;
    protected final Map columnIndexes;
    protected final Map> tableColumnIndexes;

    public DatabaseResult(PreparedStatement statement, ResultSet resultSet, Map columnIndexes, Map> aliasColumnIndexes) {
        this.statement = statement;
        this.resultSet = resultSet;
        this.columnIndexes = columnIndexes;
        this.tableColumnIndexes = aliasColumnIndexes;
    }

    public DatabaseResult(PreparedStatement statement, ResultSet resultSet) throws SQLException {
        this(statement, resultSet, new HashMap<>(), new HashMap<>());
        ResultSetMetaData metaData = resultSet.getMetaData();
        for (int i = 1; i <= metaData.getColumnCount(); i++) {
            String columnName = metaData.getColumnName(i).toUpperCase();
            String tableName = metaData.getTableName(i).toUpperCase();
            if (!tableName.equals("")) {
                tableColumnIndexes.computeIfAbsent(tableName, name -> new HashMap<>()).put(columnName, i);
            }

            if (!columnIndexes.containsKey(columnName)) {
                columnIndexes.put(columnName, i);
            } else {
                logger.warn("Duplicate column " + columnName + " in query result");
            }
        }
    }

    @Override
    public void close() throws SQLException {
        resultSet.close();
    }

    public boolean next() throws SQLException {
        return resultSet.next();
    }

    public  List list(RowMapper mapper) throws SQLException {
        List result = new ArrayList<>();
        while (next()) {
            result.add(mapper.mapRow(row()));
        }
        return result;
    }

    public void forEach(DatabaseTable.RowConsumer consumer) throws SQLException {
        while (next()) {
            consumer.apply(row());
        }
    }

    @Nonnull
    public  Optional single(RowMapper mapper) throws SQLException {
        if (!next()) {
            return Optional.empty();
        }
        T result = mapper.mapRow(row());
        if (next()) {
            throw new IllegalStateException("More than one row returned");
        }
        return Optional.of(result);
    }

    public DatabaseRow row() {
        return new DatabaseRow(this.resultSet, this.columnIndexes, this.tableColumnIndexes);
    }

    public  Stream stream(RowMapper mapper, String query) throws SQLException {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator(mapper, query), 0), false);
    }

    public  Iterator iterator(RowMapper mapper, String query) throws SQLException {
        return new Iterator<>(mapper, query);
    }

    class Iterator implements java.util.Iterator {
        private final RowMapper mapper;
        private final long startTime;
        private final String query;
        private boolean hasNext;

        public Iterator(RowMapper mapper, String query) throws SQLException {
            this.mapper = mapper;
            this.startTime = System.currentTimeMillis();
            this.query = query;
            hasNext = resultSet.next();
        }

        @Override
        public boolean hasNext() {
            return hasNext;
        }

        @Override
        public T next() {
            try {
                T o = mapper.mapRow(row());
                hasNext = resultSet.next();
                if (!hasNext) {
                    logger.debug("time={}s query=\"{}\"", (System.currentTimeMillis()- startTime)/1000.0, query);
                    close();
                }
                return o;
            } catch (SQLException e) {
                throw ExceptionUtil.softenCheckedException(e);
            }
        }

        protected void close() throws SQLException {
            resultSet.close();
            statement.close();
        }

        @SuppressWarnings("deprecation")
        @Override
        protected void finalize() throws Throwable {
            close();
        }
    }}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy