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);   
  
    }   

 

posted on 2014-12-14 18:29  lnlvinso  阅读(387)  评论(0编辑  收藏  举报