数据库简易帮助包-阿里云开发者社区

开发者社区> 数据库> 正文

数据库简易帮助包

简介: 源码在:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/jdbc?dir=1&filepath=ajaxjs-base%2Fsrc%2Fcom%2Fajaxjs%2Fjdbc 概述 从 JDBC 规范上看,其对数据访问层有相当简洁的抽象: - 连接 Connection - 语句 Statement - 结果集 Result Set 因此,我们对数据库做的事情无非:连接数据库、执行语句、拿到结果。

源码在:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/jdbc?dir=1&filepath=ajaxjs-base%2Fsrc%2Fcom%2Fajaxjs%2Fjdbc

概述

从 JDBC 规范上看,其对数据访问层有相当简洁的抽象:
- 连接 Connection
- 语句 Statement
- 结果集 Result Set
因此,我们对数据库做的事情无非:连接数据库、执行语句、拿到结果。如下图所示。

这里写图片描述

故这里的 DB helper 仅仅是基于 JDBC 的简单封装,只有三个关键的类,其特性有:

  • 提供增改查三种静态函数,可以传值参数。query/queryList 查询函数主要就是将数据库的查询出来的 ResultSet 转化为 Map 或 List;新增记录返回主键;
  • 一律采用 PreparedStatment,以防止 SQL 注入及自动值类型转换;
  • 主键为 java.io.serializable 类型,兼容 int/long/string 类型;
  • 提供简易的半 ORM 方案,也就是说,这并不是完全意义上的 ORM。返回的类型可以有 Map 或者 Bean;
  • 提供简单的分页功能; 支持 JDBC 4 以及 Java 7 autoClose 自动关闭资源,无须手动 close();
  • 打印运行时出错的 SQL 语句,可以将其直接拷贝到数据库客户端上进行调试,并提供格式化 SQL 工具函数,打印日志时更美观;
  • 提炼了 MyBatis 的 SQL Builder 包,可以通过 Java 动态拼接 SQL;
  • 当前暂不提供批量操作 TODO。

数据库连接 JdbcConnection

获取数据库连接对象 DataSource
通过 JDBC 的 DriverManager.getConnection 获取数据库连接对象。提供如下方法:

Connection getConnection(String jdbcUrl);
Connection getConnection(String jdbcUrl, Properties props);

其中 jdbcUrl 参数形如 jdbc:sqlite:c:\project\foo\work\work.sqlite,无须传入数据库驱动字符串 Driver 名称(如 “org.sqlite.JDBC”),这是采用了 JDBC4 新特性的缘故,如果你的 JDK 不支持 JDBC4,可以退回旧写法:

Connection conn = null;
try {
    if (props == null)
        conn = DriverManager.getConnection(jdbcUrl);
    else
        conn = DriverManager.getConnection(jdbcUrl, props);
    LOGGER.info("数据库连接成功: " + conn.getMetaData().getURL());
} catch (SQLException e) {
    LOGGER.warning("数据库连接失败!", e);
    try { // jdbc 4的新 写法可不用 Class.forName,如果不支持,退回旧写法
        Class.forName(driver);
    } catch (ClassNotFoundException e1) {
        LOGGER.warning("创建数据库连接失败,请检查是否安装对应的 Driver:{0}。", driver);
    }
}

数据库连接池
数据源提供了一种简单获取数据库连接的方式,并能在内部通过一个池的机制来复用数据库连接。当前我们这个框架使用了 Tomcat 自带 Pool(适用于 Web),你也可以使用其他如 Druid 的数据库连接池。

// 简写方式
javax.sql.DataSource ds = (javax.sql.DataSource)new InitialContext().lookup("java:/comp/env/jdbc/derby");
// 通过数据源对象获得数据库连接对象
Connection connection = ds.getConnection();

数据库数据的增删改查

查询

先连接数据库:

Connection conn = getConnection("jdbc:sqlite:c:\\project\\foo\\work\\work.sqlite");

查询单个记录,将其转换为 map。

Map<String, Object> info = Helper.query(conn, "SELECT * FROM news WHERE id = ?", 1);

支持带参数的 SQL,如:

Map<String, Object> info = Helper.query(conn, "SELECT * FROM news WHERE id = 1");

查询多个记录,将其转换为 List。

List<Map<String, Object>> list = Helper.queryList(conn, "SELECT * FROM news WHERE type = 1");
// 或
List<Map<String, Object>> list = Helper.queryList(conn, "SELECT * FROM news WHERE type = ?", 1);

除 Connection 外,涉及的 statement、resultset 对象均采用 Java 7 autoClose 自动关闭资源,无须手动 close()。

创建&修改
为防止 SQL 注入,推荐使用 PreparedStatement。下面是 JDBC 经典的创建方法。

String createSql = "INSERT INTO myblog (name, content, uid, brief, catalog, createDate) values(?, ?, ?, ?, ?, datetime('now'))"; 
try (PreparedStatement ps = conn.prepareStatement(createSql);) {
    ps.setString(1, request.getParameter("name"));
    ps.setString(2, request.getParameter("content"));
    ps.setString(3, Util.getUUID());
    ps.setString(4, request.getParameter("brief") == null ? "" : request.getParameter("brief"));
    ps.setInt(5, Integer.parseInt(request.getParameter("catalog")));

    if (ps.executeUpdate() == 0) {
        request.setAttribute("errMsg", "创建失败!");
    } else {
        request.setAttribute("okMsg", "创建成功!");
    }
}

据此,我们封装的 create/update 使用方法如下:

// 创建一个 bean
// 返回的主键为 java.io.serializable 类型,兼容 int/long/string 的情况
Serializable newlyId = Helper.create(conn, "INSERT INTO news (name) VALUES (?)", "test2");
System.out.println(newlyId);
int id = (int)newlyId;
assertNotNull(id);

// 修改一个 bean
int updated;// 影响的行数
updated = Helper.update(conn, "UPDATE news SET name = ? WHERE id = ?", "Hi", id);
updated = Helper.update(conn, "UPDATE news SET name = 'hi' WHERE id = 60");
assertEquals(1, updated);

删除
删除方法是本类唯一封装了 SQL 语句的方法,故需要传入表名 tableName。其用法如下:

/**
 * 删除一条记录
 * 
 * @param conn
 *            数据库连接对象
 * @param tableName
 *            表名
 * @param id
 *            ID
 * @return 是否删除成功
 */
public static boolean delete(Connection conn, String tableName, Serializable id) ;
// 例子
Helper.delete(conn, "news", id);

分页

自动生成求记录总数的 SQL,如果 > 0 则允许进行分页;可指定起始数、每页记录行数。

SimplePager sp = new SimplePager(conn, sql, request.getParameter("start"));
PageResult<Map<String, Object>> pr = sp.getResult();

返回 PageResult 对象供 页面 渲染。PageResult 是一个 Java Bean。

ORM

ORM 也是围绕 CRUD 的,只不过实体类型换为 bean。
查询:

SimpleORM<News> simpleORM = new SimpleORM<>(conn, News.class);
News news = simpleORM.query("SELECT * FROM news WHERE id = ?", 23);
System.out.println(news.getName());

List<News> allNews = simpleORM.queryList("SELECT * FROM news");
System.out.println(allNews.get(23).getName());

增加、修改、删除:

News news = new News();
news.setName("标题一");
news.setIntro("hihi");

SimpleORM<News> simpleORM = new SimpleORM<>(conn, News.class);
int newlyId = (int)simpleORM.create(news, "news");
System.out.println(newlyId);

news.setName("标题二");
news.setId(newlyId); // 修改刚刚生成的记录
int effectRows = (int)simpleORM.update(news, "news");
System.out.println(effectRows);

assertTrue(simpleORM.delete(news, "news"));

当前 ORM 内部使用了不少约定的做法,例如 id 字段的名称写死了,没有允许修改——像这些是大家要注意的。

推荐参考项目 Memory:https://git.oschina.net/bitprince/memory

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章