在模拟servlet调用dao中,我们发现在dao的实现类中有许多重复代码,我们可以将其封装起来。
步骤:
一. 创建一个类 DBUtil
1加载驱动和建立链接的代码 完全一样
加载驱动写到静态代码快中 :因为 驱动只需要加载一次即可 比如:你安装了一台电脑 只需要下载一次qq 以后直接使用就可以了
类的静态代码块 随着类的加载 只执行一次
建立连接的代码 单独创建一个方法 通过返回值返回连接对象:为什么连接要连接多次?因为来连接用完了就关闭了
2 关闭的代码也需要封装
3 增删改的预处理代码 也基本一样
4.查询单独封装
A List<Map<String,Object>>
B 如果我们不知道表有哪些列 该怎么办?
出现什么问题:1 我们不能根据列名获取该列对应的数据
2 在存储到map中的时候 也不知道该用什么key来映射
解决方案: 1 可以通过列的编号取数据
2 可以通过列的编号获取列名
出现的问题: 我们可以通过列的编号获取列的名字和数据,那么我们不确定一张表有多少列,取得时候上限是多少呢?
解决方案 : 可以获取一张表有多少列
代码如下:
/** * JDBC工具类 */ public class DBUtil { //注册驱动代码 static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //建立连接 public static Connection getConnection(){ try { return DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEnconding=UTF-8", "root", "root"); } catch (SQLException e) { e.printStackTrace(); } return null; } /** 增删改的通用方法 * @paramString sql 要执行的sql * @paramObject[] obj 对象类型的数组 里面存放着 sql执行的占位符参数 * 【name,age,id】 * 【id】 * 【name,age】 * Object... 可变参数 * */ public static boolean executeUpdate(String sql,Object... args){ Connection conn = null; PreparedStatement ps = null; try { conn = getConnection(); ps = conn.prepareStatement(sql); for (int i=0;i<args.length;i++){ ps.setObject(i+1,args[i]); } int i = ps.executeUpdate(); if (i>0)return true; } catch (SQLException e) { e.printStackTrace(); } finally { //关闭 close(conn,ps,null); } return false; } /** * 查询的通用方法 * @param sql * @param args * @return */ public static List<Map<String,Object>> executeQuery(String sql,Object... args){ Connection conn = null; PreparedStatement ps = null; ResultSet set = null; try { conn = DBUtil.getConnection(); ps = conn.prepareStatement(sql); /* 有可能有参数 */ for (int i=0;i<args.length;i++){ ps.setObject(i+1,args[i]); } /*执行*/ set = ps.executeQuery(); /*需要将所有数据都存放到 List中 每一行 用一个 map存放*/ List<Map<String,Object>> list = new ArrayList<>(); /*获取本次查询结果集有多少列*/ int count = set.getMetaData().getColumnCount(); while(set.next()){ Map<String, Object> map = new HashMap<>();//一行数据 用一个map 接收 for(int i=0;i<count;i++){ String name = set.getMetaData().getColumnLabel(i+1); map.put(name,set.getObject(name)); } /*将每行的map存放到 List中*/ list.add(map); } return list; } catch (Exception e) { e.printStackTrace(); }finally { close(conn,ps,set); } return null; } /** 关闭的通用方法 * * */ private static void close(Connection conn,PreparedStatement st,ResultSet set){ try { if(set!=null){ set.close(); } if(st!=null){ st.close(); } if(conn != null){ conn.close(); } }catch (Exception e){ e.printStackTrace(); } } }
二.使用工具类前的代码:
三.使用后的代码:
public class StudentDAOImpl implements IStudentDAO { //增加 @Override public boolean add(Student s) { String sql = "insert into student (name,age) values (?,?)"; return DBUtil.executeUpdate(sql,s.getName(),s.getAge()); } //删除 @Override public boolean delete(int id) { String sql = "delete from student where id = ?"; return DBUtil.executeUpdate(sql,id); } //修改 @Override public boolean update(Student s) { String sql = "update student set name=?,age=? where id = ?"; return DBUtil.executeUpdate(sql,s.getName(),s.getAge(),s.getId()); } //查询,结果封装成map(只能查一条) @Override public Map<String, Object> getStudent(int id) { String sql = "select * from student where id = ?"; List<Map<String, Object>> list = DBUtil.executeQuery(sql, id); if(list.size()>0){ return list.get(0); } return null; } //查询,多条map放进list集合中 @Override public List<Map<String, Object>> getAllStudent() { String sql = "select * from dog"; return DBUtil.executeQuery(sql); } }