• JDBC学习笔记(四)


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

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

    public class DBConnectionManager{
      
      static{
       Class.forName("com.mysql.jdbc.Driver");
      }
    
     //读操作
     public static List<Map<String,Object>> selectObject(String sql, String[] params) throws Exception {
      Connection conn = null;
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      List<Map<String,Object>>> result  = new ArrayList<Map<String,Object>>>();
      try {
       conn = DBConnectionManager.getConnection();   
       pstmt = conn.prepareStatement(sql);
       
       for (int i = 0; params != null && i < params.length; i++) {
        pstmt.setString(i + 1, params[i]);
       }
       rs = pstmt.executeQuery();
       ResultSetMetaData meta = rs.getMetaData();
       while (rs.next()) {
        Map<String,Object> columnValue = new HashMap<String,Object>
        int size = meta.getColumnCount();
        for (int i = 1; i <= size; i++) {
         String columnName = meta.getColumnLabel(i);  //getColumnName返回的是数据库列名,getColumnLabel如有别名将返回列的别名,否则和getColumnName相同
         columnValue.add(columnName,rs.getObject(columnName));
        }
        result.add(columnValue);
       }
       return result;
      } catch (Exception e) {
       //logger.info("Execute sql : " + sql + " fail!!!");
       throw e;
      } finally {
       DBConnectionManager.free(conn, pstmt, rs);
      }
     }
     
     //增删改操作
     public static void updateObject(String sql, String[] params) throws Exception {
      Connection conn = null;
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      try {
       conn = DBConnectionManager.getConnection();   
       pstmt = conn.prepareStatement(sql);
       
       for (int i = 0; params != null && i < params.length; i++) {
        pstmt.setObject(i + 1, params[i]);
       }
       rs = pstmt.executeUpdate();
       
      } catch (Exception e) {
       //logger.info("Execute sql : " + sql + " fail!!!");
       throw e;
      } finally {
       DBConnectionManager.free(conn, pstmt, rs);
      }
     }
     
     //更好的做法是从数据库连接池中取链接
     public static Connection getConnection(){
          String dbName = "nnm5"; 
          String passwrod = "OSSDB123"; 
          String userName = "root"; 
          String url = "jdbc:mysql://localhost:13306/" + dbName; 
    
          Connection conn = DriverManager.getConnection(url, userName,passwrod); 
          return conn;
     }
     
    
     public static void free(Connection conn,PreparedStatement pstmt,ResultSet rs){
        if (rs != null) { 
                  try { 
                      rs.close(); 
                  } finally{
             if(ps != null){
               try{
                 ps.close();
                            }finally{
                 if(conn != null){
                   conn.close();
                             }
                          }
              }
              }     
         }
     
    }

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

          

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

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

    public static List selectObject(String sql, String[] params) throws Exception {
      Connection conn = null;
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      List<Map<String,Object>>> result  = new ArrayList<Map<String,Object>>>();
      try {
       conn = DBConnectionManager.getConnection();   
       pstmt = conn.prepareStatement(sql);
       
       for (int i = 0; params != null && i < params.length; i++) {
        pstmt.setString(i + 1, params[i]);
       }
       rs = pstmt.executeQuery();
       List list = new ArrayList();
       int index=0;  
       while (rs.next()) {
          list.add(objectMapper(rs));  //传递的是每次减去一行后的结果集
       index++;   
       }
       return list ;
      } catch (Exception e) {
       //logger.info("Execute sql : " + sql + " fail!!!");
       throw e;
      } finally {
       DBConnectionManager.free(conn, pstmt, rs);
      }
     }
    
    public abstract  Object objectMapper(ResultSet rs);

      具体的Dao中的代码如下:

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

      

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

          首先需要一个接口:

    public interface RowMapper {
        public Object objectMapper(ResultSet rs);
    }

           再修改模板类:

    public static List selectObject(String sql, String[] params, RowMapper mapper) throws Exception {
      Connection conn = null;
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      List<Map<String,Object>>> result  = new ArrayList<Map<String,Object>>>();
      try {
       conn = DBConnectionManager.getConnection();   
       pstmt = conn.prepareStatement(sql);
       
       for (int i = 0; params != null && i < params.length; i++) {
        pstmt.setString(i + 1, params[i]);
       }
       rs = pstmt.executeQuery();
       List list = new ArrayList();
       int index=0;  
       while (rs.next()) {
          list.add(mapper.objectMapper(rs));  //传递的是每次减去一行后的结果集
       index++;   
       }
       return list ;
      } catch (Exception e) {
       //logger.info("Execute sql : " + sql + " fail!!!");
       throw e;
      } finally {
       DBConnectionManager.free(conn, pstmt, rs);
      }
     }

      具体的Dao中的代码:

    public List getPerson(Integer id) {
             String sql="select id,name from person where id<?";
             Object [] objs=new Object[]{id};
             return mu.getObject(sql,objs,new MyRowMapper1());
    }
        
    class MyRowMapper1 implements RowMapper{
             public Object objectMapper(ResultSet rs) {          
             Person person=new Person();
             try{
                                 person.setId((Integer)rs.getObject(1));
                                 person.setName((String)rs.getObject(2));
             }catch(Exception e){
                  logger.log(e.printStackTrace());
             }            
             return person;
          }
    }

      使用JDBC的SimpleJDBCTemplate的代码:

    String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :tname";
    
    RowMapper<UserBean> rw = new RowMapper<UserBean>(){
    
      @Override
    
        public UserBean mapRow(ResultSet paramResultSet, int paramInt)
    
         throws SQLException {
    
          UserBean ub = new UserBean();        
    
                      ub.setId(paramResultSet.getObject("id") + "");
    
          ub.setName(paramResultSet.getObject("tname") + "");
    
          ub.setPassword(paramResultSet.getObject("tpwd") + "");
    
          return ub;
    
        }    
    
      };
    
      Map<String, String> map = new HashMap<String, String>();
    
      map.put("tname", "p");
    
        UserBean ub = jdbctemplate.queryForObject(sql2, map, rw);    //UserBean ub = jdbctemplate.queryForObject(sql2, map, new BeanPropertyRowMapper(UserBean.class)); 
    
        System.out.println(ub.getName() + "," + ub.getPassword());

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

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

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

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

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

     String sql="insert into person(name) values (:name)";
     Map map = new HashMap();
     map.put(":tname","add");
    
     //Person p = new Person();
     //SqlParamterSource ps = new BeanPropertySqlParamterSource(p);

    KeyHolder keyHolder
    = new GeneratedKeyHolder(); jdbctemplate.update(sql, map, keyHolder ); int id = keyHolder.getKey().intValue(); //单主键的情况 Map map = keyHolder.getKeys(); //混合主键的情况

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

             

         使用SimpleJdbcTemplate的例子:

    @Override  
        public void delete(int id) {   
            String sql = "delete from user where id=?";   
            getSimpleJdbcTemplate().update(sql, id);   
      
        }   
      
        @Override  
        public User findById(int id) {   
            String sql = "select * from user where id=?";   
            return getSimpleJdbcTemplate().queryForObject(sql,   
                    ParameterizedBeanPropertyRowMapper.newInstance(User.class), id);   
      
            // 下面的方法只能返回一列,所以行不通   
            // return getSimpleJdbcTemplate().queryForObject(sql, User.class, id);   
      
        }   
      
        @Override  
        public int findByName(String name){   
            String sql = "select id from user where name=?";   
            return getSimpleJdbcTemplate().queryForObject(sql, Integer.class, name);   
            // Integer.class 改成int.class 不行   
            // 貌似只能用包装类   
               
        }   
      
        @Override  
        public List<User> findAll() {   
            String sql = "select * from user";   
            return getSimpleJdbcTemplate().query(sql,   
                    ParameterizedBeanPropertyRowMapper.newInstance(User.class));   
        }   
      
        @Override  
        public int count() {   
            String sql = "select count(*) from user";   
            return getSimpleJdbcTemplate().queryForInt(sql);   
        }   
      
        @Override  
        public void batchInsert(List<User> users) {   
            String sql = "insert into user(id,name)values(?,?)";   
            List<Object[]> parameters = new ArrayList<Object[]>();   
            for (User u : users) {   
                parameters.add(new Object[] { u.getId(), u.getName() });   
            }   
            getSimpleJdbcTemplate().batchUpdate(sql, parameters);   
      
        }   

     

  • 相关阅读:
    基于jQuery的自定义插件:实现整屏分页转换的功能
    蝶恋花
    js中面向对象编程
    移动端web页面列表类上拉加载,查看详情,iframe嵌套第三方页面遇到的问题以及解决办法
    控制使用jquery load()方法载入新页面中的元素
    bootstrap-daterangepicker双日历控件开始日期选择问题
    点击select下拉框获取option的属性值
    bootstrap table表格前台分页,点击tab选项,重新刷新表格
    jquery中使元素显示和隐藏方法之间的区别
    jquery对象和DOM对象的相互转换
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/4162820.html
Copyright © 2020-2023  润新知