减少各个Dao类间的重复代码,有以下几种方式:

写一个DBConnectionManager,将公共的查询逻辑做成方法,将sql语句作为参数传递给方法。

  1. public class DBConnectionManager{
  2.  
  3. static{
  4. Class.forName("com.mysql.jdbc.Driver");
  5. }
  6.  
  7. //读操作
  8. public static List<Map<String,Object>> selectObject(String sql, String[] params) throws Exception {
  9. Connection conn = null;
  10. PreparedStatement pstmt = null;
  11. ResultSet rs = null;
  12. List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
  13. try {
  14. conn = DBConnectionManager.getConnection();
  15. pstmt = conn.prepareStatement(sql);
  16.  
  17. for (int i = 0; params != null && i < params.length; i++) {
  18. pstmt.setString(i + 1, params[i]);
  19. }
  20. rs = pstmt.executeQuery();
  21. ResultSetMetaData meta = rs.getMetaData();
  22. while (rs.next()) {
  23. Map<String,Object> columnValue = new HashMap<String,Object>
  24. int size = meta.getColumnCount();
  25. for (int i = 1; i <= size; i++) {
  26. String columnName = meta.getColumnLabel(i); //getColumnName返回的是数据库列名,getColumnLabel如有别名将返回列的别名,否则和getColumnName相同
  27. columnValue.add(columnName,rs.getObject(columnName));
  28. }
  29. result.add(columnValue);
  30. }
  31. return result;
  32. } catch (Exception e) {
  33. //logger.info("Execute sql : " + sql + " fail!!!");
  34. throw e;
  35. } finally {
  36. DBConnectionManager.free(conn, pstmt, rs);
  37. }
  38. }
  39.  
  40. //增删改操作
  41. public static void updateObject(String sql, String[] params) throws Exception {
  42. Connection conn = null;
  43. PreparedStatement pstmt = null;
  44. ResultSet rs = null;
  45. try {
  46. conn = DBConnectionManager.getConnection();
  47. pstmt = conn.prepareStatement(sql);
  48.  
  49. for (int i = 0; params != null && i < params.length; i++) {
  50. pstmt.setObject(i + 1, params[i]);
  51. }
  52. rs = pstmt.executeUpdate();
  53.  
  54. } catch (Exception e) {
  55. //logger.info("Execute sql : " + sql + " fail!!!");
  56. throw e;
  57. } finally {
  58. DBConnectionManager.free(conn, pstmt, rs);
  59. }
  60. }
  61.  
  62. //更好的做法是从数据库连接池中取链接
  63. public static Connection getConnection(){
  64. String dbName = "nnm5";
  65. String passwrod = "OSSDB123";
  66. String userName = "root";
  67. String url = "jdbc:mysql://localhost:13306/" + dbName;
  68.  
  69. Connection conn = DriverManager.getConnection(url, userName,passwrod);
  70. return conn;
  71. }
  72.  
  73. public static void free(Connection conn,PreparedStatement pstmt,ResultSet rs){
  74. if (rs != null) {
  75. try {
  76. rs.close();
  77. } finally{
  78.          if(ps != null){
  79.            try{
  80.              ps.close();
  81. }finally{
  82.              if(conn != null){
  83.                conn.close();
  84. }
  85. }
  86.          }
  87. }
  88. }
  89.  
  90. }

  上述方法不好的地方在于返回的结果是 List<Map<String,Object>>,如果希望能像ORM框架那样的返回对象,就可以实现一个RowMapper,类似于Spring中提供的SimpleJdbcTemplate。

代码中加上RowMapper也有两种方式,第一种是使用模板方式,第二种是使用策略方式。

使用模板方式的例子如下,修改上面的模板类中的方法:

  1. public static List selectObject(String sql, String[] params) throws Exception {
  2. Connection conn = null;
  3. PreparedStatement pstmt = null;
  4. ResultSet rs = null;
  5. List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
  6. try {
  7. conn = DBConnectionManager.getConnection();
  8. pstmt = conn.prepareStatement(sql);
  9.  
  10. for (int i = 0; params != null && i < params.length; i++) {
  11. pstmt.setString(i + 1, params[i]);
  12. }
  13. rs = pstmt.executeQuery();
  14. List list = new ArrayList();
  15. int index=0;
  16. while (rs.next()) {
  17. list.add(objectMapper(rs)); //传递的是每次减去一行后的结果集
  18. index++;
  19. }
  20. return list ;
  21. } catch (Exception e) {
  22. //logger.info("Execute sql : " + sql + " fail!!!");
  23. throw e;
  24. } finally {
  25. DBConnectionManager.free(conn, pstmt, rs);
  26. }
  27. }
  28.  
  29. public abstract Object objectMapper(ResultSet rs);

  具体的Dao中的代码如下:

  1. public List getPerson(Integer id){
  2. String sql="select id,name from person where id<?";
  3. Object [] objs=new Object[]{id};
  4. return super.getObject(sql,objs); //实际调用的还是该类中的objectMapper。
  5. }
  6.  
  7. public Object objectMapper(ResultSet rs){
  8. Person person=new Person;
  9. try{
  10. person.setId((Integer)rs.getObject(1));
  11. person.setName((String)rs.getObject(2));
  12. }catch(Exception e){
  13. logger.log(e.printStackTrace());
  14. }
  15. return person;
  16. }

  

使用策略模式修改模板类中的代码如下:

首先需要一个接口:

  1. public interface RowMapper {
  2. public Object objectMapper(ResultSet rs);
  3. }

再修改模板类:

  1. public static List selectObject(String sql, String[] params, RowMapper mapper) throws Exception {
  2. Connection conn = null;
  3. PreparedStatement pstmt = null;
  4. ResultSet rs = null;
  5. List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
  6. try {
  7. conn = DBConnectionManager.getConnection();
  8. pstmt = conn.prepareStatement(sql);
  9.  
  10. for (int i = 0; params != null && i < params.length; i++) {
  11. pstmt.setString(i + 1, params[i]);
  12. }
  13. rs = pstmt.executeQuery();
  14. List list = new ArrayList();
  15. int index=0;
  16. while (rs.next()) {
  17. list.add(mapper.objectMapper(rs)); //传递的是每次减去一行后的结果集
  18. index++;
  19. }
  20. return list ;
  21. } catch (Exception e) {
  22. //logger.info("Execute sql : " + sql + " fail!!!");
  23. throw e;
  24. } finally {
  25. DBConnectionManager.free(conn, pstmt, rs);
  26. }
  27. }

  具体的Dao中的代码:

  1. public List getPerson(Integer id) {
  2. String sql="select id,name from person where id<?";
  3. Object [] objs=new Object[]{id};
  4. return mu.getObject(sql,objs,new MyRowMapper1());
  5. }
  6.  
  7. class MyRowMapper1 implements RowMapper{
  8. public Object objectMapper(ResultSet rs) {
  9. Person person=new Person();
  10. try{
  11. person.setId((Integer)rs.getObject(1));
  12. person.setName((String)rs.getObject(2));
  13. }catch(Exception e){
  14. logger.log(e.printStackTrace());
  15. }
  16. return person;
  17. }
  18. }

  使用JDBC的SimpleJDBCTemplate的代码:

  1. String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :tname";
  2.  
  3. RowMapper<UserBean> rw = new RowMapper<UserBean>(){
  4.  
  5.   @Override
  6.  
  7.     public UserBean mapRow(ResultSet paramResultSet, int paramInt)
  8.  
  9.      throws SQLException {
  10.  
  11.       UserBean ub = new UserBean();
  12.  
  13.   ub.setId(paramResultSet.getObject("id") + "");
  14.  
  15.       ub.setName(paramResultSet.getObject("tname") + "");
  16.  
  17.       ub.setPassword(paramResultSet.getObject("tpwd") + "");
  18.  
  19.       return ub;
  20.  
  21.     }
  22.  
  23.   };
  24.  
  25.   Map<String, String> map = new HashMap<String, String>();
  26.  
  27.   map.put("tname", "p");
  28.  
  29.   UserBean ub = jdbctemplate.queryForObject(sql2, map, rw); //UserBean ub = jdbctemplate.queryForObject(sql2, map, new BeanPropertyRowMapper(UserBean.class));
  30.  
  31.   System.out.println(ub.getName() + "," + ub.getPassword());

  queryForObject只返回一条记录,如果是多条记录应该用query方法。queryForString(String sql,String.class)将返回字符串型的结果。如果没有对应的javabean,可以用queryForMap和queryForList方法。queryForMap返回一条记录,queryForList返回多条记录。

  如果希望能够取得插入记录的主键值,可以调用回调函数,也可以在回调函数中对connection做更多的处理。

  1. static Integer id=0;
  2.  
  3. public static int getId(final Person person) {
  4. JdbcTemplate jdbcTemplate=new JdbcTemplate(JDBCUtils.getDataSource());
  5.  
  6. jdbcTemplate.execute(new ConnectionCallback(){
  7. //传递的参数为Connection conn,自己可以在conn内写希望完成的功能
  8. public Object doInConnection(Connection conn) throws SQLException,DataAccessException{
  9. String sql="insert into person(name) values (?)";
  10. PreparedStatement ps=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//返回所插入数据的主键
  11. for(int i=0;i<10;i++){
  12. ps.setString(1, person.getName());
  13. ps.addBatch(); //批处理,将SQL语句进行打包
  14. }
  15. //ps.executeUpdate();
  16. ps.executeBatch(); //没有这一行是不会插入数据的
  17. ResultSet rs=ps.getGeneratedKeys();
  18. while(rs.next())
  19. id=rs.getInt(1);
  20. return id;
  21. }
  22. });
  23. return id;
  24. }

  SimpleJdbcTemplate里面封装了NamedJdbcTemplate,NamedJdbcTemplate里面又包含JdbcTemplate,增加了对泛型和可变长度参数的支持。从Spring 3.1开始,JdbcTemplate和NamedParameterJdbcTemplate提供了SimpleJdbcTemplate的功能。SimpleJdbcTemplate被标注为过时,使用JdbcTemplate和NamedParameterJdbcTemplate即可。

使用JDBCTemplate的KeyHolder获取新插入数据的主键:

  1. String sql="insert into person(name) values (:name)";
  2. Map map = new HashMap();
  3. map.put(":tname","add");

  4.  //Person p = new Person();
     //SqlParamterSource ps = new BeanPropertySqlParamterSource(p);
  5. KeyHolder keyHolder = new GeneratedKeyHolder();
  6. jdbctemplate.update(sql, map, keyHolder );
  7. int id = keyHolder.getKey().intValue(); //单主键的情况
  8.  
  9. Map map = keyHolder.getKeys(); //混合主键的情况

 如果想调用NamedJdbcTemplate中的方法,可以使用jdbctemplate.getNamedJdbcTemplate()。

使用SimpleJdbcTemplate的例子:

  1. @Override
  2. public void delete(int id) {
  3. String sql = "delete from user where id=?";
  4. getSimpleJdbcTemplate().update(sql, id);
  5.  
  6. }
  7.  
  8. @Override
  9. public User findById(int id) {
  10. String sql = "select * from user where id=?";
  11. return getSimpleJdbcTemplate().queryForObject(sql,
  12. ParameterizedBeanPropertyRowMapper.newInstance(User.class), id);
  13.  
  14. // 下面的方法只能返回一列,所以行不通
  15. // return getSimpleJdbcTemplate().queryForObject(sql, User.class, id);
  16.  
  17. }
  18.  
  19. @Override
  20. public int findByName(String name){
  21. String sql = "select id from user where name=?";
  22. return getSimpleJdbcTemplate().queryForObject(sql, Integer.class, name);
  23. // Integer.class 改成int.class 不行
  24. // 貌似只能用包装类
  25.  
  26. }
  27.  
  28. @Override
  29. public List<User> findAll() {
  30. String sql = "select * from user";
  31. return getSimpleJdbcTemplate().query(sql,
  32. ParameterizedBeanPropertyRowMapper.newInstance(User.class));
  33. }
  34.  
  35. @Override
  36. public int count() {
  37. String sql = "select count(*) from user";
  38. return getSimpleJdbcTemplate().queryForInt(sql);
  39. }
  40.  
  41. @Override
  42. public void batchInsert(List<User> users) {
  43. String sql = "insert into user(id,name)values(?,?)";
  44. List<Object[]> parameters = new ArrayList<Object[]>();
  45. for (User u : users) {
  46. parameters.add(new Object[] { u.getId(), u.getName() });
  47. }
  48. getSimpleJdbcTemplate().batchUpdate(sql, parameters);
  49.  
  50. }

 

JDBC学习笔记(四)的更多相关文章

  1. JDBC 学习笔记(十一)—— JDBC 的事务支持

    1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...

  2. JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架

    1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...

  3. JDBC学习笔记一

    JDBC学习笔记一 JDBC全称 Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的Java API. ODBC全称 Open Database Conn ...

  4. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  5. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  6. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  8. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

随机推荐

  1. BZOJ2338: [HNOI2011]数矩形

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2338 中学数学老师告诉我们,一个矩形的两条对角线相等,所以只要把所有的边拿出来,记录下中点坐标 ...

  2. c++(查找)

    无论是数据库,还是普通的ERP系统,查找功能数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数 ...

  3. SpringMVC框架学习笔记——各种异常、报错解决

    1.Target runtime com.genuitec.runtime.generic.jee60 is not defined. 找到导入项目的.setting文件夹org.eclipse.ws ...

  4. HttpClient 用于解决测试时候乱码的问题

    @Test public void doPostWithParam() throws Exception, IOException { CloseableHttpClient httpClient = ...

  5. UEP-查询方式总结

    public void retrieve() { QueryParamList params = getQueryParam("dataWrap"); //获取页面上的参数,即查询 ...

  6. Deep Learning速成教程

          引言         深度学习,即Deep Learning,是一种学习算法(Learning algorithm),亦是人工智能领域的一个重要分支.从快速发展到实际应用,短短几年时间里, ...

  7. 【深度学习系列】PaddlePaddle可视化之VisualDL

    上篇文章我们讲了如何对模型进行可视化,用的keras手动绘图输出CNN训练的中途结果,本篇文章将讲述如何用PaddlePaddle新开源的VisualDL来进行可视化.在讲VisualDL之前,我们先 ...

  8. 如何制作gif图片

    制作Gif图片的方法很多,大多数情况下都会选择利用PS中的ImageReady插件来制作.其实还有其它更好的选择来制作Gift图片,其中一款软件就是利用Flash来实现.下面小编就给大家展示一下如何利 ...

  9. MYSQL 数据库导入导出命令

    在不同操作系统或MySQL版本情况下,直接拷贝文件的方法可能会有不兼容的情况发生.所以一般推荐用SQL脚本形式导入.下面分别介绍两种方法. MySQL命令行导出数据库 1,进入MySQL目录下的bin ...

  10. twitter的ID生成器的snowFlake算法的自造版

    snowFlake算法在生成ID时特别高效,可参考:https://segmentfault.com/a/1190000011282426 SnowFlake算法生成id的结果是一个64bit大小的整 ...