Java8的Lambda表达式确实是一个很好的特性。可是在哪些场合下使用。事实上还是须要细致考虑的。我们当然不能为了使用而使用,而是须要找到切实实用的场合。在JDBC编程中,比如查询语句,首先须要进行查询參数绑定,其次是处理返回的结果集,这两步操作是每一个查询都不同的,而获取JDBC连接,准备PreparedStatement,以及释放资源则都是全然同样的,这就是一个Lambda表达式应用的绝佳场景。

在讨论详细的实现细节之前,想先讨论一下JDBC的问题。

眼下相信90%以上的Java程序猿都不会再用JDBC了,基本都採用某种OR映射机制。如Hibernate、Persistent API等,採用所谓OO的方式来操作数据库。

可是实际上这样的方式在理论上非常好,在实际应用中是有非常大问题的,尤其在眼下大数据的情况下。将数据和程序绑在一起是非常不可取的,同一时候採用OR映射之后,抽象出的数据操作在功能和性能方面,都全然不能与SQL相比,因此直接使用JDBC还是值得考虑的。如今的语言之争,基本是该语言下最流行的框架之争,Java语言下基本就是SSH和JBOSS,因为这两个异常流行和笨重的框架。使Java基本淡出了互联网应用开发领域。事实上结合Java的NIO
2以及近期的Lambda表达式、Stream API的新特性。全然有可能写比Node.js更优秀的框架,仅仅可惜java开发社区在自己的思维惯性下。非常难使这样的可能变为现实。

好了,言归正传。我们首先如果我们须要查询数据库中的t_user表,当中有user_id, user_name, nick_name, birthday等字段,我们须要构造一个SQL查询。找出user_id小于10000的记录。

首先我们先定义值对象:

public class UserInfo {
public long getUserId() {
return userId;
} public void setUserId(long userId) {
this.userId = userId;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getNickName() {
return nickName;
} public void setNickName(String nickName) {
this.nickName = nickName;
} public Calendar getBirthday() {
return birthday;
} public void setBirthday(Calendar birthday) {
this.birthday = birthday;
} private long userId = 0;
private String userName = null;
private String nickName = null;
private Calendar birthday = null;
}

其次我们定义获取和释放JDBC连接的函数:

    private Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/WkyDb? user=wky&password=wky123&" +
"useUnicode=true&characterEncoding=utf-8&" +
"autoReconnect=true&failOverReadOnly=false");
} catch (Exception e) {
System.exit(0);
}
return conn;
} private void closeConnection(Connection conn) {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

以下我们来定义參数绑定函数式接口:

@FunctionalInterface
public interface FParamBinder<T> {
public void bindParams(PreparedStatement stmt, T param) throws SQLException;
}

接下来我们定义接收返回结果的函数式接口:

@FunctionalInterface
public interface FResetSetter<T> {
public List<T> getResultSet(ResultSet rst) throws SQLException;
}

以下是SQL查询的详细实现函数:

    public <T> List<T> executeQuery(String sql, FParamBinder<T> binder, T cond, FResetSetter<T> setter) {
Connection conn = getConnection();
PreparedStatement stmt = null;
ResultSet rst = null;
List<UserInfo> items = new ArrayList<UserInfo>();
UserInfo item = null;
List<T> recs = null;
try {
stmt = conn.prepareStatement(sql);
binder.bindParams(stmt, cond); // 调用參数绑定函数式接口
rst = stmt.executeQuery();
recs = setter.getResultSet(rst); // 获取返回结果集
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rst != null) {
rst.close();
}
if (stmt != null) {
stmt.close();
}
} catch (Exception ex) {}
}
closeConnection(conn);
return recs;
}

这个函数实现与普通的JDBC编程中的查询不同。參数绑定和接收结果集这两部分都是通过传入的函数式接口变量来实现,因此代码显得很简洁。

以下是其它函数调用SQL查询时对上面函数的调用,例如以下所看到的:

    public void testIt() {
String sql = "select user_id, user_name, nick_name, birthday from t_user where user_id<?";
FParamBinder<UserInfo> binder = (PreparedStatement stmt, UserInfo param) -> {
stmt.setLong(1, param.getUserId());
};
UserInfo cond = new UserInfo();
cond.setUserId(10000000L);
FResetSetter<UserInfo> setter = (ResultSet rst) -> {
List<UserInfo> items = new ArrayList<UserInfo>();
UserInfo item = null;
while (rst.next()) {
item = new UserInfo();
item.setUserId(rst.getLong(1));
item.setUserName(rst.getString(2));
items.add(item);
}
return items;
};
List<UserInfo> recs = executeQuery(sql, binder, cond, setter);
System.out.println("size=" + recs.size() + "!");
for (UserInfo u : recs) {
System.out.println("U:" + u.getUserName() + "-" + u.getUserId() + "!");
}
}

如上所述。调用者须要指定查询SQL语句,定义參数绑定函数式接口变量,结果集接收函数式接口变量,然后调用上面的executeQuery方法,就能够获取到结果集。然后就能够进行下一步的操作了。

Java8学习之旅2---基于Lambda的JDBC编程的更多相关文章

  1. Java8学习笔记(一)--Lambda表达式

    两个概念 函数式接口 函数式接口就是只显式声明一个抽象方法的接口.为保证方法数量不多不少,java8提供了一个专用注解@FunctionalInterface,这样,当接口中声明的抽象方法多于或少于一 ...

  2. Java8函数之旅 (六) -- 使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  3. Java8 学习笔记--函数式接口与lambda表达式的关系

    在java中,lambda表达式与函数式接口是不可分割的,都是结合起来使用的. 对于函数式接口,我们可以理解为只有一个抽象方法的接口,除此之外它和别的接口相比并没有什么特殊的地方.为了确保函数式接口的 ...

  4. 【小梅哥FPGA进阶学习之旅】基于Altera FPGA 的DDR2+千兆以太网电路设计

    DDR2电路设计 在高速大数据的应用中,高速大容量缓存是必不可少的硬件.当前在FPGA系统中使用较为广泛的高速大容量存储器有经典速度较低的单数据速率的SDRAM存储器,以及速度较高的双速率DDR.DD ...

  5. Java网络编程学习A轮_07_基于Buffer的Socket编程

    示例代码: https://github.com/gordonklg/study,socket module A. LineSeparate 基于 Buffer 实现逐行读取的 EchoServer ...

  6. Java8学习笔记目录

    Java8学习笔记(一)--Lambda表达式 Java8学习笔记(二)--三个预定义函数接口 Java8学习笔记(三)--方法引入 Java8学习笔记(四)--接口增强 Java8学习笔记(五)-- ...

  7. Java8学习笔记----Lambda表达式 (转)

    Java8学习笔记----Lambda表达式 天锦 2014-03-24 16:43:30 发表于:ATA之家       本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人 ...

  8. Java8学习(3)- Lambda 表达式

    猪脚:以下内容参考<Java 8 in Action> 本次学习内容: Lambda 基本模式 环绕执行模式 函数式接口,类型推断 方法引用 Lambda 复合 上一篇Java8学习(2) ...

  9. JAVA8学习——深入浅出Lambda表达式(学习过程)

    JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在 ...

随机推荐

  1. <%%>创建内联代码块(表达式)

    其实<%%>很早之前就见过了,只是会用一点功能,其它的不甚了解.今天偶尔见到了它的庐山真面目,现在共享给大家. 语法 代码块呈现(<%%>)定义了当呈现页时执行的内联代码或内联 ...

  2. 需求:在浏览器加载完毕后,自动播放视频:出现play() failed because the user didn't interact with the document first.错误

    解决方法:给video标签加入<video muted></video> 静音即可. Chrome 66为了避免标签产生随机噪音. 参考链接:https://juejin.im ...

  3. 理解String的compareTo()方法返回值

    compareTo()的返回值是整型,它是先比较对应字符的大小(ASCII码顺序), 如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值. 如果第一个字符和参数的第一个字符相等,则以第 ...

  4. 展示C代码覆盖率的gcovr工具简单介绍及相关命令使用演示样例

    (本人正在參加2015博客之星评选,诚邀你来投票,谢谢:username=zhouzxi">http://vote.blog.csdn.net/blogstar2015/candida ...

  5. POJ2029:Get Many Persimmon Trees(二维树状数组)

    Description Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aiz ...

  6. 【几何/数学】概念的理解 —— (非)刚体变换((non-)rigid transformation)

    1. 刚体变换与非刚体变换 What is a non-rigid transformation? 刚体变换(rigid transformation)一般分为如下几种: 平移对象,而不改变形状和大小 ...

  7. C# SocketAsyncEventArgs类

    Namespace:System.Net.Sockets Assemblies:System.Net.Sockets.dll, System.dll, netstandard.dll (Represe ...

  8. 安装filezilla client报错libgnutls版本旧

    http://blog.csdn.net/mofabang/article/details/9212217

  9. [React] Style a React component with styled-components

    In this lesson, we remove the mapping between a React component and the styles applied to it via cla ...

  10. php课程 9-33 php文件操作里面的注意事项有哪些

    php课程 9-33 php文件操作里面的注意事项有哪些 一.总结 一句话总结:文件操作其实很简单,就是几个文件操作函数需要记一下. 1.文件函数如何使用(如何找php文件函数的资料)? 查看参考手册 ...