做Java开发的朋友可能经常要与数据库打交道,而如果每次都写一大堆的获取连接,执行sql语句的方法未免太过笨拙,下面提供一种以帮助类的形式解决JDBC连接数据库的问题,可比较轻松地解决基本的CRUD操作
下面是该类的全部程序:
package com.bbs2.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; /** * JDBC的帮助类 * @author yu * * @param <T> */ public class DBHelp<T> { private final String DRIVER = "com.mysql.jdbc.Driver"; //指定数据库驱动 private final String URL = "jdbc:mysql:///bbs2"; //要连接的数据库 /** * 获取连接 * @return */ public Connection getConnection() { try { Class.forName(DRIVER); Connection conn = DriverManager.getConnection(URL,"root","root"); return conn; } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } /** * 获取自动增长的ID * @param sql save()语句 * @param args 参数列表 * @return 刚刚插入的ID */ public int getLastInsertId(String sql,Object...args){ Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; int lastId = 0; try { conn = this.getConnection(); stat = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); for (int i = 0; i < args.length; i++) { //循环给参数列表赋值 stat.setObject(i+1, args[i]); } stat.executeUpdate(); rs = stat.getGeneratedKeys(); //获取自动增长的ID if(rs.next()){ lastId = rs.getInt(1); System.out.println("latid:"+lastId); } System.out.println("SQL:"+sql); } catch (SQLException e) { System.out.println("系统出错"); } finally{ this.close(rs, stat, conn); } return lastId; } /** * 获取总记录数 * @param sql 使用聚合函数的语句 * @param args 参数列表 * @return */ public int queryForInt(String sql,Object...args){ Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; int num = 0; try { conn = this.getConnection(); stat = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { stat.setObject(i+1, args[i]); } rs = stat.executeQuery(); if(rs.next()){ num = rs.getInt(1); } System.out.println("SQL:"+sql); } catch (SQLException e) { System.out.println("系统出错"); } finally{ this.close(rs, stat, conn); } return num; } /** * 查询一组对象 * @param sql * @param mapper 对象的RowMap * @param args * @return */ public List<T> queryForList(String sql,RowMapper<T> mapper,Object...args) { Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; List<T> list = new ArrayList<T>(); conn = this.getConnection(); try { stat = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { stat.setObject(i+1, args[i]); } rs = stat.executeQuery(); while(rs.next()){ //每调用一次mapper对象的mapRow(rs)方法,会产生一个新的对象 T obj = mapper.mapRow(rs); list.add(obj); } System.out.println("SQL:" + sql); } catch (SQLException e) { e.printStackTrace(); } finally { this.close(rs, stat, conn); } return list; } /** * 查询对象 * @param sql * @param mapper * @param args * @return */ public T queryForObject(String sql,RowMapper<T> mapper,Object...args) { Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; T obj = null; conn = this.getConnection(); try { stat = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { stat.setObject(i+1, args[i]); } rs = stat.executeQuery(); if(rs.next()){ //每调用一次mapper对象的mapRow(rs)方法,会产生一个新的对象 obj = mapper.mapRow(rs); } System.out.println("SQL:" + sql); } catch (SQLException e) { e.printStackTrace(); } finally { this.close(rs, stat, conn); } return obj; } /** * 执行insert,update,delete操作 * @param sql * @param args * @return */ public int executeUpdate(String sql,Object... args){ Connection conn = null; PreparedStatement state = null; int rows = 0; try { conn = this.getConnection(); state = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { state.setObject(i+1, args[i]); } rows = state.executeUpdate(); System.out.println("SQL:"+sql); } catch (SQLException e) { e.printStackTrace(); } finally { this.close(state, conn); } return rows; } /** * 关闭连接 * @param rs * @param stat * @param conn */ public void close(ResultSet rs,Statement stat,Connection conn) { try { if(rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if(stat != null) { stat.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if(conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } /** * 关闭连接 * @param stat * @param conn */ public void close(Statement stat,Connection conn) { try { if(stat != null) { stat.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if(conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }
其中执行insert。update,delete操作的时候无需过多解释,PreparedStatement方式的sql,调用executeUpdate()方法即可,执行查询操作的时候配合下面的接口RowMapper使用,每个实体类,都应该有一个mapper类与之对应,推荐使用内部类的形式,效果更好:
package com.bbs2.util; import java.sql.ResultSet; import java.sql.SQLException; /** * 实现实体类的set方法的接口,每个实体类,都应该有一个mapper类与之对应 * 推荐使用内部类的形式 * @author yu * * @param <T> 实体类 */ public interface RowMapper<T> { T mapRow(ResultSet rs) throws SQLException; }
例如:登录操作,就可这么来做:
private DBHelp<User> db = new DBHelp<User>(); public User findByNameAndPwd(String name,String pwd){ String sql = "SELECT id,NAME,PASSWORD,regTime,email,flag,pic FROM t_user where name=? and password=?"; return db.queryForObject(sql, new UserMap(), name,pwd); }
其中UserMap()是实现了RowMapper接口的内部类:
public User mapRow(ResultSet rs) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password")); user.setRegTime(rs.getString("regTime")); user.setEmail(rs.getString("email")); user.setFlag(rs.getInt("flag")); user.setPic(rs.getString("pic")); return user; }
可以看到,这里面就是简单的给实例赋值
这么做可以在很大程度上实现代码的复用,例如,下面的注册操作:
public int save(User user) { String sql = "INSERT INTO t_user(NAME,PASSWORD,email,flag,pic,regTime) VALUES(?,?,?,?,?,?)"; return db.executeUpdate(sql, user.getName(),user.getPassword(),user.getEmail(),user.getFlag(),user.getPic(),user.getRegTime()); }
可以看到,虽然刚开始的配置是有一些复杂,但是,一旦配置完后,每个CRUD操作就是简单的两行语句