虽然现在出现了很多ORM框架,可是还是有很多朋友也许还在使用JDBC,就像我现在一样,除了学习的时候在使用Hibernate、Spring类似这些优秀的框架,工作时一直都在使用JDBC。本文就简单介绍一下利用Jakarta Commons旗下beanutils、dbutils简化JDBC数据库操作,
虽然现在出现了很多ORM框架,可是还是有很多朋友也许还在使用JDBC,就像我现在一样,除了学习的时候在使用Hibernate、Spring类似这些优秀的框架,工作时一直都在使用JDBC。本文就简单介绍一下利用Jakarta Commons旗下beanutils、dbutils简化JDBC数据库操作,以抛砖引玉,希望对像我一样在使用JDBC的朋友有所帮助。下面就分两部分简单介绍beanutils、dbutils在基于JDBC API数据库存取操作中的运用。第一部分显介绍beanutils在JDBC数据库存取操作中的运用,第二部分介绍dbutils在JDBC数据库存取操作中的运用,最后看看他们的优缺点,谈谈本人在项目运用过程中对他们的一点心得体会,仅供参考,其中有错误的地方希望大虾不吝赐教,大家多多交流共同进步。
一、Jakarta Commons beanutils
Beanutils是操作Bean的锐利武器,其提过的BeanUtils工具类可以简单方便的读取或设置Bean的属性,利用Dyna系列,还可以在运行期创建Bean,符合懒人的习惯,正如LazyDynaBean,LazyDynaClass一样,呵呵。这些用法已经有很多文章提及,也可以参考apache的官方文档。
对于直接利用JDBC API访问数据库时(这里针对的是返回结果集ResultSet的查询select),大多数都是采用两种方式,一种是取出返回的结果集的数据存于Map中,另一种方式是Bean里。针对第二种方式,Beanutils里提供了ResultSetDynaClass结合DynaBean以及RowSetDynaClass结合DynaBean来简化操作。下面用以个简单的例子展示一下beanutils的这两个类在JDBC数据库操作中的运用。
请在本机建立数据库publish,我用的是MySQL,在publish数据库中建立表book,脚本如下:
CREATE TABLE book(
id int(11) NOT NULL auto_increment,
title varchar(50) character set latin1 NOT NULL,
authors varchar(50) character set latin1 default NULL,
PRIMARY KEY (id)
)
然后用你喜欢的编辑器建立一个类BeanutilsJDBCTest,我们先用ResultSetDynaClass来处理,然后再用RowSetDynaClass来实现同样的类,之后看看他们之间有什么不同,用ResultSetDynaClass处理的源代码如下所示:
然后用你喜欢的编辑器建立一个类BeanutilsJDBCTest,我们先用ResultSetDynaClass来处理,然后再用RowSetDynaClass来实现同样的类,之后看看他们之间有什么不同,用ResultSetDynaClass处理的源代码如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.ResultSetDynaClass;
public class BeanutilsJDBCTest{
public static void main(String[] args) {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
con = DriverManager.getConnection(url, "root", "hyys");
st = con.createStatement();
rs = st.executeQuery("select * from book");
ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);
Iterator itr = rsDynaClass.iterator();
System.out.println("title-------------authors");
while (itr.hasNext()) {
DynaBean dBean = (DynaBean) itr.next();
System.out.println(PropertyUtils.getSimpleProperty(dBean,"title")
+ "-------------"+ PropertyUtils.getSimpleProperty(dBean, "authors"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
用RowSetDynaClass处理的源代码如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.RowSetDynaClass;
public class BeanutilsJDBCTest{
public static void main(String[] args) {
List rsDynaClass = rsTest();
System.out.println("title ------------- authors ");
Iterator itr = rsDynaClass.iterator();
while (itr.hasNext()) {
DynaBean dBean = (DynaBean) itr.next();
try {
System.out.println(PropertyUtils.getSimpleProperty(dBean,"name")
+ "-------------"+ PropertyUtils.getSimpleProperty(dBean, "mobile"));
} catch (Exception e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
}
private static List rsTest() {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
con = DriverManager.getConnection(url, "root", "hyys");
st = con.createStatement();
rs = st.executeQuery("select * from book");
RowSetDynaClass rsdc = new RowSetDynaClass(rs);
return rsdc.getRows();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
这两个方法输出的结果应该是一样的。但是很显然第二种方式比第一种方式要好,它把数据访问部分抽取出来放到一个方法中,显得简单清晰。
其实在利用ResultSetDynaClass时,必须在ResultSet等数据库资源关闭之前,处理好那些数据,你不能在资源关闭之后使用DynaBean,否则就会抛出异常,异常就是说不能在ResultSet之后存取数据(具体的异常名我也忘了),当然你也可以采用以前的方式一个一个的把数据放到Map里,如果你一定要那样做,建议还是别用Beanutils,因为这没带给你什么好处。总之利用ResultSetDynaClass你的程序的扩展性非常部好。
从第二中方式可以看出,利用RowSetDynaClass可以很好的解决上述ResultSetDynaClass遇到的问题,RowSetDynaClass的getRows()方法,把每一行封装在一个DynaBean对象里,然后,把说有的行放到一个List里,之后你就可以对返回的List里的每一个DynaBean进行处理,此外对于DynaBean你还可以采用标准的get/set方式处理,当然你也可以用PropertyUtils. getSimpleProperty(Object bean, String name)进行处理。
从上面的分析中,你应该可以决定你应该使用ResultSetDynaClass还是RowSetDynaClass了。
二、Jakarta Commons dbutils:
用JDBC API时最令人讨厌的就是异常处理,也很烦琐,而且很容易出错,本人曾考虑过利用模板进行处理,后来看到了dbutils,之后就采用那个dbutils,采用模板的方式各位朋友可以参考Spring,Spring的JdbcTemplate不灵活而强大,呵呵,说句闲话,实在太佩服Rod Johnson了,Rod Johnson真的很令人尊敬。
Dbutils的QueryRunner把大多数与关闭资源相关的封装起来,另外,你也可以使用DbUtils进行关闭,当然DbUtils提供的功能当然不止这些,它提过了几个常用的静态方法,除了上述的关闭资源外,DbUtils. commitAndClose(Connection conn)还提供事务提及等操作。
还是以一个例子来说说吧,毕竟我不是搞业务的,小嘴巴吧嗒吧哒不起来啊,呵呵。
为了和采用Beanutils更好的进行对比,这个例子还是实现同样的功能,数据库同样采用前一篇文章中提到的publish。
同样的,用你喜欢的编辑器建立一个类DbutilsJDBCTest,示例代码如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
public class DbutilsJDBCTest{
public static void main(String[] args) {
Connection conn = null;
String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
String jdbcDriver = "com.mysql.jdbc.Driver";
try {
DbUtils.loadDriver(jdbcDriver);
// Username "root". Password "root"
conn = DriverManager.getConnection(jdbcURL, "root", "root");
QueryRunner qRunner = new QueryRunner();
System.out.println("***Using MapListHandler***");
//以下部分代码采用Map存储方式,可以采用Bean的方式代替进行处理
List lMap = (List) qRunner.query(conn,
"select title,authors from books", new MapListHandler());
//以下是处理代码,可以抽取出来
System.out.println("title ------------- authors ");
for (int i = 0; i Map vals = (Map) lMap.get(i);
System.out.println(vals.get("title")+"-------------"+ vals.get("authors"));
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
怎么样?是不是比采用Beanutils的ResultSetDynaTrial和RowSetDynaClass好多了?采用Beanutils令人难缠的是关闭那些资源以及处理那些异常,而这里采用Dbutils显然代码量减少了很多。
上例在处理结果集时,它把数据库中的每一行映射成一个Map,其中列名作为Key,该列对应的值作为Value存放,查询的所有的数据一起放在一个List里,然后进行处理,当然,一个更明智的处理是直接返回List然后再单独进行处理。
事实上上例返回的结果集中的每一行不必放在一个Map里,你可以放在一个Bean里,当然如果你真的很懒,你也可以使用Beanutils的LazyDynaClass和LazyDynaBean,不过也许没有必要那么做,至于原因请看下文。
如果使用Bean而不是用Map,那么,你也许需要建立一个Bean,如下:
package cn.qtone.test;
public class Book {
public int id;
public String title;
public String authors ;
public StudentBean() {
}
public String getAuthors() {
return authors;
}
public void setAuthors(String authors) {
this.authors = authors;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
然后简单修改一下DbutilsJDBCTest 中的部分代码即可,代替之后的源代码如下:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
public class DbutilsJDBCTest{
public static void main(String[] args) {
Connection conn = null;
String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
String jdbcDriver = "com.mysql.jdbc.Driver";
try {
DbUtils.loadDriver(jdbcDriver);
// Username "root". Password "root"
conn = DriverManager.getConnection(jdbcURL, "root", "root");
QueryRunner qRunner = new QueryRunner();
System.out.println("***Using BeanListHandler ***");
//以下部分代码采用Map存储方式,可以采用Bean的方式代替进行处理
List lBeans = (List) qRunner.query(conn," select title,authors from books ", new BeanListHandler(Book.class));
//以下是处理代码,可以抽取出来
System.out.println("title ------------- authors ");
for (int i = 0; i Book vals = (Book) lBeans.get(i);
System.out.println(vals.getTitle ()+"-------------"+ vals. getAuthors ());
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
这两种法输出的结果应该是一样的。两种处理方式都差不多,但我更愿意采用第一种,因为第一种少写一个bean,而且我测试过采用Map的方式即第一种方式性能要好的多,采用Bean性能比较低可能是因为采用反射的缘故,采用反射的东东性能和不采用反射的还是有点差距。也是这个原因,不推荐采用LazyDynaClass和LazyDynaBean,因为采用这二者是在运行期动态创建Bean类和Bean属性,然后再创建Bean对象的,其性能可想而知了(不过我没有测试过啊,所以我说这个话可说是没有根据的,感兴趣的朋友自己测试一下,记得告诉我结果哦,呵呵),除了MapListHandler以及BeanListHandler之外,DButils还提供了其他的Handler,如果这些不能满足你的需求,你也可以自己实现一个Handler。
最后,也是最大的体会,也许是最大的收获吧,那就是:对于每一个项目,在根据每一个需求获取相应解决方案时,先寻找开源组件,看是否已经有满足某些功能需求的开源组件,如果没有,再考虑自主开发或者向第三方购买,否则尽量采用开源组件.
请尽量享用开源的魅力,尽情的拥抱开源吧。
好了,终于写完了,有什么问题请联系我,大家互相交流交流

如何利用GitLab进行项目文档管理一、背景介绍在软件开发过程中,项目文档是非常重要的资料,不仅能够帮助开发团队了解项目的需求和设计,还能提供给测试团队和客户参考。为了方便项目文档的版本控制和团队协作,我们可以利用GitLab来进行项目文档管理。GitLab是一个基于Git的版本控制系统,除了支持代码管理,还可以管理项目文档。二、GitLab环境搭建首先,我

Vue是目前最流行的前端框架之一,而VUE3则是Vue框架的最新版本,相较于VUE2,VUE3具备了更高的性能和更出色的开发体验,成为了众多开发者的首选。在VUE3中,使用extends继承组件是一个非常实用的开发方式,本文将为大家介绍如何使用extends继承组件。extends是什么?在Vue中,extends是一个非常实用的属性,它可以用于子组件继承父

Vue怎么通过JSX动态渲染组件?下面本篇文章给大家介绍一下Vue高效通过JSX动态渲染组件的方法,希望对大家有所帮助!

在VSCode中开发Vue/React组件时,怎么实时预览组件?本篇文章就给大家分享一个VSCode 中实时预览Vue/React组件的插件,希望对大家有所帮助!

抖音作为一个全球知名的短视频社交平台,靠着其独特的个性化推荐算法赢得了广大用户的青睐。本文将深入研究抖音视频推荐的价值和原理,帮助读者更好地了解和充分利用这一功能。一、什么是抖音推荐视频抖音推荐视频是根据用户的兴趣和行为习惯,利用智能推荐算法为用户筛选和推送个性化视频内容。抖音平台通过分析用户的观看历史、点赞和评论行为、分享记录等数据,从庞大的视频库中精选出最符合用户口味的视频进行推荐。这种个性化推荐系统不仅提高了用户体验,也帮助用户发现更多符合其喜好的视频内容,从而增强用户黏性和留存率。在这个

VUE3开发入门教程:使用组件实现分页分页是一个常见的需求,因为在实际开发中,我们往往需要将大量的数据分成若干页以展示给用户。在VUE3开发中,可以通过使用组件实现分页功能,本文将介绍如何使用组件实现简单的分页功能。1.创建组件首先,我们需要创建一个分页组件,使用“vuecreate”命令创建VUE项目,并在src/components目录下创建Pagin

Vue.js是一款流行的前端JavaScript框架,它提供了一种简单易用的方式来构建动态网页应用程序。Vue.js的主要特点是其模块化的设计和可插拔的组件系统。这使得开发者可以轻松地创建可复用的组件,从而提高了应用程序的重用性和可维护性。在本文中,我们将重点介绍VUE3初学者如何使用Vue.js组件组合实现可复用组合。Vue.js组件是一个完整的封装元素,

react让子组件不渲染的方法:1、通过“shouldComponentUpdate(nextProps,nextState){...}”实现父组件渲染,子组件不渲染;2、通过“PureComponent”方式让子组件不渲染;3、引入memo,用memo把hooks包裹即可。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境