在Dao层中,每次对数据库的增、删、改、查操作存在代码冗余,可以将共有代码抽取封装。
方法有两个参数,第一个是sql语句、第二个是参数列表。
/** * 增删改通用方法 * @param sql 增删改sql语句 * @param args 参数列表 * @return 受影响行数 */ public int commonUpdate(String sql, Object... args) { Connection conn = null; PreparedStatement preparedStatement = null; try { conn = DBUtils.getConnection(); preparedStatement = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { //第一个参数是设置的值下标,从1开始,第二个是从参数列表中取值的下标,所以从0开始 preparedStatement.setObject(i + 1, args[i]); } int result = preparedStatement.executeUpdate(); return result; } catch (SQLException sqlException) { sqlException.printStackTrace(); } finally { DBUtils.closeDb(null, preparedStatement, null); } return 0; }
public int update(Account account) { String sql = "update Account set pwd=?,balance=?,name=? where id=?"; Object[] arr = {account.getPwd(), account.getBalance(), account.getName(), account.getId()}; return daoUtils.commonUpdate(sql, arr); }
数组里的值和SQL语句中占位符一一对应。
查询通用方法相对比较麻烦,因为查询的是单个、还是多个不知道,取值时候也不清楚是哪张表、表中有哪些字段,取出来后赋值给谁、接收用什么类型接收等等。
public interface RowMapper<T> { public T getRow(ResultSet resultSet); }
public class AccountRowMapperImpl implements RowMapper<Account> { @Override public Account getRow(ResultSet resultSet) { Account account = null; try { int id = resultSet.getInt(1); String pwd = resultSet.getString(2); Double balance = resultSet.getDouble(3); String name = resultSet.getString(4); account = new Account(id,pwd,balance,name); return account; } catch (SQLException sqlException) { sqlException.printStackTrace(); } return null; } }
如果是其它表、比如User,那么就再新建一个实现类,泛型参数是User、返回类型也是User。
/** * 查询通用方法 * @param sql 查询sql语句 * @param rowMapper 回调接口、调用者要传入接口实现类 * @param args 参数列表 * @return 返回值(集合) */ public List<T> commomSelect(String sql, RowMapper<T> rowMapper, Object... args) { Connection conn = null; PreparedStatement preparedStatement = null; ResultSet rs = null; List<T> list = new ArrayList<>(); try { conn = DBUtils.getConnection(); preparedStatement = conn.prepareStatement(sql); if (args != null) { for (int i = 0; i < args.length; i++) { preparedStatement.setObject(i + 1, args[i]); } rs = preparedStatement.executeQuery(); while (rs.next()) { T t = rowMapper.getRow(rs);//回调 -->调用者提供的一个封装方法ORM list.add(t); } } } catch (SQLException sqlException) { sqlException.printStackTrace(); } finally { DBUtils.closeDb(null, preparedStatement, rs); } return list; }
public Account select(int id) { String sql = "select id,pwd,balance,name from Account where id=?"; List<Account> list = daoUtils.commomSelect(sql, new AccountRowMapperImpl(), id); if (!list.isEmpty()) { return list.get(0); } return null; }
概括来讲、增删改比较简单,返回的就只是受影响行数,而查询比较复杂,不知道查询的是那张表、有哪些字段、就更不知道用那个实体类来接收。添加一个回调函数、通过泛型传入相应的实体类,遍历赋值完成后返回给通用方法,通用方法只负责查询和返回,回调函数赋值取值和赋值。