分享一个很轻的、纯JDBC ORM映射小框架,泛型化,SQL级别
首先这是一个超轻的纯JDBC 框架,说是ORM,但又不配,但又具有一点点ORM的特性。四不像,怎么称呼,各位看官自取。
笨人笨舌的,看看代码吧,也许您就更清楚:
首先定义一个通用Dao的借口,定义了有限的几个方法:
package com.xiaomin.dao;import java.util.List;/** * 利用泛型操作数据表 * * @author xiaomin * * @param <T> */public interface IBaseDao<T> {/** * 插入对象 * * @param sql * @param params */int add(String sql, Object... params);/** * 查找多个对象 * * @param sql * @param params * @return */List<T> query(String sql, Object... params);/** * 查找对象 * * @param sql * @param params * @return */T get(String sql, Object... params);/** * 执行更新的sql语句,插入,修改,删除 * * @param sql * @return */boolean update(String sql);}
?对应实现是重点:
package com.xiaomin.dao.impl;import java.lang.reflect.ParameterizedType;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.List;import org.apache.commons.configuration.PropertiesConfiguration;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanListHandler;import com.xiaomin.dao.IBaseDao;/** * 利用泛型操作数据表 * * @author xiaomin * * @param <T> */public class BaseDAOImpl<T> implements IBaseDao<T> {// 在构造函数中反射出泛型类对象private Class<T> tClass;@SuppressWarnings("unchecked")public BaseDAOImpl() {tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];}/** * 插入对象 * * @param sql * @param params */public int add(String sql, Object... params) {Connection conn = getConnection();QueryRunner qr = new QueryRunner();try {int inserts = qr.update(conn, sql, params);return inserts;} catch (SQLException e) {e.printStackTrace();return -1;} finally {DbUtils.closeQuietly(conn);}}/** * 查找多个对象 * * @param sql * @param params * @return */@SuppressWarnings( { "unchecked", "deprecation" })public List<T> query(String sql, Object... params) {List<T> beans = null;Connection conn = null;try {conn = getConnection();QueryRunner qRunner = new QueryRunner();beans = (List<T>) qRunner.query(conn, sql, params, new BeanListHandler(tClass));} catch (SQLException e) {e.printStackTrace();} finally {DbUtils.closeQuietly(conn);}return beans;}/** * 查找对象 * * @param sql * @param params * @return */@SuppressWarnings( { "unchecked", "deprecation" })public T get(String sql, Object... params) {T obj = null;Connection conn = null;try {conn = getConnection();QueryRunner qRunner = new QueryRunner();List<T> litT = (List<T>) qRunner.query(conn, sql, params, new BeanListHandler(tClass));if (litT != null && litT.size() > 0)obj = litT.get(0);} catch (SQLException e) {e.printStackTrace();} finally {DbUtils.closeQuietly(conn);}return obj;}/** * 执行更新的sql语句,插入,修改,删除 * * @param sql * @return */public boolean update(String sql) {Connection conn = null;boolean flag = false;try {conn = getConnection();QueryRunner qRunner = new QueryRunner();int i = qRunner.update(conn, sql);if (i > 0) {flag = true;}} catch (SQLException e) {e.printStackTrace();} finally {DbUtils.closeQuietly(conn);}return flag;}/** * 数据库连接 若生产环境下,建议使用数据连接池获取链接 * * @return */private static Connection getConnection() {Connection conn = null;PropertiesConfiguration propertyUtil = null;try {propertyUtil = new PropertiesConfiguration("/jdbc.properties");} catch (Exception e) {return null;}String driver = propertyUtil.getString("jdbc.driverClassName");String url = propertyUtil.getString("jdbc.url");DbUtils.loadDriver(driver);try {conn = DriverManager.getConnection(url, propertyUtil.getString("jdbc.username"), propertyUtil.getString("jdbc.password"));} catch (SQLException ex) {ex.printStackTrace();}return conn;}}
?诸位看到这里一定明白了,使用到了Apache Commons DbUtils,然后添加JDK 1.5的泛型支持,很浅显。
如何使用呢 ?
我们在数据库中定义了一个表格:
CREATE TABLE BaseEntity(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,url VARCHAR(100),site VARCHAR(50),pubDate TIMESTAMP(8),inDate TIMESTAMP(8));
?对应的实体则一定是:
package com.yourdomain;import java.io.Serializable;import java.util.Date;public class BaseEntity implements Serializable {private static final long serialVersionUID = 516103458363794423L;private Integer id;private String url;/** * 添加到数据库日期 */private Date inDate;/** * 来自网站简称 */private String site;/** * 原始站点发布日期 */private Date pubDate;public BaseEntity() {}public BaseEntity(String url, Date inDate, String site, Date pubDate) {this.url = url;this.inDate = inDate;this.site = site;this.pubDate = pubDate;}public BaseEntity(Integer id, String url, Date inDate, String site, Date pubDate) {this(url, inDate, site, pubDate);this.id = id;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public Date getInDate() {return inDate;}public void setInDate(Date inDate) {this.inDate = inDate;}public String getSite() {return site;}public void setSite(String site) {this.site = site;}public Date getPubDate() {return pubDate;}public void setPubDate(Date pubDate) {this.pubDate = pubDate;}}
?下面是对这个实体的操作:
package com.yourdomain.dao.impl;import java.util.List;import com.xiaomin.dao.impl.BaseDAOImpl;import com.yourdomain.BaseEntity;import com.yourdomain.dao.IDemoDao;public class DemoDaoImpl extends BaseDAOImpl<BaseEntity> implements IDemoDao {public List<BaseEntity> getAll() {String hql = "select * from BaseEntity";return this.query(hql);}public BaseEntity getBaseEntity(Integer entityId) {String sql = "select * from BaseEntity where id = ?";return this.get(sql, entityId);}public void save(BaseEntity videoEntity) {String sql = "INSERT INTO BaseEntity(url,site,pubDate,inDate) VALUES (?,?,?,?)";Object[] insertParams = { videoEntity.getUrl(), videoEntity.getSite(),videoEntity.getPubDate(), videoEntity.getInDate() };this.add(sql, insertParams);}public void save(List<BaseEntity> entityList) {for(BaseEntity entity : entityList){this.save(entity);}}}
?这样对 BaseEntity 的操作就这样完成了。
还有未能说清楚地方,请参见附件一个完整Demo。
?
附加说明:
1 . 需要 JDK 1.5 或更高版本;使用到泛型,可变参数;每一个实体对应ID个人认为使用不上,暂无泛型化
2 . 需要一个数据库,数据库连接参数在 src/jdbc.properties 中修改
3 . 创建数据库脚本在 document/database.sql 中寻找;测试请运行test.service.TestDemoDao
4 . 仅仅为了更简单使用JDBC,厌烦了Hibernate的臃肿
5 . 可在中小型项目中使用
6 . 仅仅封装了Dao层,请自行融入到现有项目中
7 . 数据库表格和实体名字一样,字段名称和实体属性名字一致
8 . 新的Dao操作类,仅仅需要集成com.xiaomin.dao.impl.BaseDAOImpl或者其它方式,请自行实践
9 . 又是一个贫瘠的域模型,很瘦!
?
在小型项目中是再简单不过了,只是分享,但不推荐您也这样做,除非您有驾驭能力,出了问题也知道在什么地方。
?
?
1 楼 xihuyu2000 2010-09-25 我在项目中用过,后来被Hibernate替换掉了,原因是传入的参数类型无法验证,直接拼SQL会造成代码难读,直接结果是在DAO层花费了过多的时间,不经济