将Dao层中增删改查的代码进行封装
一、封装的目的和原因
- 简化Dao层对数据库的操作,希望像可以像数据库中的操作一样,只根据不同的sql语句和sql语句中的参数来达到操作数据库的目的
二、封装增删改查的分析
- 根据增删改查四种执行语句提取出相同部分进行封装,因为增删改的sql语句在数据库中执行时都只返回影响的行数,且statement对象中的executeUpdate方法可执行增删改三种sql语句,故可以将这三种方法封装成一个方法,返回影响的行数。
- 将查询方法单独进行封装,返回查询数据的集合。因为不知道具体要查询的数据对应的实体类的属性个数和数据类型,故无法进行数据封装,需要用到泛型来让调用者告知类型,用到接口回调来让调用者实现接口,告知实体类的属性个数和属性类型
三、DaoUtil工具类
1、工具类的实现
public class DaoUtils<T> {
//对增删改进行封装
//insert into emp value (?,?,?,?,?,?,?,?)
public int commonsUpdate(String sql,Object... args){
//1、获取数据库连接对象Connection
Connection conn = JDBCUtil.getConn();
//2、获取数据库操作对象
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
//2.1、设置占位符的值
if(args != null){
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
}
//3、执行SQl语句
int count = ps.executeUpdate();
//4、处理结果
return count;
} catch (SQLException e) {
e.printStackTrace();
}finally {
//5、关闭资源
JDBCUtil.closeAll(conn,ps,null);
}
return 0;
}
//对查询进行封装
public List<T> commonsQuery(String sql,RowMapper<T> rowMapper, Object... args){
//1、获取数据库连接对象Connection
Connection conn = JDBCUtil.getConn();
//2、获取数据库操作对象
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
//2.1设置占位符的值
if(args != null){
for (int i = 0; i < args.length; i++) {
//这里是重点,因为不知道要传递参数类型故用Object
ps.setObject(i+1,args[i]);
}
}
//3、执行SQL语句返回结果
ResultSet rs = ps.executeQuery();
//定义一个List集合,保存获取到一行数据
List<T> list = new ArrayList<>();
//思路:要将rs中的内容映射到 T这个类
while(rs.next()){
T t = rowMapper.getRow(rs);
list.add(t);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
2、接口回调
public interface RowMapper<T> {
//将rs指向的这行数据映射到实体类中
public T getRow(ResultSet rs);
}
3、 接口实现
class EmpRowMapper implements RowMapper<Emp>{
@Override
public Emp getRow(ResultSet rs) {
try {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
String job = rs.getString("job");
int mgr = rs.getInt("mgr");
Date hiredate = rs.getDate("hiredate");
double sal = rs.getDouble("sal");
double comm = rs.getDouble("comm");
int deptno = rs.getInt("deptno");
Emp emp = new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
return emp;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
4、DaoUtils工具类使用
public class EmpDaoImpl implements EmpDao {
DaoUtils<Emp> daoUtils = new DaoUtils();
@Override
public int insertEmp(Emp emp) {
String sql = "insert into emp values (?,?,?,?,?,?,?,?)";
Object[] args = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
return daoUtils.commonsUpdate(sql,args);
}
@Override
public int updateEmp(Emp emp) {
String sql = "update emp set ename = ?,job = ?,mgr = ?,hiredate = ?,sal = ? ,comm = ?,deptno = ? where empno = ?";
Object[] args = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};
return daoUtils.commonsUpdate(sql,args);
}
@Override
public int deleteEmp(int empno) {
String sql = "delete from emp where empno =?";
Object[] args = {empno};
return daoUtils.commonsUpdate(sql,args);
}
@Override
public Emp selectOne(int empno) {
String sql = "select * from emp where empno = ?";
Object[] args = {empno};
List<Emp> empList = daoUtils.commonsQuery(sql,new EmpRowMapper(), args);
if(empList.size() > 0 ){
return empList.get(0);
}
return null;
}
@Override
public List<Emp> selectAll() {
String sql = "select * from emp";
return daoUtils.commonsQuery(sql,new EmpRowMapper());
}
}
四、连接池
1、出现数据库连接池的原因
- 数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
2、什么是数据源(DataSource)
- JDBC2.0 提供了javax.sql.DataSource接口,它负责建立与数据库的连接,当在应用程序中访问数据库时不必编写连接数据库的代码,直接引用DataSource获取数据库的连接对象即可。用于获取操作数据Connection对象。
3、Druid连接池
- 连接池的作用:在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。
- 使用Druid连接池的步骤:
- a、创建 db.properties 配置文件。
- b、引入druid的jar 文件。
db.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///java2006?useSSL=false
username=root
password=123456
#初始化连接 (初始化连接池的,里面默认就已经存在了10个Connection连接)
initialSize=10
#最大连接数量 (当初始的10个连接不够的时候,最大会创建到50个)
maxActive=50
#最小空闲连接 (当连接池中的连接,没有被使用,就会减少到5个)
minIdle=5
#超时等待时间 (当连接数超过最大连接数,会等待5秒,如果5秒后还没有空闲连接,就会抛出异常)
maxWait=5000
4、升级之后的JDBC工具类(加入连接池)
public class JDBCUtil {
//定义一个Druid连接池
private static DataSource ds;
static {
//通过Properties读取配置文件
Properties pro = new Properties();
InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(in);
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//连接池一般是DBUtils的QueryRunner使用
public static DataSource getDataSource(){
return ds;
}
public static Connection getConn(){
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static void closeAll(Connection conn, Statement stat, ResultSet rs){
try {
if(rs!=null){
rs.close();
}
if(stat != null){
stat.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
DBUtils工具类
1、DBUtils简介
DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用
- 对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。
- 对于数据表的DML操作,也变得很简单(只需要写SQL语句)。
2、DbUtils核心API
ResultSetHandler接口:转换类型接口(结果集处理类)
- BeanHandler类:实现类,把一条记录转换成对象
- BeanListHandler类:实现类,把多条记录转换成List集合。
- ScalarHandler类:实现类,适合获取一行一列的数据。
- MapHandler类: 实现类,把一条记录转换成Map集合
- MapListHandler类:实现类,把多条记录转换成List集合。
QueryRunner:执行sql语句的类
- 增、删、改:update();
- 查询:query();
/*
* QueryRunner数据查询操作:
* 调用QueryRunner类方法query(Connection con, String sql, ResultSetHandler r, Object...params)
* ResultSetHandler r 结果集的处理方式,传递ResultSetHandler接口实现类
* Object...params SQL语句中的?占位符
*
* 注意:query方法返回值,返回的是T 泛型,具体返回值类型,跟随结果集处理方式变化
*/
/*
* 结果集其中一种处理方法,BeanListHandler
* 结果集每一行数据,封装JavaBean对象
* 多个JavaBena对象,存储到List集合
*/
public static void beanListHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort";
//调用方法query,传递结果集处理实现类BeanListHandler
List<Sort> list = qr.query(con, sql, new BeanListHandler<Sort>(Sort.class));
for(Sort s : list) {
System.out.println(s);
}
}
3、 DbUtils的使用步骤
导入jar包
- mysql连接驱动jar包
- 导入druid 的jar包
- database.properties配置文件
- 导入commons-dbutils的jar包
4、DBUtils使用
public class EmpDaoImpl implements EmpDao {
@Override
public int insertEmp(Emp emp) {
//1、创建QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
//2、调用update方法
String sql = "insert into emp values(?,?,?,?,?,?,?,?)";
Object[] args = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
try {
return qr.update(sql,args);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Emp selectOne(int empno) {
//1、创建QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from emp where empno = ?";
Object[] args = {empno};
//2、调用query方法
try {
return qr.query(sql,new BeanHandler<Emp>(Emp.class),args);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Emp> selectAll() {
//1、创建QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from emp";
//2、调用query方法
try {
return qr.query(sql,new BeanListHandler<Emp>(Emp.class));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public int selectCount() {
//1、创建QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select count(*) from emp";
//2、调用query方法
try {
return qr.query(sql, new ScalarHandler<Long>()).intValue();
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
}
将查询出来的数据封装成一个Map集合,一般用于多表联查时,有多张表的数据不能封装到一个实体类,需要装入Map的集合再一个个取出,进行封装
public class StudentDaoImpl implements StudentDao {
@Override
public Map<String, Object> selectOne(int id) {
//1、获取QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from tb_student where id = ?";
Object[] args = {id};
try {
return qr.query(sql,new MapHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Map<String, Object>> selectAll() {
//1、获取QueryRunner对象
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from tb_student";
try {
return qr.query(sql,new MapListHandler());
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}