一.首先先说一下个人理解这样实现dao层的优点:
1. 阿里的Druid连接池:
Druid 是目前比较流行的高性能的,分布式列存储的OLAP框架(具体来说是MOLAP)。它有如下几个特点:
(1). 亚秒级查询
druid提供了快速的聚合能力以及亚秒级的OLAP查询能力,多租户的设计,是面向用户分析应用的理想方式。
(2).实时数据注入
druid支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性
(3).可扩展的PB级存储
druid集群可以很方便的扩容到PB的数据量,每秒百万级别的数据注入。即便在加大数据规模的情况下,也能保证时其效性
(4).多环境部署
druid既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括hadoop,spark,kafka,storm和samza等
(5).丰富的社区
druid拥有丰富的社区,供大家学习
2.Apache的DButils工具类:
DBUtils是java编程中的数据库操作实用工具,小巧简单实用.
(1).对于数据表的读操作,可以把结果转换成List,Array,Set等java集合,便于程序员操作。
(2).对于数据表的写操作,也变得很简单(只需写sql语句)。
3.dao层
这个就不多说了,最大的特点实现了代码解耦。
二.代码实现:
首先三个jar包:
前两个都是druid的包,第三个数据库驱动包。
1.通过Druid连接池获取DataSource的工具类(重点哦):
package com.qjl.util;
import java.io.InputStream;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DruidUtils {
private static DruidDataSource ds;
static {
try {
InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("database.properties");
Properties properties = new Properties();
properties.load(is);
ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource() {
if(ds != null) {
return ds;
}
return null;
}
}
2.dao接口
public interface EmployeeDao {
List<Employee> findAll();
Employee findById(int empno);
int insert(Employee employee);
}
3.dao接口实现类(重点看这里哦)
package com.qjl.daoImpl;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.qjl.dao.EmployeeDao;
import com.qjl.domain.Employee;
import com.qjl.util.DruidUtils;
public class EmployeeDaoImpl implements EmployeeDao{
/**
* 查找所有
*/
@Override
public List<Employee> findAll(){
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
List<Employee> list = null;
try {
list = qr.query("select * from emp;", new BeanListHandler<>(Employee.class));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
/**
* 查找一个
*/
@Override
public Employee findById(int empno) {
Employee employee = null;
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
try {
employee = qr.query("select * from emp where empno=?;", new BeanHandler<>(Employee.class), empno);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return employee;
}
/**
* 新增
* 增删改都一个套路
*/
@Override
public int insert(Employee employee) {
int r = 0;
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
try {
r = qr.update("insert into emp values(?,?,?,?,?,?,?,?)", employee.getEmpno(),employee.getEname(),employee.getJob(),employee.getMgr(),employee.getHiredate(),employee.getSal(),employee.getComm(),employee.getDeptno());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return r;
}
}
这里写点总结,数据库操作中查找是区别于增删改的,query查找需要接收返回值对于查找多条数据用BeanListHandler来返回对象的集合,查找一条数据就BeanHandler返回一个对象接收就可以了,说一下这里这两个方法其实底层都是用反射通过Employee.class获取Employee的属性,所以这里有一点Employee实体类中的属性名称和数据库所存储的名称一定保持一致,对于update增删改大家看一下上面写的inset方法就能懂啦,然后用apache的这个DButils是真的简单,其实实际代码只有两行,获取QueryRunner对象qr,然后qr执行sql指令,还有一点这里是不需要关闭的DButils已经写好了自动关闭。
4.Employee实体类
public class Employee implements Serializable {
/**
*
*/
private static final long serialVersionUID = 373910607014836778L;
private int empno;
private String ename;
private String job;
private int mgr;
private Date hiredate;
private double sal;
private double comm;
private int deptno;
public Employee() {
// TODO Auto-generated constructor stub
}
public Employee(int empno, String ename, String job, int mgr, Date hiredate, double sal, double comm, int deptno) {
super();
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
@Override
public String toString() {
return "Employee [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate="
+ hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]";
}
}
5.最后的测试类:
public class EmployeeDaoTest {
private static EmployeeDao e = new EmployeeDaoImpl();
@Test
public void testFindAll() {
List<Employee> list = e.findAll();
for (Employee employee : list) {
System.out.println(employee);
}
}
@Test
public void testFindById() {
Employee employee = e.findById(7782);
System.out.println(employee.toString());
}
@Test
public void testInsert() throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse("1997-08-22");
Employee employee = new Employee(1112,"Joe","Manager",9000,date,1000.0,0.0,20);
int r = e.insert(employee);
if(r == 1) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
}
}
测试没有问题,就不占图啦。
6.database.properties配置文件(记得改成自己的)
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/studentdb1
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=5000
总结:
相比于传统自己编写的数据库连接工具,利用数据库连接池避免了频繁的开关数据库连接,大大提高了效率,利用apache的DButils也远比自己编写的工具功能更加强大,其中不只上面所展示方法,还有很多(比如获取一行一列数据、获取数据转成Object数组、转成集合等等),功能更加强大和完善。
这里我自己简单总结一下数据库连接池的原理(只是简单总结。。。抽象的思考。。一定没这么简单):其实在最开始通过配置文件配置,一次性创建多个Connection数据库连接,将这些数据库连接存入集合,当需要连接时从连接池取出,用完以后再放回这个数据库连接的集合中,而不是真正的关闭,这里大家可以自己编写一个数据库连接池做测试(通过打印取出的数据库连接的hashcode来看数据库连接是哪个,不会的问我啦),不要用人家的数据库连接池做测试,因为他们的都已经封装了已经不是最初的Connection了。然后常用的数据库连接池有:tomacat默认的dbcp、很多框架用的c3p0、阿里的性能最好的druid。
就这些啦,欢迎大家随时沟通交流。。。。