DbUtils

本文介绍了一个对JDBC进行封装的工具——DBUtils,通过实际案例展示了如何使用它简化数据库操作,包括查询、更新等基本功能。
今天花了一晚上的时间来学习dbutils,其实一开始都不知道有这个东西,都是通过一师兄说的,说这东西挺好用,操作又简单,于是就怀揣着一颗好奇的心去学习了一下dbutils。本身dbutils就是对jdbc做了一层薄薄的封装,前段时间也学习过JdbcTemplate,自己做了一下比较,感觉这俩东西很相似,毕竟都是对JDBC简单的封装,但是自我感觉dbutils更简单,更易于操作,对jdbc封装的更薄

既然是使用别人的东西,当然得把它的东西加进来。其实很小,这个包又不依赖于其他包,就只有一个包而已,然后再加上我们自己还要使用到的一些到,既然是对数据库操作,数据库的驱动包当然不能少了,我这里使用的mysql,再加上一个log4j。


下面直接来看一下例子吧。为了更省事,我将DAO层又简单的封装了一层。首先提取一个DAO接口。
/**
 * 
 */
package org.byent.dao;
import java.util.List;
import java.util.Map;
/**
 * @author Z.ting 2011-8-10 下午07:57:27
 */
public interface Dao {
	public <T> List<T> findAll(Class<T> clazz);
	public <T> T findById(Class<T> clazz, int id);
	public long insert(String sql, Object... args);
	public long update(String sql, Object... args);
	public List<Map<String, Object>> executeQuery(String sql, Object... args);
	public long executeUpdate(String sql, Object... args);
	public void delete(String sql, Object... args);
	public int[] batchUpdate(String sql, Object[][] objs);
}
                      
这里边就是定义一些CRUD的操作,大家对这个应该不陌生了。现在接口有了,当然需要写一个实现类来完成这个接口所定义的一些工作咯,下面来看下DAO的实现类。

/**
 * 
 */
package org.byent.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.log4j.Logger;
import org.byent.dao.Dao;
import com.mysql.jdbc.JDBC4Connection;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
/**
 * @author Z.ting 2011-8-10 下午08:05:06
 */
public class DaoImpl implements Dao {
	private MysqlDataSource dataSource = new MysqlDataSource();
	private QueryRunner qryRun = null;
	private Logger logger = Logger.getLogger(getClass());
	private java.sql.DatabaseMetaData dbmb;
	public DaoImpl() {
		dataSource.setUrl("jdbc:mysql://localhost:3306/blog");
		dataSource.setUser("root");
		dataSource.setPassword("zhangting");
		qryRun = new QueryRunner(dataSource);
		dbmb = getDatabaseMetaData();
	}
	private java.sql.DatabaseMetaData getDatabaseMetaData() {
		Properties info = new Properties();
		info.setProperty("user", "root");
		info.setProperty("password", "zhangting");
		java.sql.DatabaseMetaData metaData = null;
		try {
			metaData = new JDBC4Connection("localhost", 3306, info, "blog", null).getMetaData();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return metaData;
	}
	@Override
	public <T extends Object> List<T> findAll(Class<T> clazz) {
		ResultSetHandler<List<T>> rsh = new BeanListHandler<T>(clazz);
		List<T> result = null;
		try {
			result = qryRun.query("select * from " + clazz.getSimpleName(), rsh);
			logger.debug("SQL: select * from " + clazz.getSimpleName());
		} catch (SQLException e) {
			logger.error("Can not this query table " + clazz.getSimpleName(), e);
		}
		return result;
	}
	@Override
	public <T> T findById(Class<T> clazz, int id) {
		ResultSetHandler<T> rsh = new BeanHandler<T>(clazz);
		T result = null;
		try {
			ResultSet rs = dbmb.getPrimaryKeys(null, null, clazz.getSimpleName());
			String primary_key = null;
			while (rs.next()) {
				primary_key = rs.getString("Column_name");
			}
			if (!"".equals(primary_key) || null != primary_key) {
				result = qryRun.query("select * from " + clazz.getSimpleName() + 
				" where " + primary_key + "=?", rsh, new Object[] { id });
				logger.debug("SQL: select * from " + clazz.getSimpleName() + " where " + 

                    primary_key + "=" + id);
			} else {
				logger.error("This table " + clazz.getSimpleName() + " has not primary key");
				throw new SQLException("This table has not primary key");
			}
		} catch (SQLException e) {
			logger.error("Can not this query table " + clazz.getSimpleName(), e);
		}
		return result;
	}
	@Override
	public List<Map<String, Object>> executeQuery(String sql, Object... args) {
		MapListHandler rsh = new MapListHandler();
		List<Map<String, Object>> result = null;
		try {
			result = qryRun.query(sql, rsh, args);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	@Override
	public long insert(String sql, Object... args) {
		return executeUpdate(sql, args);
	}
	@Override
	public long update(String sql, Object... args) {
		return executeUpdate(sql, args);
	}
	@Override
	public void delete(String sql, Object... args) {
		executeUpdate(sql, args);
	}
	@Override
	public long executeUpdate(String sql, Object... args) {
		long id = 0;
		try {
			id = qryRun.update(sql, args);
		} catch (SQLException e) {
			logger.error("This table can not changed !", e);
		}
		return id;
	}
	@Override
	public int[] batchUpdate(String sql, Object[][] objs) {
		int[] ids = null;
		try {
			ids = qryRun.batch(sql, objs);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return ids;
	}
}
                      


看见这个QueryRunner了吗,这个类就是我们应该控制的类。然后对数据库的一步步工作都由这个东西来帮我们完成了。

是不是突然觉得真的很简单?简简单单的一个调用就把一切工作都帮我们完成了,其实我们使用到的无非就是query、update、batch操作。

操作完成的结果都是由实现ResultSetHandler此接口的类来完成的。看一下我们都可以将结果包装成什么类型来返回给客户端吧。



看一下吧,都是我们常用到的容器类。实现一些常用的结果返回已经足够了。再来看一下它的core包。


BasicRowProcessor与BeanRowProcessor主要是将数据库的记录封装到各个容器与bean文件中。DbUtils主要就是完成了以前ResultSet,Connection,statement这些个的关闭啊,回滚啊。一些个我们以前写个简单查询就要噼里啪啦写一大堆的东西。现在没那么麻烦了,因为DbUtils已经帮我们完成了。

接下来再写个测试类来测试一下是否通过吧。
package org.byent.dao.impl.test;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.byent.dao.Dao;
import org.byent.dao.impl.DaoImpl;
import org.byent.pojo.Sex;
import org.junit.Before;
import org.junit.Test;
public class DaoImplTest {
	private Dao dao;
	@Before
	public void testDaoImpl() {
		dao = new DaoImpl();
	}
	@Test
	public void testFindAll() {
		List<Sex> result = dao.findAll(Sex.class);
		Assert.assertEquals(result.size(), 6);
	}
	@Test
	public void testFindById() {
		Sex sex = dao.findById(Sex.class, 4);
		Assert.assertEquals(sex.getSex_mc(), "男");
	}
	@Test
	public void testExecuteQuery() {
		List<Map<String, Object>> result = dao.executeQuery("select * from sex where sex_id=?", new Object[] { 1 });
		Assert.assertEquals(result.get(0).get("sexId"), "女");
	}
	@Test
	public void testInsert() {
		long id = dao.insert("insert into sex (sex_mc) values (?)", new Object[] { "男" });
		Assert.assertNotNull(id);
	}
	@Test
	public void testUpdate() {
		long id = dao.update("update sex set sex_mc=? where sex_id=?", new Object[] { "男", 5 });
		Assert.assertEquals(id, 5);
	}
	@Test
	public void testDelete() {
		dao.delete("delete from sex where sex_id=?", new Object[] { 5 });
	}
	// @Test
	public void testExecuteUpdate() {
	}
	@Test
	public void testBatchUpdate() {
		Object[][] objs = new Object[][] { { "man" }, { "women" }, { "man" } };
		int[] ids = dao.batchUpdate("insert into sex (sex_mc) values(?)", objs);
		Assert.assertEquals(3, ids.length);
	}
}
                      

亮绿灯了,表明测试已经通过。

PS:现在操作数据库的框架可真多啊,东西多了,学习起来还真是个麻烦的事,打好基础才是王道,现在所谓的持久化框架最终还是基于JDBC开发。效率高才是真的好。

看一下官方给的Example: http://commons.apache.org/dbutils/examples.html
然后自己再深入到源码看一下就一切都明白了。
该数据集通过合成方式模拟了多种发动机在运行过程中的传感器监测数据,旨在构建一个用于机械系统故障检测的基准资源,特别适用于汽车领域的诊断分析。数据按固定时间间隔采集,涵盖了发动机性能指标、异常状态以及工作模式等多维度信息。 时间戳:数据类型为日期时间,记录了每个数据点的采集时刻。序列起始于2024年12月24日10:00,并以5分钟为间隔持续生成,体现了对发动机运行状态的连续监测。 温度(摄氏度):以浮点数形式记录发动机的温度读数。其数值范围通常处于60至120摄氏度之间,反映了发动机在常规工况下的典型温度区间。 转速(转/分钟):以浮点数表示发动机曲轴的旋转速度。该参数在1000至4000转/分钟的范围内随机生成,符合多数发动机在正常运转时的转速特征。 燃油效率(公里/升):浮点型变量,用于衡量发动机的燃料利用效能,即每升燃料所能支持的行驶里程。其取值范围设定在15至30公里/升之间。 振动_X、振动_Y、振动_Z:这三个浮点数列分别记录了发动机在三维空间坐标系中各轴向的振动强度。测量值标准化至0到1的标度,较高的数值通常暗示存在异常振动,可能与潜在的机械故障相关。 扭矩(牛·米):以浮点数表征发动机输出的旋转力矩,数值区间为50至200牛·米,体现了发动机的负载能力。 功率输出(千瓦):浮点型变量,描述发动机单位时间内做功的速率,取值范围为20至100千瓦。 故障状态:整型分类变量,用于标识发动机的异常程度,共分为四个等级:0代表正常状态,1表示轻微故障,2对应中等故障,3指示严重故障。该列作为分类任务的目标变量,支持基于传感器数据预测故障等级。 运行模式:字符串类型变量,描述发动机当前的工作状态,主要包括:怠速(发动机运转但无负载)、巡航(发动机在常规负载下平稳运行)、重载(发动机承受高负荷或高压工况)。 数据集整体包含1000条记录,每条记录对应特定时刻的发动机性能快照。其中故障状态涵盖从正常到严重故障的四级分类,有助于训练模型实现故障预测与诊断。所有数据均为合成生成,旨在模拟真实的发动机性能变化与典型故障场景,所包含的温度、转速、燃油效率、振动、扭矩及功率输出等关键传感指标,均为影响发动机故障判定的重要因素。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值