jdbc数据库操作的通用类 小弟写了一个数据库操作的通用类,不知道有用没有,在项目里一般情况下是使用框架比较多,还是其他的,有需要的话留下邮箱,交流交流,看看还有没有改进的地方 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 DbUtils这个开源项目已经提供了 DbUtils 用spring的数据库操作感觉比较爽的 好吧!package com.prj.tools;import java.io.File;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;public class DataBase { private static String db_driver = "";//数据库驱动 private static String db_url = "";//连接字符串 private static String db_userName = "";//用户名 private static String db_userPass = "";//用户密码 private static String db_state = "";//状态 private static String db_dataBaseName = "";//数据库名 private static Connection conn = null; private static PreparedStatement pst = null; private static CallableStatement cs= null; private static ResultSet res = null; private static Statement st = null; /** * 加载必要的数据库连接信息 */ private static void init(){ try { String url = Class.class.getClass().getResource("/").getPath(); //获取当前项目在本地的物理路径 url = url.substring(1); url = url.substring(0,url.lastIndexOf("/")-7); url = url.replace("/", "\\\\"); url = url.replace("%20", " "); //利用dom4j获取xml文件的信息 SAXReader reader = new SAXReader(); Document document = reader.read(new File(url + "DataBase.xml")); Element root = document.getRootElement();//xml文件的根目录 db_state = root.element("sqlserver").element("state").getText(); db_driver = root.element("sqlserver").element("driver").getText(); db_userName = root.element("sqlserver").element("userName").getText(); db_userPass = root.element("sqlserver").element("userPass").getText(); db_dataBaseName = root.element("sqlserver").element("dataBaseName").getText(); db_url = "jdbc:sqlserver://" + root.element("sqlserver").element("baseURL").getText() + ":1433;databasename=" + db_dataBaseName; if(db_state == "0" || "0".equals(db_state)){ db_state = root.element("mysql").element("state").getText(); db_driver = root.element("mysql").element("driver").getText(); db_userName = root.element("mysql").element("userName").getText(); db_userPass = root.element("mysql").element("userPass").getText(); db_dataBaseName = root.element("mysql").element("dataBaseName").getText(); db_url = "http://" + root.element("mysql").element("baseURL").getText() + ":1433;databasename=" + db_dataBaseName; } if(db_state == "0" || "0".equals(db_state)){ db_state = root.element("oracle").element("state").getText(); db_driver = root.element("oracle").element("driver").getText(); db_userName = root.element("oracle").element("userName").getText(); db_userPass = root.element("oracle").element("userPass").getText(); db_dataBaseName = root.element("oracle").element("dataBaseName").getText(); db_url = "http://" + root.element("oracle").element("baseURL").getText() + ":1433;databasename=" + db_dataBaseName; } } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 创建数据库连接 * @return */ public static Connection getConn(){ init(); try { Class.forName(db_driver); conn = java.sql.DriverManager.getConnection(db_url, db_userName, db_userPass); conn.setAutoCommit(false); //关闭自动提交功能,改为人工提交事务 } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } /** * 关闭数据库参数 */ public static void close(){ try { if(res != null){ res.close(); } if(pst != null){ pst.close(); } if(st != null){ st.close(); } if(cs != null){ cs.close(); } if(conn != null){ conn.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 执行sql语句的增删改 * @param sql * @param param * @return */ public static Integer executeSQL(String sql,String[] param) throws SQLException{ Integer result = 0; conn = null; pst = null; try { conn = getConn(); pst = conn.prepareStatement(sql); if(param != null){ for(int i = 0; i < param.length; i++){ pst.setString(i + 1, param[i]); } } result = pst.executeUpdate(); conn.commit();//提交事务 } catch (SQLException e) { // TODO Auto-generated catch block conn.rollback();//回滚事务 e.printStackTrace(); }finally{ close(); } return result; } /** * 批处理的增删改 * @param sql * @return */ public static Integer executeSQLBatch(String sql) throws SQLException{ Integer result = 1; try { conn = null; st = null; conn = getConn(); st = conn.createStatement(); st.addBatch(sql); int[] resultArray = st.executeBatch(); for(int i = 0; resultArray.length > 0 && i < resultArray.length;i++){ if(resultArray[i] <= 0){ result = 0; } } if(result > 0){ conn.commit(); } } catch (SQLException e) { // TODO Auto-generated catch block conn.rollback(); e.printStackTrace(); }finally{ close(); } return result; } /** * 执行存储过程的增删改 * @param sql * @param param * @return */ public static Integer executeSQLProc(String sql,String[] param) throws SQLException{ Integer result = 0; conn = null; cs = null; try { conn = getConn(); cs = conn.prepareCall(sql); if(param != null){ for(int i = 0; i < param.length; i++){ cs.setString(i + 1, param[i]); } } result = cs.executeUpdate(); conn.commit();//提交事务 } catch (SQLException e) { // TODO Auto-generated catch block conn.rollback();//回滚事务 e.printStackTrace(); }finally{ close(); } return result; } /** * 普通sql查询 * @param sql * @param param * @return */ public static ResultSet execute(String sql,String[] param){ try { conn = getConn(); pst = conn.prepareStatement(sql); if(param != null){ for(int i = 0; i < param.length; i++){ pst.setString(i + 1, param[i]); } } res = pst.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; } /** * 执行存储过程的查询 * @param sql * @param param * @return */ public static ResultSet executeProc(String sql,String[] param){ conn = null; cs = null; res = null; try { conn = getConn(); cs = conn.prepareCall(sql); if(param != null){ for(int i = 0; i < param.length; i++){ cs.setString(i + 1, param[i]); } } res = cs.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; }}xml<?xml version="1.0" encoding="UTF-8"?><database> <sqlserver> <driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver><!-- 数据库驱动 --> <userName>sa</userName><!-- 用户名 --> <userPass>sapassword</userPass><!-- 密码 --> <state>1</state> <!-- 状态,是否开启 --> <dataBaseName>test</dataBaseName><!-- 数据库名 --> <baseURL>localhost</baseURL><!-- 服务器地址 --> </sqlserver> <mysql> <driver>org.gjt.mm.mysql.Driver</driver><!-- 数据库驱动 --> <userName>root</userName><!-- 用户名 --> <userPass>root</userPass><!-- 密码 --> <state>0</state> <!-- 状态,是否开启 --> <dataBaseName>test</dataBaseName><!-- 数据库名 --> <baseURL>localhost</baseURL><!-- 服务器地址 --> </mysql> <oracle> <driver>oracle.jdbc.driver.OracleDriver</driver><!-- 数据库驱动 --> <userName>root</userName><!-- 用户名 --> <userPass>root</userPass><!-- 密码 --> <state>0</state> <!-- 状态,是否开启 --> <dataBaseName>test</dataBaseName><!-- 数据库名 --> <baseURL>localhost</baseURL><!-- 服务器地址 --> </oracle></database> 楼主你的close方法写的不咋滴,可以看看别人怎么写的假如rs关闭抛错了,本来还有关闭conn的保障,结果你这个conn,close就执行不到了 已经到了抛异常的阶段,也就不需要执行conn的close了吧,肯定是要在底层控制的么 no,其实stat,pstat都是可以不close,只close conn就会自动关闭stat,pstat所以你应该直接catch掉stat,pstat的异常,然后再关闭conn,conn的异常可抛可不抛,一般是这么做的 明白你的意思,我这个Close()方法主要是给这个类的基类调用的,我在基类里关闭,因为有一个ResultSet /** * 普通sql查询 * @param sql * @param param * @return */ public static ResultSet execute(String sql,String[] param){ try { conn = getConn(); pst = conn.prepareStatement(sql); if(param != null){ for(int i = 0; i < param.length; i++){ pst.setString(i + 1, param[i]); } } res = pst.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; } /** * 执行存储过程的查询 * @param sql * @param param * @return */ public static ResultSet executeProc(String sql,String[] param){ conn = null; cs = null; res = null; try { conn = getConn(); cs = conn.prepareCall(sql); if(param != null){ for(int i = 0; i < param.length; i++){ cs.setString(i + 1, param[i]); } } res = cs.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; }}这两个里面不关连接?关也不是不关也不是,我觉得不应该实现查询功能 这两个查询要在底层finally里Close()再把底层用到的ResultSet对象也关闭掉 有没有研究DAO组件的,可以兼容Hibernate、iBATIS,并且用JDBC实现了简单的ORM有可以交流下,QQ:584783469(非诚勿扰e) 自己写过一个山寨dbutil.....功能一样,就是处理器少一点,够自己用 我觉得写在property里面得了,简单的关系不必用xml配置 public static Connection getConn(){ init();每次获取连接都要重新解析配置文件? 写在static代码块就可以了多定义几个字段。 写在xml里面就是考虑到如果切换数据库的时候,写在类里面不是写死了么 package dao;import java.sql.*;import java.util.*;public class DbManager { public DbManager() { try { jbInit(); } catch (Exception ex) { ex.printStackTrace(); } } private Connection conn = null; private Statement stmt = null; private ResultSet rs = null; private void getStmt(String db) { try { //加载驱动 Class.forName("net.sourceforge.jtds.jdbc.Driver"); //创建连接 String url = "jdbc:jtds:sqlserver://localhost:1433/" + db; conn = DriverManager.getConnection(url,"sa","baolian"); //创建语句对象 stmt = conn.createStatement(); } catch (Exception ex) { System.out.println("创建语句对象失败"); } } //****************************************** //增删改方法 public int exeSql(String db, String sql) { int i = 0; try { System.out.println(sql); this.getStmt(db); i = stmt.executeUpdate(sql); stmt.close(); conn.close(); } catch (Exception ex) { System.out.println("执行SQL失败"); } return i; } //****************************************** //查询方法(返回值为结果集) public ResultSet getRs(String db, String sql) { try { this.getStmt(db); rs = stmt.executeQuery(sql); } catch (Exception ex) { System.out.println("查询失败"); } return rs; } //****************************************** //关闭方法 public void close() { try { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } if (conn != null) { conn.close(); } } catch (Exception ex) { System.out.println("关闭失败"); } } //****************************************** //查询方法(返回值为Vector) public Vector getRows(String db, String sql) { Vector rows = new Vector(); try { this.getStmt(db); rs = stmt.executeQuery(sql); while (rs.next()) { Vector row = new Vector(); for (int i = 1; i < rs.getMetaData().getColumnCount(); i++) { row.add(rs.getString(i)); } rows.add(row); } rs.close(); stmt.close(); conn.close(); } catch (Exception ex) { System.out.println("查询失败"); } return rows; } private void jbInit() throws Exception { }} package com.quanguowuliu.dao;import java.util.*;import org.hibernate.Criteria;import org.hibernate.HibernateException;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.criterion.DetachedCriteria;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import org.springframework.orm.hibernate3.SessionFactoryUtils;public class BaseDAO extends HibernateDaoSupport implements IBaseDAO{ /** * 向数据库添加一条对应于一个业务对象实例的记录 * * @param entity * 业务对象实例 * @throws DaoException * */ public boolean create(Object entity) { try { super.getHibernateTemplate().save(entity); return true; } catch (Exception e) { System.out.println("保存 " + entity.getClass().getName() + " 实例到数据库失败"+e); return false; } } public List findByPage(DetachedCriteria dc,int start,int end) { List listpage=this.getHibernateTemplate().findByCriteria(dc, start, end); return listpage; } public List ListDeptInfor(DetachedCriteria dc) throws HibernateException{ List lists= this.getHibernateTemplate().findByCriteria(dc); return lists; } /** * 获得一个session */ public Session openSession() { return SessionFactoryUtils.getSession(super.getHibernateTemplate().getSessionFactory(), false); } /** * 获得Query对象 */ public Query getQuery(String sql){ Session session = this.openSession(); Query query = session.createQuery(sql); return query; } /** * 获得Criteria对象 */ public Criteria getCriteria(Class clazz){ Session session=this.openSession(); Criteria criteria = session.createCriteria(clazz); return criteria; } /** * 向数据库更新一条对应于一个业务对象实例的记录 * * @param entity * 业务对象实例 * @throws DaoException * */ public boolean update(Object entity) { try { super.getHibernateTemplate().update(entity); return true; } catch (Exception e) { System.out.println("更新 " + entity.getClass().getName() + " 实例到数据库失败"+e); return false; } } /** * 从数据库删除一条对应于一个业务对象的记录 * * @param entity * 业务对象实例 * @throws DaoException * */ public boolean delete(Object entity) { try { super.getHibernateTemplate().delete(entity); return true; } catch (Exception e) { System.out.println("从数据库删除 " + entity.getClass().getName() + " 实例失败"+e); return false; } } /** * 从数据库删除所有对应于一个业务对象的记录 * @param clazz * 指定类型的业务对象 * @throws DaoException */ public boolean deleteAll(Class clazz) { try { List result = super.getHibernateTemplate().loadAll(clazz); super.getHibernateTemplate().deleteAll(result); return true; } catch (Exception e) { System.out.println("从数据库删除 " + clazz.getName() + " 的所有记录失败"+ e); return false; } } public boolean deleteAll(Collection entities) { try { super.getHibernateTemplate().deleteAll(entities); return true; } catch(Exception e) { return false; } } /** * 从数据库查询一个业务对象的所以记录 * @param clazz * 指定类型的业务对象 */ public List LoadAll(Class clazz){ List list=null; try{ list=super.getHibernateTemplate().loadAll(clazz); }catch(Exception e){ System.out.println("从数据库查询"+clazz.getName()+"失败"); } return list; } /** * 根据关键字从数据库加载指定类型的业务对象。 * * @param clazz * 业务对象的Class * @param keyName * 指定关键字对应的字段名称 * @param keyValue * 指定关键字的值 * @return <ul> * <li>当关键字唯一并存在该记录时,返回该记录对应的业务对象</li> * <li>当关键字不唯一,返回查询结果的第一条记录所对应的业务对象</li> * <li>当不存在该记录时,返回null</li> * </ul> * @throws DaoException * */ public Object loadByKey(Class clazz, String keyName, Object keyValue) { List result = super.getHibernateTemplate().find( "from " + clazz.getName() + " where " + keyName + " = ?", keyValue); if (result != null && result.size() > 0) { return result.get(0); } else { return null; } } /** * 根据主键查询唯一数据对象。 * * @param clazz * 业务对象的Class * @return 返回查询结果包含的业务对象 * @throws DaoException * */ public Object getByPk(Class clazz,Integer id){ Object obj = (Object)super.getHibernateTemplate().get(clazz,id); return obj; } public Object getByPk(Class clazz,Long id){ Object obj = (Object)super.getHibernateTemplate().get(clazz,id); return obj; } public Object getByPk(Class clazz,String id){ Object obj = (Object)super.getHibernateTemplate().get(clazz,id); return obj; } /** * 根据查询语句查询数据库并返回查询结果所包含的业务对象集合。 * * @param queryString * 指定查询语句 * @return 返回查询结果包含的业务对象集合 * @throws DaoException * */ public List find(String queryString) { List list =null; try { list= super.getHibernateTemplate().find(queryString); ; } catch (Exception e) { System.out.println("执行查询 " + queryString + " 失败"+e); } return list; } /** * 根据带一个参数的查询语句查询数据库并返回查询结果所包含的业务对象集合。 * * @param queryString * 指定查询语句 * @param param * 指定所带参数 * @return 返回查询结果包含的业务对象集合 * @throws DaoException * 牭±查询失败时抛??鲆斐?? */ public List find(String queryString, Object param) { List list= null; try { list = super.getHibernateTemplate().find(queryString, param); } catch (Exception e) { System.out.println("执行参数为 " + param + " 的查询 " + queryString + " 失败"+e); } return list; } /** * 根据带多个参数的查询语句查询数据库并返回查询结果所包含的业务对象集合。 * * @param queryString * 指定查询语句 * @param params * 指定参数数组 * @return 返回查询结果包含的业务对象集合 * @throws DaoException * */ public List find(String queryString, Object[] params) { List list= null; try { list= super.getHibernateTemplate().find(queryString, params); } catch (Exception e) { StringBuffer paramString = new StringBuffer(""); for (int i = 0; i < params.length; i++) { paramString.append(params[i]); paramString.append(" "); } System.out.println("执行参数为 " + paramString + "的查询 " + queryString + " 失败"+e); } return list; } } Hibernate用过,但是不知道支持不支持存储过程和视图,之前没有写过 xml文件不用每个数据库都写一次,写一个就行了 效率很难得到保证,close()方法有人已经提出来了;应该是潜逃try()catch()进行关闭public static void free(Connection conn, Statement stmt, ResultSet rs) { try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (stmt != null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } }}还有,也不支持dataSource获取连接和连接池的支持,没法用在实际的项目中。参数支持的也应该再强大一些,这是我以前写过的一个JDBC的封装,既然是共享,就贴出来了,欢迎板砖,共同探讨。以下是核心的几个类:/** * 整个JDBC操作的DAO接口。 * <p>提供对实体单个和批量的增删改查操作。 * * @author ZhiCheng Lu * * @version 1.0 2010-1-11 */public interface EntityDao { /** * {@link cn.myground.jdbc.dao.EntityDao EntityDao} 自带的JDBC操作的封装 */ MyDaoImplTemplate dao = new MyDaoImplTemplate(); /** * 保存一个对象。 * @param obj 需要保存的对象 * @return 返回保存后的这个对象 */ public Object save(Object obj); /** * 更新一个对象。 * @param obj 需要更新的对象 * @return 更新后的对象 */ public Object update(Object obj); /** * 删除一个对象。 * @param obj 需要删除的对象 * @return 数据库中受影响的记录数 */ public int delete(Object obj); /** * 根据ID值获取一个对象。 * @param id 该对象在数据库中的ID值 * @return 该ID值在数据库中对应的实体 */ public Object get(int id); /** * 根据给定条件查询一个对象。 * <p>参数的设置规则:为一个 <code>Map</code> 集合, * <code>Key</code> 为该对象的属性名, <code>Value</code> * 为该对象属性对应的值。 * @param map 参数集合 * @return 符合条件的对象 */ public Object get(Map<String, Object> map);} /** * 该类是对{@linkplain cn.myground.jdbc.dao.EntityDao EntityDao}接口的一个模板实现。 * <p>对{@linkplain cn.myground.jdbc.dao.EntityDao EntityDao} * 接口中的各种JDBC操作提供模板代码的实现。 * @author ZhiCheng Lu * * @version 1.0 2010-1-11 */public final class MyDaoImplTemplate { /** * 保存实体。 * 并返回保存该实体后由数据库返回的主键集合。 * @param sql SQL语句 * @param map 参数集 * @return 该实体的 <code>List(Object)</code> 主键集 */ public List<Object> save(String sql, Map<String, Object> map) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; List<Object> list = new ArrayList<Object>(); try { conn = JdbcUtils.getConnection(); pstmt = conn.prepareStatement(this.replaceSql(sql), Statement.RETURN_GENERATED_KEYS); // 替换SQL中的参数 sql = this.setParameterValue(sql, pstmt, map); // 执行操作 pstmt.executeUpdate(); rs = pstmt.getGeneratedKeys(); while(rs.next()){ list.add(rs.getObject("GENERATED_KEY")); } return list; } catch (SQLException e) { throw new DaoException(e.getMessage(), e); } finally { JdbcUtils.free(conn, pstmt, rs); } } /** * 更新实体。 * @param sql SQL语句 * @param map 参数集 * @return 数据库中受影响的记录数 */ public int update(String sql, Map<String, Object> map) { Connection conn = null; PreparedStatement pstmt = null; try { conn = JdbcUtils.getConnection(); pstmt = conn.prepareStatement(this.replaceSql(sql)); // 替换SQL中的参数 this.setParameterValue(sql, pstmt, map); // 执行操作 return pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); throw new DaoException(e.getMessage(), e); } finally { JdbcUtils.free(conn, pstmt, null); } } /** * 根据SQL语句、参数集和行映射器 获取一个实体。 * 若数据库中有多条满足条件的记录,则返回第一条。 * <p>该方法需要一个行映射器 <code>RowMapper</code>, * 用于实现从 <code>ResultSet</code> 结果集到实体的映射工作。 * <p>例如: * <blockquote><pre> * User user = (User)dao.get(sql, map, new RowMapper() { * * public Object mapRow(ResultSet rs) throws SQLException { * User user = new User(); * user.setId(rs.getInt("id")); * user.setName(rs.getString("name")); * user.setPassword(rs.getString("password")); * return user; * } * }); *</pre></blockquote> * * @param sql SQL语句 * @param map 参数集 * @param rowMapper 行映射器 * @return 符合条件的对象 * * @see RowMapper */ public Object get(String sql, Map<String, Object> map, RowMapper rowMapper) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Object obj = null; try { conn = JdbcUtils.getConnection(); pstmt = conn.prepareStatement(this.replaceSql(sql)); this.setParameterValue(sql, pstmt, map); rs = pstmt.executeQuery(); if (rs.next()) { obj = rowMapper.mapRow(rs); } } catch (SQLException e) { e.printStackTrace(); throw new DaoException(e.getMessage(), e); } finally { JdbcUtils.free(conn, pstmt, null); } return obj; } /** * 根据类、SQL语句和参数集 获取一个实体 * <p>若数据库中有多条满足条件的记录,则返回第一条。 * <p>该方法需要指定需要获取的实体的类型 <code>Class</code>, * 根据指定的类型,将根据SQL查询出的结果集自动填充到该实体中。 * <br>映射规则为SQL语句中所要查询内容的别名与该实体的属性名一致。 * * @param clazz 实体类型 * @param sql SQL语句 * @param map 参数集 * @return 符合条件的对象 */ public <T> T get(Class<T> clazz, String sql, Map<String, Object> map) { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; ResultSetMetaData rsmd = null; T obj = null; try { conn = JdbcUtils.getConnection(); pstmt = conn.prepareStatement(this.replaceSql(sql)); this.setParameterValue(sql, pstmt, map); rs = pstmt.executeQuery(); if (rs.next()) { rsmd = rs.getMetaData(); int count = rsmd.getColumnCount(); String[] colName = new String[count]; for (int i = 0; i < count; i++) colName[i] = rsmd.getColumnLabel(i + 1); obj = clazz.newInstance(); Method[] ms = clazz.getMethods(); for (Method m : ms) for (int i = 0; i < colName.length; i++) if (m.getName().equalsIgnoreCase("set" + colName[i])) m.invoke(obj, rs.getObject(colName[i])); } return obj; } catch (Exception e) { throw new DaoException(e.getMessage(), e); } finally { JdbcUtils.free(conn, pstmt, null); } } /** * 删除实体 * @param sql SQL语句 * @param map 参数集 * @return 数据库中受影响的记录数 */ public int detele(String sql, Map<String, Object> map) { return this.update(sql, map); } /** * 根据SQL语句、参数集和行映射器 获取一个实体 * <p>若数据库中有多条满足条件的记录,则返回第一条。 * <p>该方法需要一个行映射器 <code>RowMapper</code>, * 用于实现从 <code>ResultSet</code> 结果集到实体的映射工作。 * <p>例如: * <blockquote><pre> * User user = (User)dao.get(sql, map, new RowMapper() { * * public Object mapRow(ResultSet rs) throws SQLException { * User user = new User(); * user.setId(rs.getInt("id")); * user.setName(rs.getString("name")); * user.setPassword(rs.getString("password")); * return user; * } * }); *</pre></blockquote> * * @param sql SQL语句 * @param map 参数集 * @param rowMapper 行映射器 * @return 符合条件的对象 * * @see RowMapper */ public Object query(String sql, Map<String, Object> map, RowMapper rowMapper) { return this.get(sql, map, rowMapper); } /** * 根据类、SQL语句和参数集 获取一个实体 * <p>若数据库中有多条满足条件的记录,则返回第一条。 * <p>该方法需要指定需要获取的实体的类型 <code>Class</code>, * 根据指定的类型,将根据SQL查询出的结果集自动填充到该实体中。 * <br>映射规则为SQL语句中所要查询内容的别名与该实体的属性名一致。 * * @param clazz 实体类型 * @param sql SQL语句 * @param map 参数集 * @return 符合条件的对象 */ public <T> T query(Class<T> clazz, String sql, Map<String, Object> map) { return this.get(clazz, sql, map); } public <T> List<T> saveAll(String sql, List<T> list) { Connection conn = null; PreparedStatement pstmt = null; try { conn = JdbcUtils.getConnection(); pstmt = conn.prepareStatement(sql); } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtils.free(conn, pstmt, null); } return null; } public <T> void deleteAll(List<T> list) { } public <T> void updateAll(List<T> list) { } public <T> void getAll(List<T> list) { } /** * 将Map<String, Object>中的参数添加到SQL语句中 * * @param sql * SQL语句 * @param pstmt * 需要执行的 <code>PreparedStatement</code> * @param map * 参数集合 * @throws SQLException * 当发生数据库操作异常时 */ private String setParameterValue(String sql, PreparedStatement pstmt, Map<String, Object> map) throws SQLException { int count = this.parameterCount(sql); for (int i = 1; i <= count; i++) { String pName = this.parameterName(i, sql); boolean like = sql.substring(sql.indexOf(":" + pName) - 5, sql.indexOf(":" + pName)).equals("like "); sql = sql.replace((":" + pName), ":?"); try { Object o = map.get(pName); if (o != null) if (like) pstmt.setObject(i, "%" + map.get(pName) + "%"); else pstmt.setObject(i, map.get(pName)); else throw new ParameterException(pName + " 没有被设置!"); } catch (NullPointerException e) { e.printStackTrace(); throw new ParameterException(pName + " 没有被设置!"); } } sql = sql.replaceAll(":", ""); return sql; } /** * 替换SQL中的参数为一个正确的SQL。 * <p> * 不改变原有SQL,返回一个新的替换后的SQL。 * * @param sql * 需要替换的SQL * @return 替换后的SQL */ private String replaceSql(String sql) { String temp = sql; int count = this.parameterCount(temp); for (int i = 1; i <= count; i++) { String pName = this.parameterName(i, temp); temp = temp.replace((":" + pName), ":?"); } temp = temp.replaceAll(":", ""); return temp; } /** * 返回SQL语句中参数的个数 * * @param sql * @return */ private int parameterCount(String sql) { int count = 0; while (sql.indexOf(":") > 0) { sql = sql.replaceFirst(":", ""); count++; } return count; } /** * 返回指定位置的参数名称 * * @param index * 指定第几个参数 * @param sql * 需要的SQL语句 * @return 指定位置的参数名称 */ private String parameterName(int index, String sql) { int count = 0; if (index == 1) count = sql.indexOf(":"); else { for (int i = 1; i < index; i++) { sql = sql.replaceFirst(":", ""); count = sql.indexOf(":"); } } String s = sql.substring(count + 1, sql.length()); char[] sqls = s.toCharArray(); StringBuffer temp = new StringBuffer(); Pattern p = Pattern.compile("[a-zA-Z]{1}"); for (int i = 0; i < sqls.length; i++) { String c = new String(sqls, i, 1); Matcher m = p.matcher(c); if (m.matches()) temp.append(c); else break; } return temp.toString(); } public static void main(String[] args) { MyDaoImplTemplate mdt = new MyDaoImplTemplate(); String sql = "select * from user where name like :name"; Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "zhangsan"); String s = ""; try { s = mdt.setParameterValue(sql, null, map); } catch (SQLException e) { e.printStackTrace(); } System.out.println(s); }} 你这个也太牛了吧!object!怎么增删改查呀!我以前想写一个这个样子的,但是没有成功! /** * 该接口为行映射器。 * * <P>该接口中只有一个方法 <code>mapRow()</code>。 * 实现该方法,用于完成从 <code>ResultSet</code> 结果集到 * 实体的映射。 * * @author ZhiCheng Lu * * @version 1.0 2010-1-11 */public interface RowMapper { /**行映射器。 * <p>实现该方法,用于完成从 <code>ResultSet</code> 结果集到 * 实体的映射。 * @param rs <code>ResultSet</code> 结果集 * @return 映射后的实体 * @throws SQLException 若发生数据库错误 */ public Object mapRow(ResultSet rs) throws SQLException;}SQL语句中的参数支持 :key 进行占位,然后通过Map<String, Object>进行赋值。具体的映射规则,如果bean的字段名跟数据库中的字段名都对应的话,可以使用默认实现,如果不一致可以自行实现RowMapper来完成映射,类似于spring的JDBC操作。其实就是个spring的JDBC操作简易版。默认实现不能够完成需求的话,也可以实现EntityDao,自行实现。EntityDao持有一个MyDaoImplTemplate引用,所有的常规JDBC操作在里面都有封装,直接调用即可。 Object的你可以遵循最简单的一个映射规则,就是bean的字段名跟数据库的字段名相同,或者实现自己的EntityDao,然后在映射的时候实现对应bean的RowMapper即可。因为我没做太多工作,如果有功夫,也可以自己做一个映射层,用自己的XML配置文件指定实体Bean的映射工作;或者用Annotation指定也行,自己再多写点类进行映射工作。 后来又增加了对泛型的支持,不过没在EntityDao接口中体现出来,但在MyDaoImplTemplate中已经能够支持了,你可以把EntityDao的接口改一下,支持泛型,这样用起来更顺手。O(∩_∩)O~~ 字符串转码,急人 如何将一串数字转换为日期 邮件服务器 ApacheJames的问题 lomboz-all-in-one-R-3.3在下面Window-->Preference下不能看到Lomboz IIS和resin的问题 删除按钮判断框问题 hibernate错误的原因 springMVC整合hibernate配置出错 IIS+JSP怎么配啊,我照着网上的N多的文章都试了还是不行 struts2校验不好使 两个关于XML的选择题,求解答 给大家分享个过滤IP的Filter
package com.prj.tools;import java.io.File;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;public class DataBase {
private static String db_driver = "";//数据库驱动
private static String db_url = "";//连接字符串
private static String db_userName = "";//用户名
private static String db_userPass = "";//用户密码
private static String db_state = "";//状态
private static String db_dataBaseName = "";//数据库名
private static Connection conn = null;
private static PreparedStatement pst = null;
private static CallableStatement cs= null;
private static ResultSet res = null;
private static Statement st = null;
/**
* 加载必要的数据库连接信息
*/
private static void init(){
try {
String url = Class.class.getClass().getResource("/").getPath(); //获取当前项目在本地的物理路径
url = url.substring(1);
url = url.substring(0,url.lastIndexOf("/")-7);
url = url.replace("/", "\\\\");
url = url.replace("%20", " ");
//利用dom4j获取xml文件的信息
SAXReader reader = new SAXReader();
Document document = reader.read(new File(url + "DataBase.xml"));
Element root = document.getRootElement();//xml文件的根目录
db_state = root.element("sqlserver").element("state").getText();
db_driver = root.element("sqlserver").element("driver").getText();
db_userName = root.element("sqlserver").element("userName").getText();
db_userPass = root.element("sqlserver").element("userPass").getText();
db_dataBaseName = root.element("sqlserver").element("dataBaseName").getText();
db_url = "jdbc:sqlserver://" + root.element("sqlserver").element("baseURL").getText() + ":1433;databasename="
+ db_dataBaseName;
if(db_state == "0" || "0".equals(db_state)){
db_state = root.element("mysql").element("state").getText();
db_driver = root.element("mysql").element("driver").getText();
db_userName = root.element("mysql").element("userName").getText();
db_userPass = root.element("mysql").element("userPass").getText();
db_dataBaseName = root.element("mysql").element("dataBaseName").getText();
db_url = "http://" + root.element("mysql").element("baseURL").getText() + ":1433;databasename="
+ db_dataBaseName;
}
if(db_state == "0" || "0".equals(db_state)){
db_state = root.element("oracle").element("state").getText();
db_driver = root.element("oracle").element("driver").getText();
db_userName = root.element("oracle").element("userName").getText();
db_userPass = root.element("oracle").element("userPass").getText();
db_dataBaseName = root.element("oracle").element("dataBaseName").getText();
db_url = "http://" + root.element("oracle").element("baseURL").getText() + ":1433;databasename="
+ db_dataBaseName;
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 创建数据库连接
* @return
*/
public static Connection getConn(){
init();
try {
Class.forName(db_driver);
conn = java.sql.DriverManager.getConnection(db_url, db_userName, db_userPass);
conn.setAutoCommit(false); //关闭自动提交功能,改为人工提交事务
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
/**
* 关闭数据库参数
*/
public static void close(){
try {
if(res != null){
res.close();
}
if(pst != null){
pst.close();
}
if(st != null){
st.close();
}
if(cs != null){
cs.close();
}
if(conn != null){
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 执行sql语句的增删改
* @param sql
* @param param
* @return
*/
public static Integer executeSQL(String sql,String[] param) throws SQLException{
Integer result = 0;
conn = null;
pst = null;
try {
conn = getConn();
pst = conn.prepareStatement(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
pst.setString(i + 1, param[i]);
}
}
result = pst.executeUpdate();
conn.commit();//提交事务
} catch (SQLException e) {
// TODO Auto-generated catch block
conn.rollback();//回滚事务
e.printStackTrace();
}finally{
close();
}
return result;
}
/**
* 批处理的增删改
* @param sql
* @return
*/
public static Integer executeSQLBatch(String sql) throws SQLException{
Integer result = 1;
try {
conn = null;
st = null;
conn = getConn();
st = conn.createStatement();
st.addBatch(sql);
int[] resultArray = st.executeBatch();
for(int i = 0; resultArray.length > 0 && i < resultArray.length;i++){
if(resultArray[i] <= 0){
result = 0;
}
}
if(result > 0){
conn.commit();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
conn.rollback();
e.printStackTrace();
}finally{
close();
}
return result;
}
/**
* 执行存储过程的增删改
* @param sql
* @param param
* @return
*/
public static Integer executeSQLProc(String sql,String[] param) throws SQLException{
Integer result = 0;
conn = null;
cs = null;
try {
conn = getConn();
cs = conn.prepareCall(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
cs.setString(i + 1, param[i]);
}
}
result = cs.executeUpdate();
conn.commit();//提交事务
} catch (SQLException e) {
// TODO Auto-generated catch block
conn.rollback();//回滚事务
e.printStackTrace();
}finally{
close();
}
return result;
}
/**
* 普通sql查询
* @param sql
* @param param
* @return
*/
public static ResultSet execute(String sql,String[] param){
try {
conn = getConn();
pst = conn.prepareStatement(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
pst.setString(i + 1, param[i]);
}
}
res = pst.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
/**
* 执行存储过程的查询
* @param sql
* @param param
* @return
*/
public static ResultSet executeProc(String sql,String[] param){
conn = null;
cs = null;
res = null;
try {
conn = getConn();
cs = conn.prepareCall(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
cs.setString(i + 1, param[i]);
}
}
res = cs.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
}xml<?xml version="1.0" encoding="UTF-8"?>
<database>
<sqlserver>
<driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver><!-- 数据库驱动 -->
<userName>sa</userName><!-- 用户名 -->
<userPass>sapassword</userPass><!-- 密码 -->
<state>1</state> <!-- 状态,是否开启 -->
<dataBaseName>test</dataBaseName><!-- 数据库名 -->
<baseURL>localhost</baseURL><!-- 服务器地址 -->
</sqlserver>
<mysql>
<driver>org.gjt.mm.mysql.Driver</driver><!-- 数据库驱动 -->
<userName>root</userName><!-- 用户名 -->
<userPass>root</userPass><!-- 密码 -->
<state>0</state> <!-- 状态,是否开启 -->
<dataBaseName>test</dataBaseName><!-- 数据库名 -->
<baseURL>localhost</baseURL><!-- 服务器地址 -->
</mysql>
<oracle>
<driver>oracle.jdbc.driver.OracleDriver</driver><!-- 数据库驱动 -->
<userName>root</userName><!-- 用户名 -->
<userPass>root</userPass><!-- 密码 -->
<state>0</state> <!-- 状态,是否开启 -->
<dataBaseName>test</dataBaseName><!-- 数据库名 -->
<baseURL>localhost</baseURL><!-- 服务器地址 -->
</oracle>
</database>
假如rs关闭抛错了,本来还有关闭conn的保障,结果你这个conn,close就执行不到了
明白你的意思,我这个Close()方法主要是给这个类的基类调用的,我在基类里关闭,因为有一个ResultSet
* 普通sql查询
* @param sql
* @param param
* @return
*/
public static ResultSet execute(String sql,String[] param){
try {
conn = getConn();
pst = conn.prepareStatement(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
pst.setString(i + 1, param[i]);
}
}
res = pst.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
/**
* 执行存储过程的查询
* @param sql
* @param param
* @return
*/
public static ResultSet executeProc(String sql,String[] param){
conn = null;
cs = null;
res = null;
try {
conn = getConn();
cs = conn.prepareCall(sql);
if(param != null){
for(int i = 0; i < param.length; i++){
cs.setString(i + 1, param[i]);
}
}
res = cs.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
}
这两个里面不关连接?关也不是不关也不是,我觉得不应该实现查询功能
init();
每次获取连接都要重新解析配置文件?
import java.util.*;public class DbManager {
public DbManager() {
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
} private Connection conn = null;
private Statement stmt = null;
private ResultSet rs = null;
private void getStmt(String db) {
try {
//加载驱动
Class.forName("net.sourceforge.jtds.jdbc.Driver");
//创建连接
String url = "jdbc:jtds:sqlserver://localhost:1433/" +
db;
conn = DriverManager.getConnection(url,"sa","baolian");
//创建语句对象
stmt = conn.createStatement();
} catch (Exception ex) {
System.out.println("创建语句对象失败");
}
} //******************************************
//增删改方法
public int exeSql(String db, String sql) {
int i = 0;
try {
System.out.println(sql);
this.getStmt(db);
i = stmt.executeUpdate(sql);
stmt.close();
conn.close();
} catch (Exception ex) {
System.out.println("执行SQL失败");
}
return i;
} //******************************************
//查询方法(返回值为结果集)
public ResultSet getRs(String db, String sql) {
try {
this.getStmt(db);
rs = stmt.executeQuery(sql);
} catch (Exception ex) {
System.out.println("查询失败");
}
return rs;
} //******************************************
//关闭方法
public void close() {
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception ex) {
System.out.println("关闭失败");
}
} //******************************************
//查询方法(返回值为Vector)
public Vector getRows(String db, String sql) {
Vector rows = new Vector();
try {
this.getStmt(db);
rs = stmt.executeQuery(sql);
while (rs.next()) {
Vector row = new Vector();
for (int i = 1; i < rs.getMetaData().getColumnCount(); i++) {
row.add(rs.getString(i));
}
rows.add(row);
}
rs.close();
stmt.close();
conn.close();
} catch (Exception ex) {
System.out.println("查询失败");
}
return rows;
} private void jbInit() throws Exception {
}
}
import java.util.*;import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
public class BaseDAO extends HibernateDaoSupport implements IBaseDAO{
/**
* 向数据库添加一条对应于一个业务对象实例的记录
*
* @param entity
* 业务对象实例
* @throws DaoException
*
*/
public boolean create(Object entity) {
try {
super.getHibernateTemplate().save(entity);
return true;
} catch (Exception e) {
System.out.println("保存 " + entity.getClass().getName() + " 实例到数据库失败"+e);
return false;
}
}
public List findByPage(DetachedCriteria dc,int start,int end)
{
List listpage=this.getHibernateTemplate().findByCriteria(dc, start, end);
return listpage;
}
public List ListDeptInfor(DetachedCriteria dc) throws HibernateException{
List lists= this.getHibernateTemplate().findByCriteria(dc);
return lists;
}
/**
* 获得一个session
*/
public Session openSession() {
return SessionFactoryUtils.getSession(super.getHibernateTemplate().getSessionFactory(), false);
} /**
* 获得Query对象
*/
public Query getQuery(String sql){
Session session = this.openSession();
Query query = session.createQuery(sql);
return query;
}
/**
* 获得Criteria对象
*/
public Criteria getCriteria(Class clazz){
Session session=this.openSession();
Criteria criteria = session.createCriteria(clazz);
return criteria;
} /**
* 向数据库更新一条对应于一个业务对象实例的记录
*
* @param entity
* 业务对象实例
* @throws DaoException
*
*/
public boolean update(Object entity) {
try {
super.getHibernateTemplate().update(entity);
return true;
} catch (Exception e) {
System.out.println("更新 " + entity.getClass().getName() + " 实例到数据库失败"+e);
return false;
}
} /**
* 从数据库删除一条对应于一个业务对象的记录
*
* @param entity
* 业务对象实例
* @throws DaoException
*
*/
public boolean delete(Object entity) {
try {
super.getHibernateTemplate().delete(entity);
return true;
} catch (Exception e) {
System.out.println("从数据库删除 " + entity.getClass().getName() + " 实例失败"+e);
return false;
}
}
/**
* 从数据库删除所有对应于一个业务对象的记录
* @param clazz
* 指定类型的业务对象
* @throws DaoException
*/
public boolean deleteAll(Class clazz) {
try {
List result = super.getHibernateTemplate().loadAll(clazz);
super.getHibernateTemplate().deleteAll(result);
return true;
} catch (Exception e) {
System.out.println("从数据库删除 " + clazz.getName() + " 的所有记录失败"+ e);
return false;
}
} public boolean deleteAll(Collection entities) {
try {
super.getHibernateTemplate().deleteAll(entities);
return true;
} catch(Exception e) {
return false;
}
}
/**
* 从数据库查询一个业务对象的所以记录
* @param clazz
* 指定类型的业务对象
*/
public List LoadAll(Class clazz){
List list=null;
try{
list=super.getHibernateTemplate().loadAll(clazz);
}catch(Exception e){
System.out.println("从数据库查询"+clazz.getName()+"失败");
}
return list;
}
/**
* 根据关键字从数据库加载指定类型的业务对象。
*
* @param clazz
* 业务对象的Class
* @param keyName
* 指定关键字对应的字段名称
* @param keyValue
* 指定关键字的值
* @return <ul>
* <li>当关键字唯一并存在该记录时,返回该记录对应的业务对象</li>
* <li>当关键字不唯一,返回查询结果的第一条记录所对应的业务对象</li>
* <li>当不存在该记录时,返回null</li>
* </ul>
* @throws DaoException
*
*/
public Object loadByKey(Class clazz, String keyName, Object keyValue)
{
List result = super.getHibernateTemplate().find(
"from " + clazz.getName() + " where " + keyName + " = ?",
keyValue);
if (result != null && result.size() > 0) {
return result.get(0);
} else {
return null;
}
}
/**
* 根据主键查询唯一数据对象。
*
* @param clazz
* 业务对象的Class
* @return 返回查询结果包含的业务对象
* @throws DaoException
*
*/
public Object getByPk(Class clazz,Integer id){
Object obj = (Object)super.getHibernateTemplate().get(clazz,id);
return obj;
}
public Object getByPk(Class clazz,Long id){
Object obj = (Object)super.getHibernateTemplate().get(clazz,id);
return obj;
}
public Object getByPk(Class clazz,String id){
Object obj = (Object)super.getHibernateTemplate().get(clazz,id);
return obj;
}
/**
* 根据查询语句查询数据库并返回查询结果所包含的业务对象集合。
*
* @param queryString
* 指定查询语句
* @return 返回查询结果包含的业务对象集合
* @throws DaoException
*
*/
public List find(String queryString) {
List list =null;
try {
list= super.getHibernateTemplate().find(queryString); ;
} catch (Exception e) {
System.out.println("执行查询 " + queryString + " 失败"+e);
}
return list;
}
/**
* 根据带一个参数的查询语句查询数据库并返回查询结果所包含的业务对象集合。
*
* @param queryString
* 指定查询语句
* @param param
* 指定所带参数
* @return 返回查询结果包含的业务对象集合
* @throws DaoException
* 牭±查询失败时抛??鲆斐??
*/
public List find(String queryString, Object param) {
List list= null;
try {
list = super.getHibernateTemplate().find(queryString, param);
} catch (Exception e) {
System.out.println("执行参数为 " + param + " 的查询 " + queryString + " 失败"+e);
}
return list;
}
/**
* 根据带多个参数的查询语句查询数据库并返回查询结果所包含的业务对象集合。
*
* @param queryString
* 指定查询语句
* @param params
* 指定参数数组
* @return 返回查询结果包含的业务对象集合
* @throws DaoException
*
*/
public List find(String queryString, Object[] params) {
List list= null;
try {
list= super.getHibernateTemplate().find(queryString, params);
} catch (Exception e) {
StringBuffer paramString = new StringBuffer("");
for (int i = 0; i < params.length; i++) {
paramString.append(params[i]);
paramString.append(" ");
}
System.out.println("执行参数为 " + paramString + "的查询 " + queryString + " 失败"+e);
}
return list;
} }
public static void free(Connection conn, Statement stmt, ResultSet rs) {
try {
if (rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (stmt != null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null)
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
还有,也不支持dataSource获取连接和连接池的支持,没法用在实际的项目中。
参数支持的也应该再强大一些,这是我以前写过的一个JDBC的封装,既然是共享,就贴出来了,欢迎板砖,共同探讨。
以下是核心的几个类:/**
* 整个JDBC操作的DAO接口。
* <p>提供对实体单个和批量的增删改查操作。
*
* @author ZhiCheng Lu
*
* @version 1.0 2010-1-11
*/
public interface EntityDao { /**
* {@link cn.myground.jdbc.dao.EntityDao EntityDao} 自带的JDBC操作的封装
*/
MyDaoImplTemplate dao = new MyDaoImplTemplate(); /**
* 保存一个对象。
* @param obj 需要保存的对象
* @return 返回保存后的这个对象
*/
public Object save(Object obj); /**
* 更新一个对象。
* @param obj 需要更新的对象
* @return 更新后的对象
*/
public Object update(Object obj); /**
* 删除一个对象。
* @param obj 需要删除的对象
* @return 数据库中受影响的记录数
*/
public int delete(Object obj); /**
* 根据ID值获取一个对象。
* @param id 该对象在数据库中的ID值
* @return 该ID值在数据库中对应的实体
*/
public Object get(int id); /**
* 根据给定条件查询一个对象。
* <p>参数的设置规则:为一个 <code>Map</code> 集合,
* <code>Key</code> 为该对象的属性名, <code>Value</code>
* 为该对象属性对应的值。
* @param map 参数集合
* @return 符合条件的对象
*/
public Object get(Map<String, Object> map);}
/**
* 该类是对{@linkplain cn.myground.jdbc.dao.EntityDao EntityDao}接口的一个模板实现。
* <p>对{@linkplain cn.myground.jdbc.dao.EntityDao EntityDao}
* 接口中的各种JDBC操作提供模板代码的实现。
* @author ZhiCheng Lu
*
* @version 1.0 2010-1-11
*/
public final class MyDaoImplTemplate { /**
* 保存实体。
* 并返回保存该实体后由数据库返回的主键集合。
* @param sql SQL语句
* @param map 参数集
* @return 该实体的 <code>List(Object)</code> 主键集
*/
public List<Object> save(String sql, Map<String, Object> map) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Object> list = new ArrayList<Object>();
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(this.replaceSql(sql),
Statement.RETURN_GENERATED_KEYS);
// 替换SQL中的参数
sql = this.setParameterValue(sql, pstmt, map);
// 执行操作
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
while(rs.next()){
list.add(rs.getObject("GENERATED_KEY"));
}
return list;
} catch (SQLException e) {
throw new DaoException(e.getMessage(), e);
} finally {
JdbcUtils.free(conn, pstmt, rs);
}
} /**
* 更新实体。
* @param sql SQL语句
* @param map 参数集
* @return 数据库中受影响的记录数
*/
public int update(String sql, Map<String, Object> map) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(this.replaceSql(sql));
// 替换SQL中的参数
this.setParameterValue(sql, pstmt, map);
// 执行操作
return pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException(e.getMessage(), e);
} finally {
JdbcUtils.free(conn, pstmt, null);
}
} /**
* 根据SQL语句、参数集和行映射器 获取一个实体。
* 若数据库中有多条满足条件的记录,则返回第一条。
* <p>该方法需要一个行映射器 <code>RowMapper</code>,
* 用于实现从 <code>ResultSet</code> 结果集到实体的映射工作。
* <p>例如:
* <blockquote><pre>
* User user = (User)dao.get(sql, map, new RowMapper() {
*
* public Object mapRow(ResultSet rs) throws SQLException {
* User user = new User();
* user.setId(rs.getInt("id"));
* user.setName(rs.getString("name"));
* user.setPassword(rs.getString("password"));
* return user;
* }
* });
*</pre></blockquote>
*
* @param sql SQL语句
* @param map 参数集
* @param rowMapper 行映射器
* @return 符合条件的对象
*
* @see RowMapper
*/
public Object get(String sql, Map<String, Object> map, RowMapper rowMapper) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Object obj = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(this.replaceSql(sql));
this.setParameterValue(sql, pstmt, map);
rs = pstmt.executeQuery();
if (rs.next()) {
obj = rowMapper.mapRow(rs);
}
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException(e.getMessage(), e);
} finally {
JdbcUtils.free(conn, pstmt, null);
}
return obj;
} /**
* 根据类、SQL语句和参数集 获取一个实体
* <p>若数据库中有多条满足条件的记录,则返回第一条。
* <p>该方法需要指定需要获取的实体的类型 <code>Class</code>,
* 根据指定的类型,将根据SQL查询出的结果集自动填充到该实体中。
* <br>映射规则为SQL语句中所要查询内容的别名与该实体的属性名一致。
*
* @param clazz 实体类型
* @param sql SQL语句
* @param map 参数集
* @return 符合条件的对象
*/
public <T> T get(Class<T> clazz, String sql, Map<String, Object> map) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ResultSetMetaData rsmd = null;
T obj = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(this.replaceSql(sql));
this.setParameterValue(sql, pstmt, map);
rs = pstmt.executeQuery(); if (rs.next()) {
rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
String[] colName = new String[count];
for (int i = 0; i < count; i++)
colName[i] = rsmd.getColumnLabel(i + 1);
obj = clazz.newInstance();
Method[] ms = clazz.getMethods();
for (Method m : ms)
for (int i = 0; i < colName.length; i++)
if (m.getName().equalsIgnoreCase("set" + colName[i]))
m.invoke(obj, rs.getObject(colName[i]));
}
return obj;
} catch (Exception e) {
throw new DaoException(e.getMessage(), e);
} finally {
JdbcUtils.free(conn, pstmt, null);
}
} /**
* 删除实体
* @param sql SQL语句
* @param map 参数集
* @return 数据库中受影响的记录数
*/
public int detele(String sql, Map<String, Object> map) {
return this.update(sql, map);
} /**
* 根据SQL语句、参数集和行映射器 获取一个实体
* <p>若数据库中有多条满足条件的记录,则返回第一条。
* <p>该方法需要一个行映射器 <code>RowMapper</code>,
* 用于实现从 <code>ResultSet</code> 结果集到实体的映射工作。
* <p>例如:
* <blockquote><pre>
* User user = (User)dao.get(sql, map, new RowMapper() {
*
* public Object mapRow(ResultSet rs) throws SQLException {
* User user = new User();
* user.setId(rs.getInt("id"));
* user.setName(rs.getString("name"));
* user.setPassword(rs.getString("password"));
* return user;
* }
* });
*</pre></blockquote>
*
* @param sql SQL语句
* @param map 参数集
* @param rowMapper 行映射器
* @return 符合条件的对象
*
* @see RowMapper
*/
public Object query(String sql, Map<String, Object> map, RowMapper rowMapper) {
return this.get(sql, map, rowMapper);
}
/**
* 根据类、SQL语句和参数集 获取一个实体
* <p>若数据库中有多条满足条件的记录,则返回第一条。
* <p>该方法需要指定需要获取的实体的类型 <code>Class</code>,
* 根据指定的类型,将根据SQL查询出的结果集自动填充到该实体中。
* <br>映射规则为SQL语句中所要查询内容的别名与该实体的属性名一致。
*
* @param clazz 实体类型
* @param sql SQL语句
* @param map 参数集
* @return 符合条件的对象
*/
public <T> T query(Class<T> clazz, String sql, Map<String, Object> map) {
return this.get(clazz, sql, map);
} public <T> List<T> saveAll(String sql, List<T> list) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.free(conn, pstmt, null);
}
return null;
} public <T> void deleteAll(List<T> list) { } public <T> void updateAll(List<T> list) { } public <T> void getAll(List<T> list) { } /**
* 将Map<String, Object>中的参数添加到SQL语句中
*
* @param sql
* SQL语句
* @param pstmt
* 需要执行的 <code>PreparedStatement</code>
* @param map
* 参数集合
* @throws SQLException
* 当发生数据库操作异常时
*/
private String setParameterValue(String sql, PreparedStatement pstmt,
Map<String, Object> map) throws SQLException {
int count = this.parameterCount(sql);
for (int i = 1; i <= count; i++) {
String pName = this.parameterName(i, sql);
boolean like = sql.substring(sql.indexOf(":" + pName) - 5,
sql.indexOf(":" + pName)).equals("like ");
sql = sql.replace((":" + pName), ":?");
try {
Object o = map.get(pName);
if (o != null)
if (like)
pstmt.setObject(i, "%" + map.get(pName) + "%");
else
pstmt.setObject(i, map.get(pName));
else
throw new ParameterException(pName + " 没有被设置!");
} catch (NullPointerException e) {
e.printStackTrace();
throw new ParameterException(pName + " 没有被设置!");
}
}
sql = sql.replaceAll(":", "");
return sql;
} /**
* 替换SQL中的参数为一个正确的SQL。
* <p>
* 不改变原有SQL,返回一个新的替换后的SQL。
*
* @param sql
* 需要替换的SQL
* @return 替换后的SQL
*/
private String replaceSql(String sql) {
String temp = sql;
int count = this.parameterCount(temp);
for (int i = 1; i <= count; i++) {
String pName = this.parameterName(i, temp);
temp = temp.replace((":" + pName), ":?");
}
temp = temp.replaceAll(":", "");
return temp;
} /**
* 返回SQL语句中参数的个数
*
* @param sql
* @return
*/
private int parameterCount(String sql) {
int count = 0;
while (sql.indexOf(":") > 0) {
sql = sql.replaceFirst(":", "");
count++;
}
return count;
} /**
* 返回指定位置的参数名称
*
* @param index
* 指定第几个参数
* @param sql
* 需要的SQL语句
* @return 指定位置的参数名称
*/
private String parameterName(int index, String sql) {
int count = 0;
if (index == 1)
count = sql.indexOf(":");
else {
for (int i = 1; i < index; i++) {
sql = sql.replaceFirst(":", "");
count = sql.indexOf(":");
}
} String s = sql.substring(count + 1, sql.length());
char[] sqls = s.toCharArray();
StringBuffer temp = new StringBuffer();
Pattern p = Pattern.compile("[a-zA-Z]{1}"); for (int i = 0; i < sqls.length; i++) {
String c = new String(sqls, i, 1);
Matcher m = p.matcher(c);
if (m.matches())
temp.append(c);
else
break;
}
return temp.toString();
} public static void main(String[] args) {
MyDaoImplTemplate mdt = new MyDaoImplTemplate();
String sql = "select * from user where name like :name";
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "zhangsan");
String s = "";
try {
s = mdt.setParameterValue(sql, null, map);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println(s);
}
}
* 该接口为行映射器。
*
* <P>该接口中只有一个方法 <code>mapRow()</code>。
* 实现该方法,用于完成从 <code>ResultSet</code> 结果集到
* 实体的映射。
*
* @author ZhiCheng Lu
*
* @version 1.0 2010-1-11
*/
public interface RowMapper { /**行映射器。
* <p>实现该方法,用于完成从 <code>ResultSet</code> 结果集到
* 实体的映射。
* @param rs <code>ResultSet</code> 结果集
* @return 映射后的实体
* @throws SQLException 若发生数据库错误
*/
public Object mapRow(ResultSet rs) throws SQLException;}SQL语句中的参数支持 :key 进行占位,然后通过Map<String, Object>进行赋值。具体的映射规则,如果bean的字段名跟数据库中的字段名都对应的话,可以使用默认实现,如果不一致可以自行实现RowMapper来完成映射,类似于spring的JDBC操作。其实就是个spring的JDBC操作简易版。默认实现不能够完成需求的话,也可以实现EntityDao,自行实现。EntityDao持有一个MyDaoImplTemplate引用,所有的常规JDBC操作在里面都有封装,直接调用即可。
Object的你可以遵循最简单的一个映射规则,就是bean的字段名跟数据库的字段名相同,或者实现自己的EntityDao,然后在映射的时候实现对应bean的RowMapper即可。因为我没做太多工作,如果有功夫,也可以自己做一个映射层,用自己的XML配置文件指定实体Bean的映射工作;或者用Annotation指定也行,自己再多写点类进行映射工作。