`
asklxf
  • 浏览: 36309 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

高效使用JDBC

    博客分类:
  • Java
阅读更多

在JavaEE应用中,使用ORM操作数据库虽然简单快捷(参考“高效使用JavaEE ORM”),但是毕竟是对JDBC的封装,很多时候,ORM还是不能满足我们的需求,主要是两个问题:

1. 速度不如JDBC,毕竟是封装JDBC,有额外的开销;

2. ORM提供的xQL很多时候无法满足需求,还需要数据库相关的SQL,这时,必须使用JDBC。

使用JDBC虽然麻烦点,但是,按照软件设计的思想,一步一步封装必要的代码,还是可以做到性能与开发效率并存。

首先,要坚决避免的就是不断重复编写try... catch... finally...。对于查询、更新、插入和删除操作,每一种操作只允许编写一次try... catch... finally...。如何实现?有两个方法。

第一个办法是找一个现成的封装了这些JDBC操作的框架,最好的方案当然就是Spring的JDBC框架了,顺便可以参考JdbcTemplate的源码,以便提升自己的JavaEE功力。

如果不使用Spring,那就采用第二个办法,自己造轮子,封装一个JDBC框架。

很多人反对自己造轮子,原因不外乎费事。不过很多时候,造轮子并不麻烦,而且可以满足特定的需求。今天要造的轮子就是一个封装JDBC的框架:Express-Persist

Express-Persist是ExpressMe的持久化子项目,目标是封装JDBC并提供简单的数据库操作接口。

为什么不使用Spring JDBC呢?主要原因只有一个:Spring的JDBC目前还是1.4兼容的,不支持1.5的泛型。Express-Persist要提供的接口除了基本的数据库操作外,还要实现:

1. 简单的ORM映射,注意是简单的,没有Hibernate那样完整而强悍,本质上就是把ResultSet的每一条记录变成一个JavaBean,可以参考Spring JDBC的RowMapper,实现非常容易;

2. 充分利用Java 5泛型支持,都是类型安全的参数和返回值,不用做强制转化;

3. 利用Java 5的注解(Annotation)把SQL标记在接口方法上,比如:

1.@Query("select * from User where u.id=:id")
2.public User get(String id);

4. 最后,最重要的,只编写接口,没有实现类!

没有实现类,那JDBC代码写在哪?当然由Express-Persist框架自动生成了。如何自动生成?运行一个命令自动生成Java类?在“高效使用JavaEE ORM”一文中我们已经对JDO的这种静态增强方式表示了强烈的鄙视和唾弃,因此绝不可重蹈覆辙。Express-Persist会在启动时根据接口动态创建出类,不过我们不采用Hibernate使用的CGLIB库,而是直接通过JDK的动态代理功能实现动态类。

如何绑定SQL参数

DAO接口的方法参数要自动绑定到SQL参数中,由于方法参数的顺序与SQL参数的顺序可能不一致,因此,只能使用命名参数来绑定,即:SQL参数定义为:xxx,对应的方法参数用@Param("xxx")标记。

当SQL参数很多的时候(尤其是INSERT语句),方法参数也非常多,调用起来非常不方便,比如:

1.@Update("insert into User values(:id, :email, :password, :name)")
2.public int create(@Param("id") String id, @Param("email") String email,@Param("password") String password, @Param("name") String name);

而且都是String类型,调用起来容易出错。

因此,Express-Persist允许使用JavaBean绑定,把上述代码变为:

1.@Update("insert into User values(:u.id, :u.email, :u.password, :u.name)")
2.public int create(@Param("u") User u);

这样,调用起来只需要传入一个User对象即可,简单且不易出错。

如何分页查询

绝大多数数据库支持分页查询,但语法各不相同。如果让开发者自己写分页SQL语句,难度较大,而且不易复用。因此,Express-Persist仿照Hibernate的做法,为每一种数据库定义一个Dialect,处理分页,这样,无需考虑数据库的特定分页语法,只需额外添加@FirstResult和@MaxResults这两个注解,以便传入分页参数:

1.@Query("select * from User u order by id")
2.List<User> queryAll(@FirstResult int first, @MaxResults int max);

Express-Persist已经内置HSQLDB、MySQL和Oracle的Dialect支持,也可以编写其他数据库的Dialect,只需实现Dialect接口即可。

如何把ResultSet映射为Java对象

要把ResultSet映射为Java对象,我们采用Spring JDBC使用的RowMapper方案,改进之处在于采用了泛型,并且,提供一个BeanRowMapper,实现ResultSet到JavaBean的转换,因为大部分的转换都是到JavaBean。

利用Java 5的泛型支持,可以非常容易地生成一个BeanRowMapper,而无需编写任何方法:

1.public class UserRowMapper extends BeanRowMapper<User> {}

@MappedBy用于告诉Express-Persist如何映射ResultSet:

1.@MappedBy(UserRowMapper.class)
2.@Query("select * from User u order by id")
3.List<User> queryAll(@FirstResult int first, @MaxResults int max);

如果返回结果仅有一个,例如根据主键查询,则必须加上一个@Unique注解,这样,Express-Persist将自动检查返回的记录数,如果不为1,则抛出异常:

1.@Unique
2.@MappedBy(UserRowMapper.class)
3.@Query("select * from User u where id=:id")
4.User queryById(@Param("id") String id);

如果返回结果允许多个,则返回值应该定义为泛型List,如List<User>。

Batch支持

批量插入或修改时,使用和不使用JDBC Batch,其性能将有数量级的差距。Express-Persist提供Batch支持,通过继承BatchSupport接口:

1.public class UserDao extends BatchSupport {
2.@Update("update User set name=:name where id=:id")
3.void updateUserName(@Param("id") String id, @Param("name") String name);
4.}

Batch操作的代码稍微复杂一点,必须用try... finally执行,以便正确释放资源:

01.try {
02.dao.prepareBatch();
03.// now the batch prepared:
04.dao.updateUserName("id-1""change A's name");
05.dao.updateUserName("id-2""change B's name");
06.dao.updateUserName("id-3""change C's name");
07.// execute:
08.int[] results = dao.executeBatch();
09.}
10.finally {
11.dao.closeBatch();
12.}

事务控制

Express-Persist仅支持JDBC事务,因此无法远程传播事务。事务代码通常写在Web应用程序的Filter或Interceptor中,只需编写一次:

01.TransactionManager txManager = ...;
02.Transaction tx = txManager.beginTransaction();
03.try {
04.// TODO: DAO operations here...
05.tx.commit();
06.}
07.catch (Exception e) {
08.tx.rollback();
09.}

如果你想体验一下Express-Persist带来的全新Java持久化方案,可以从http://express-me.googlecode.com/files/express-persist.jar下载Jar包(含源代码)。完整的文档请参考http://code.google.com/p/express-me/wiki/ExpressPersist

12
6
分享到:
评论
14 楼 chenchangqun11 2011-01-06  
你这文章与标题不符啊
13 楼 rain16881 2009-10-19  
请问有没一个完整的测试代码啊!!..
不清楚怎样用呢.
本人e-mail
rain16881@hotmail.com

thanks you ..
12 楼 qbq 2009-09-18  
感觉这个很像seasar的s2dao
有对这种方式感兴趣的可以看看
个人感觉s2dao封装得更好,更易用
11 楼 xiaoban0514 2009-09-17  
treblesoftware 写道
用ORM提高的是开发效率。不是程序效率。而且,ORM用好,在某些方面效率不比JDBC差,综合来说,ORM更加实用。

想把ORM用好也不是简单的事,反正个人觉得还是JDBC效率更加好点。
10 楼 asklxf 2009-09-17  
mathfox 写道
感觉怎么文不对题呢?

有一点广告成分
9 楼 asklxf 2009-09-17  
superdandy 写道
为什么要使用jdk的动态代理呢? 既然使用薄层封装jdbc,就是为了提高性能。 那么为什么要使用jdk的接口动态代理机制呢? 速度明显比cglib慢的

动态代理很快,可以忽略不计,不用cglib是为了尽量少依赖jar
8 楼 pangbuddy 2009-09-17  
treblesoftware 写道
用ORM提高的是开发效率。不是程序效率。而且,ORM用好,在某些方面效率不比JDBC差,综合来说,ORM更加实用。


顶你!
7 楼 xly_971223 2009-09-17  
en 受够了hibernate的可以试试这个
6 楼 superdandy 2009-09-17  
为什么要使用jdk的动态代理呢? 既然使用薄层封装jdbc,就是为了提高性能。 那么为什么要使用jdk的接口动态代理机制呢? 速度明显比cglib慢的
5 楼 caizhongda 2009-09-16  
我感觉是跟风啊。。为什么啥都想用Annotation呢。?
4 楼 唯快不破 2009-09-16  
我自己的项目是jdbc查询,orm用来增,删,改。
3 楼 treblesoftware 2009-09-16  
用ORM提高的是开发效率。不是程序效率。而且,ORM用好,在某些方面效率不比JDBC差,综合来说,ORM更加实用。
2 楼 mathfox 2009-09-16  
感觉怎么文不对题呢?
1 楼 myseo 2009-09-16  
用dbutils吧

相关推荐

    JDBC数据库访问工具类 强大 精巧 高效

    JDBC数据库访问工具类 强大 精巧 高效

    高性能jdbc分页处理

    高性能jdbc分页处理,使用PreparedStatement方式

    JDBC笔记 JDBC笔记

    然后可以使用此对象高效地多次执行该语句。 java.sql.CallableStatement 用来访问数据库中的存储过程。它提供了一些方法来指定语句所使用的输入/输出参数。 java.sql.ResultSet 指的是查询返回的数据库结果集。 ...

    JDBC POOL 高效数据源配置

    Tomcat 7 的 新数据源配置方式,context.xml 配置了一个性能优秀的数据源,数据库的账号,密码和url需要根据自己的项目实际情况来修改

    jdbc连接数据库方法大全

    jdbc连接数据库方法大全,提供了各种jdbc连接数据库的方法,让你明了哪种方法更高效

    java JDBC封装库

    自己封装好的,基于commons的DBBase,DBCP的数据库工具。支持线程池,支持直接...属于超轻量级JDBC高效开发工具。 附DOC文档和源代码。如有改进意见,请邮件我。supperman_009@163.com 邮件请注明:CSDN 资源下载改进

    java8stream源码-mjdbc:小而高效的JDBC包装器

    小而高效的 JDBC 包装器。 小:没有外部依赖。 Jar 大小小于 50kb。 简单:无需特殊配置。 在 1 行初始化代码后开始使用它。 可靠:所有 SQL 语句都在应用程序启动时进行解析和验证。 灵活:在需要时直接切换和使用...

    java JDBC连接数据库,并将数据分页

    使用JDBC技术连接oracle数据库,并且实现简单的数据分页,能够更加高效的提取数据

    基于JDBC的数据库连接池高效管理策略

    基于JDBC的数据库连接池高效管理策略,很老的资料了

    JDBC加载数据库驱动的三种方法

    JDBC加载数据库驱动的三种方法 简单高效

    proc-odbc-jdbc

    用代码进行数据库链接

    基于java某百货店POS积分管理系统的毕业设计,系统采用MySQL数据库进行数据存储,使用JDBC技术实现数据的访问

    系统采用MySQL数据库进行数据存储,使用JDBC技术实现数据的访问。 MySQL数据库采用关系型数据存储,具有良好的扩展性和稳定性,能够满足系统对数据存储的各种需求。JDBC技术是一种标准的Java API,能够实现多种数据库的...

    Druid是一个JDBC组件,它包括三部分 高效可管理的数据库连接池.rar

    Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。 DruidDataSource 高效可管理的数据库连接池。 SQLParser Druid可以做什么? 1) 可以监控数据库...

    JDBC连接池(转发)

    本文介绍了基于JDBC的数据库连接池的工作原理,阐述了连接池技术的事务处理、多数据库服务器等各项关键技术,提出了一个高效的连接池管理策略,最后详细说明了数据库连接池应用的具体实现过程。 我觉得很有启发,...

    安卓 SQLite JDBC 加密技术

    SQLite Security JDBC 驱动实现了Android平台下可以使用JDBC访问SQLite数据库的能力, 提供的加密引擎是采用透明加密方式,应用程序访问SQLite不需要做任何修改,就能高效地对SQLite数据库进行数据加密。

    kingbaseV8 jdbc 驱动 kingbase8-8.2.0.jar

    Java版本 人大金仓ESV8最新版驱动程序,学习使用国产化数据库操作。 金仓通用数据库,可视化操作,毫秒级数据处理,高效准确完成数据处理全过程。面向事务处理类、兼顾分析类应用领域场景,兼容Oracle、国产数据库等多...

    阿里巴巴的开源项目JDBC连接池、监控组件 Druid.zip

    Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。 DruidDataSource 高效可管理的数据库连接池。 SQLParser Druid可以做什么? 1) 可以监控数据库访问...

    java jdbc原生连接+连接池.zip

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问解决部分mybatis或者hibernate不支持的数据库,例informix。通过pool连接池提高性能,并将...

    项目基于JDBC+MySQL的Java教务管理系统(附源码+论文说明)

    JDBC:作为Java程序访问数据库的标准接口,使用JDBC可以方便地连接和操作MySQL数据库。 MySQL数据库:作为一种开源的关系型数据库管理系统,MySQL提供了稳定、高效的数据存储和管理能力。 Java Control:实现用户...

    oracle+MySQL+jdbc数据库教程

    学员将通过实战示例掌握如何使用JDBC API进行数据库连接、执行SQL命令、处理结果集,以及进行事务管理。这一技能对于Java后端开发者来说是必不可少的,能够极大地提升其在企业级应用开发中的竞争力。 通过本课程的...

Global site tag (gtag.js) - Google Analytics