用Java 8 lambda优化JDBC

本教程源码下载
https://github.com/jexenberger/lambda-tuples

首先创建一个函数接口ResultSetProcessor :

@FunctionalInterface
public interface ResultSetProcessor {

public void process(ResultSet resultSet,
                    long currentRow) 
                    throws SQLException;

}

下面做个简单查询案例,使用这个接口遍历

public static void select(Connection connection,
String sql,
ResultSetProcessor processor,
Object… params) {
try (PreparedStatement ps = connection.prepareStatement(sql)) {
int cnt = 0;
for (Object param : params) {
ps.setObject(++cnt, param));
}
try (ResultSet rs = ps.executeQuery()) {
long rowCnt = 0;
while (rs.next()) {
processor.process(rs, rowCnt++);
}
} catch (SQLException e) {
throw new DataAccessException(e);
}
} catch (SQLException e) {
throw new DataAccessException(e);
}
}

调用这个select语句如下:

select(connection, “select * from MY_TABLE”,(rs, cnt)-> {
System.out.println(rs.getInt(1)+” “+cnt)
});

select的第三个参数ResultSetProcessor这是个函数,所以我们传入的是一个匿名函数。

Streams API

   java 8提供了更强大的 Streams API,我们可以对ResultSet处理更加强大。创建一个自己的Tuple 类型,代表ResultSet中一行记录。

   下面我们将一个查询和ResultSet包装在一个Iterator中:

public class ResultSetIterator implements Iterator {

private ResultSet rs;
private PreparedStatement ps;
private Connection connection;
private String sql;

public ResultSetIterator(Connection connection, String sql) {
    assert connection != null;
    assert sql != null;
    this.connection = connection;
    this.sql = sql;
}

public void init() {
    try {
        ps = connection.prepareStatement(sql);
        rs = ps.executeQuery();

    } catch (SQLException e) {
        close();
        throw new DataAccessException(e);
    }
}

@Override
public boolean hasNext() {
    if (ps == null) {
        init();
    }
    try {
        boolean hasMore = rs.next();
        if (!hasMore) {
            close();
        }
        return hasMore;
    } catch (SQLException e) {
        close();
        throw new DataAccessException(e);
    }

}

private void close() {
    try {
        rs.close();
        try {
            ps.close();
        } catch (SQLException e) {
            //nothing we can do here
        }
    } catch (SQLException e) {
        //nothing we can do here
    }
}

@Override
public Tuple next() {
    try {
        return SQL.rowAsTuple(sql, rs);
    } catch (DataAccessException e) {
        close();
        throw e;
    }
}

}

这是一个遍历器,每次返回ResultSet的一行记录,返回类型是我们定义Tuple.

关于tuple定义可见源码。

我们和Stream绑定在一起如下:

public static Stream stream(final Connection connection,
final String sql,
final Object… parms) {
return StreamSupport
.stream(Spliterators.spliteratorUnknownSize(
new ResultSetIterator(connection, sql), 0), false);
}

Java 8 提供StreamSupport静态方法.stream来创建 java.util.stream.Stream实例,同时还需要java.util.stream.Spliterator,这是一个用来遍历和分区一个序列元素(集合)的特殊类型,有了它才能并行处理我们饿操作,而Spliterators 这是能够对已经存在的集合如java.util.Iterator.提供并行操作。

我们调用上面stream如下:

long result = stream(connection, “select TEST_ID from TEST_TABLE”)
.filter((t) -> t.asInt(“TEST_ID”) % 2 == 0)
.limit(100)
.count();

这是查询所有的TEST_ID,然后过滤掉所有非偶数,最后再运行一个计数。非常简单明了。如果你使用ORM/JPA等框架,可能无法让自己的SQL代码如此优雅直接了,它类似Hibernate的 criteria。

你可能感兴趣的:(用Java 8 lambda优化JDBC)