java query接口_超轻量级 Java 持久化工具 Memory

Memory是一个小巧的Java持久化工具,模仿Dbutils设计,比它更精简,仅20多K。它提供接口简化数据库连接、语句执行和结果集处理,支持Bean直接持久化、SQL打印调试、分页查询等功能。Memory通过Memory类集成结果集处理、连接管理和语句预处理,提供命令与查询、增删改查操作,以及分页、IN语句和事务处理的接口。
摘要由CSDN通过智能技术生成

1. 概述

1.1 连接、语句和结果集

481ed7ff2ab108a44e76474ff5f17277.png

从JDBC的规范上看,其对数据访问层有相当简洁的抽象:1、连接(connection) 2、语句(statement)、3结果集(result set)。我们对数据库做的事情无非:连接数据库,执行语句,拿到结果。

因此,持久化的工具的目的就不言自明了:进一步简化连接的管理、语句的执行、结果集提取等操作。下面从获取结果集、管理连接、语句预处理等3方面逐一阐述工具做了哪些事情。

这里提一句,Memory在设计与实现上,都借鉴了Dbutils,其相对于hibernate,mybatis这些庞然大物,已经是一个极其小巧的工具。 但是Memory的类和接口更少(不超过10个),体积更小(只有二十几K),数目和体积都约为dbutils的1/3,却添加了非常实用的功能:

  • 将简单的POJO对象直接持久化到数据库中;
  • 打印运行时出错的SQL语句,其可以直接拷贝到数据库客户端上进行调试;
  • 直截了当的分页查询。

1.2 获取结果集

获取结果集,就是把ResultSet转换为目标数据结构,这里使用T(泛型)泛指各种数据结构。我们定义一个接口类来表示这件事情:

public interface ResultSetHandler {T handle(ResultSet rs) throws SQLException;}

在实际应用中,结果集是某张表或视图的一行或多行数据时,常使用BeanHandler、BeanListHandler或JSONObjectHandler、JSONArrayHandler进行处理,结果集是某一列的一行或多行数据时,使用ColumnHandler、ColumnListHandler进行处理。

1.3 连接的管理

将连接的交给外部的数据源(DataSource)进行统一管理。比如使用Tomcat容器自带的数据源。

在Tomcat的context.xml文件配置数据源xxxxx:

<?xml version="1.0" encoding="UTF-8"?> 

在代码中,采用懒加载单例模式加载数据源并实例化:

public class MemoryFactory {private MemoryFactory() {}private static class SingletonHolder {public static final Memory MEMORY = new Memory(getDataSource());//public static final Memory MEMORY = new Memory(new SimpleDataSource());}public static Memory getInstance() {return SingletonHolder.MEMORY;}public static final DataSource getDataSource() {try {Context context = new InitialContext();return (DataSource) context.lookup("java:comp/env/jdbc/test");} catch (NamingException e) {throw new RuntimeException(e);}}}

1.4 语句预处理

与ResultSetHanlder相互呼应,提供了PreparedStatementHanlder类,这个类提供语句(PreparedStatment)一些辅助性的方法,比如生成运行时的SQL语句、调整日期格式、简化分页语句写法等。这个类在应用中不会直接用到。其作用将隐藏在最重要的一个类Memory之中(与这个工具命名相同)。

2.使用

上章从结果集提取、连接管理、语句处理等3个角度介绍了这个工具,本章介绍的Memory类就是对3者的集成,分3节描述Memory开放的API。

2.1命令与查询

对数据库所有的操作,可分为两类:命令与查询。命令即更新数据,可进一步分为新增、删除与编辑。

2.1.1 查询(query)

public  T query(StringBuffer sql, ResultSetHandler rsh, List params);public  T query(String sql, ResultSetHandler rsh, Object... params);public  T query(Connection conn, StringBuffer sql,ResultSetHandler rsh, List params);public  T query(Connection conn, String sql, ResultSetHandler rsh, Object... params);

从接口定义可以看出,查询(query)方法,返回结果集,参数名也相似,只是数据结构不同而已:StringBuffer和List一组,String和Array(变长参数)一组,没有传递Connection参数,则表明连接在memory内部管理;有传递Connection参数,则表明连接交给外部程序管理。

在这个层面使用API,就是写SQL语句,几乎没有任何限制,唯一的限制就是在使用BeanHandler与BeanListHandler时,Bean的字段与Table的字段要存在相互匹配,Bean的字段命名风格是驼峰式,Table的字段命名是下划线连接。

2.1.2 命令(update)

public int update(StringBuffer sql, List params);public int update(String sql, Object... params);public int update(Connection conn, StringBuffer sql, List params);public int update(Connection conn, String sql, Object... params);public int[] batch(String sql, Object[][] params);public int[] batch(Connection conn, String sql, Object[][] params);

相对于查询(query)方法,更新(update)方法,没有结果集处理器(ResultSetHandler)的参数以及结果集转化为的对象。但更新有批量更新(batch)的方法,提供批量执行sql语句的功能。

2.2 增删改查(CRUD)

增删改查,英文缩写为CRUD,这个大家都非常熟悉,使用Create, read, update, delete来做作为接口名称,这样记忆和理解成本最低。

Lifesinger在《jQuery 为什么优秀兼谈库与框架的设计》一文中,提到:在类库界,解决了What,解决了定位问题后,基本上已经决定了生死存亡。 至于 How,也重要但往往不是关键。

本人对此深以为然,所以Memory工具在接口方法名称、类名等的使用上相当节制(数量尽量少),这点也不同于别的持久化工具。

2.2.1 新增(create)

public  int create(Class cls, T bean);public  int create(Class cls, T bean, boolean customKey);public  int create(Connection conn, Class cls, T bean);public  int create(Connection conn, Class cls, T bean, boolean customKey);public  int[] create(Class cls, List beans);public  int[] create(Class cls, List beans, boolean customKey);public  int[] create(Connection conn, Class cls, List beans);public  int[] create(Connection conn, Class cls, List beans, boolean customKey);

这些接口可持久化新增的一个对象或多个对象时。customkey这个参数表示主键的值是否使用自定的值。如果不是使用自定义的值,则采用序列(oracle)或自增主键(mysql),此时主键的名称必须是ID。

2.2.2 查询(read)

public  T read(Class cls, long id);public  T read(Connection conn, Class cls, long id);

根据主键(主键名必须为ID)读取一条记录,并转化为对象。

2.2.3 更新(update)

public  int update(Class cls, T bean);public  int update(Connection conn,Class cls, T bean);public  int update(Class cls, T bean, String primaryKey);public  int update(Connection conn, Class cls, T bean, String primaryKey);public  int[] update(Class cls, List beans);public  int[] update(Connection conn, Class cls, List beans);public  int[] update(Class cls, List beans,String primaryKey);public  int[] update(Connection conn, Class cls, List beans,String primaryKey);

这些接口可持久化更新的一个对象或多个对象时。primaryKey这个参数指定主键名称,默认是ID。

2.2.4 删除(delete)

public  int delete(Class cls, long id);public  int delete(Connection conn, Class cls, long id);

根据主键(主键名必须为ID)删除一条记录。

2.3其它

Memory的API在SQL语句操作层面分为:命令与查询(2.1节),在对象操作层面分为:增删改查(2.2节)。查询有一些常用的辅助性操作,比如分页和IN语句;在对事务有要求的场合,memory提供获取连接的接口,并将连接交给应用自行控制。

2.3.1 分页

public void pager(StringBuffer sql, List params, int pageSize, int pageNo);

分页查询几乎是必不可少的,但是oracle的分页查询语句写起来相当复杂(3重嵌套),mysql分页查询虽然简单,但是其参数limit offset, n也不够直观。分页查询,即在问如果每页pageSize条记录,那么第pageNo页的记录是什么。分页查询接口(pager)封装了oracle和mysql的查询语句,并提供了pageSize和pageNo两个直观的参数。

2.3.2 IN语句

public  void in(StringBuffer sql, List params, String operator, String field, List values)

IN语句在查询时也比较常用,占位符?必须与参数的个数相匹配,手工拼接容易出错;当参数个数是动态变化时,占位符的拼写更是繁琐,因此对IN语句做了一个简单的封装,以保持代码的简洁。

2.3.3 事务

public Connection getConnection();

可以从memory取出一条连接,然后设置连接为非自动提交,进行事务操作与回滚。

3.多余的废话

3.1为什么不用链式写法?

不少持久化的库或框架,喜欢使用链式写法来写SQL语句。但是殊不知链式的写法在Jquery很自然,在SQL中却是生搬硬套,不得其法。SQL是数据库领域的专用语言(DSL),用其本来的写法来表达是最自然的。

试举一些持久化框架的做法,比如droidparts:

 // Select is used to provide data to EntityCursorAdapterSelect select = select().columns("_id
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值