分享一个很轻的、纯JDBC ORM照射小框架,泛型化,SQL级别
分享一个很轻的、纯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层花费了过多的时间,不经济