- DAO模式
- 员工管理系统开发
- 封装BaseDao
- 连接池
- log4j日志框架
- 三大范式
- 数据库之间的三大关系
DAO模式
介绍
DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。夹在业务逻辑
与数据库资源中间。
在核心J2EE模式中是这样介绍DAO模式的:为了建立一个健壮的J2EE应用,应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储.
简单来说,就是定义一个接口,规定一些增删改查的方法,然后交给实现类去实现, 它介于数据库和业务逻辑代码之间,这样当我们需要操作数据库是,根据接口定义的API去操作数据库就可以了,每个方法都是一个原子性的操作,例如:增加、修改、删除等
Dao模式要求项目必须具备这样几个结构:
- 实体类:和数据库表格一 一对应的类,单独放入一个包中,包名往往是 pojo/entity/bean,要操作的每个表格都应该有对应的实体类
1 2 3
| emp > class Emp dept > class Dept account > class Account
|
- DAO 层:定义了对数据要执行那些操作的接口和实现类,包名往往是 dao/mapper,要操作的每个表格都应该有对应的接口和实现类
1 2
| emp > interface EmpDao >EmpDaoImpl dept > interface DeptDao> DeptDaoImpl
|
- Mybatis/Spring JDBCTemplate 中,对DAO层代码进行了封装,代码编写方式会有其他变化
项目的搭建
创建项目(Java模块)
添加jar包
创建包(pojo、dao)
创建实体类Emp(有多少表创多少类)
创建后台的接口EmpDao和实现类EmpDaoImpl
项目结构图
实体类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| package com.excepenxi.pojo;
import java.io.Serializable; import java.util.Date;
public class Emp implements Serializable { private Integer empno; private String ename; private String job; private Integer mgr; private Date hiredate; private Double sal; private Double comm; private Integer deptno;
@Override public String toString() { return "Emp{" + "empno=" + empno + ", ename='" + ename + '\'' + ", job='" + job + '\'' + ", mgr=" + mgr + ", hiredate=" + hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + '}'; }
public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double comm, Integer deptno) { 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 Emp(){ }
public Integer getEmpno() { return empno; } public void setEmpno(Integer 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 Integer getMgr() { return mgr; } public void setMgr(Integer 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 Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package com.excepenxi.pojo;
import java.io.Serializable;
public class Dept implements Serializable { private Integer deptno; private String dname; private String loc;
@Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + '}'; }
public Dept(Integer deptno, String dname, String loc) { this.deptno = deptno; this.dname = dname; this.loc = loc; }
public Dept() { }
public Integer getDeptno() { return deptno; }
public void setDeptno(Integer deptno) { this.deptno = deptno; }
public String getDname() { return dname; }
public void setDname(String dname) { this.dname = dname; }
public String getLoc() { return loc; }
public void setLoc(String loc) { this.loc = loc; } }
|
DAO接口代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.excepenxi.dao;
import com.excepenxi.pojo.Emp;
public interface EmpDao {
int addEmp(Emp emp);
int deleteByEmpno(int empno); }
|
1 2 3 4
| package com.excepenxi.dao;
public interface DeptDao { }
|
DAO实现类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.EmpDao; import com.excepenxi.pojo.Emp;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException;
public class EmpDaoImpl implements EmpDao { private static String driver ="com.mysql.cj.jdbc.Driver"; private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; private static String user="root"; private static String password="root";
@Override public int addEmp(Emp emp) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,emp.getEname()); preparedStatement.setObject(2,emp.getJob() ); preparedStatement.setObject(3,emp.getMgr()); preparedStatement.setObject(4,emp.getHiredate()); preparedStatement.setObject(5,emp.getSal()); preparedStatement.setObject(6,emp.getComm()); preparedStatement.setObject(7,emp.getDeptno()); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; }
@Override public int deleteByEmpno(int empno) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="delete from emp where empno =?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,empno); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; } }
|
1 2 3 4 5 6
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.DeptDao;
public class DeptDaolmpl implements DeptDao { }
|
运行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.excepenxi.test1;
import com.excepenxi.dao.EmpDao; import com.excepenxi.dao.impl.EmpDaoImpl; import com.excepenxi.pojo.Emp;
import java.util.Date;
public class Test1 { public static void main(String[] args) { EmpDao empDao = new EmpDaoImpl();
Emp emp = new Emp(null,"JHON","MANAGER",7839,new Date(),3000.12,1000.31,30); int rows = empDao.addEmp(emp); System.out.println(rows);
} }
|
员工管理系统开发
DAO接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.excepenxi.dao;
import com.excepenxi.pojo.Emp; import java.util.List; public interface EmpDao {
int addEmp(Emp emp);
int deleteByEmpno(int empno);
List<Emp> findAll();
int updateEmp(Emp emp); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.excepenxi.dao;
import com.excepenxi.pojo.Dept; import java.util.List;
public interface DeptDao {
List<Dept> findAll(); int addDept(Dept dept); }
|
DAO实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.EmpDao; import com.excepenxi.pojo.Emp;
import java.sql.*; import java.util.ArrayList; import java.util.List;
public class EmpDaoImpl implements EmpDao { private static String driver ="com.mysql.cj.jdbc.Driver"; private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; private static String user="root"; private static String password="root";
@Override public int addEmp(Emp emp) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,emp.getEname()); preparedStatement.setObject(2,emp.getJob() ); preparedStatement.setObject(3,emp.getMgr()); preparedStatement.setObject(4,emp.getHiredate()); preparedStatement.setObject(5,emp.getSal()); preparedStatement.setObject(6,emp.getComm()); preparedStatement.setObject(7,emp.getDeptno()); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; }
@Override public int deleteByEmpno(int empno) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="delete from emp where empno =?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,empno); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; }
@Override public List<Emp> findAll() { Connection connection = null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; List<Emp> list =null; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="select * from emp"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); list=new ArrayList<Emp>() ; while(resultSet.next()){ int empno = resultSet.getInt("empno"); String ename = resultSet.getString("ename"); String job = resultSet.getString("job"); int mgr = resultSet.getInt("mgr"); Date hiredate = resultSet.getDate("hiredate"); double sal= resultSet.getDouble("sal"); double comm= resultSet.getDouble("comm"); int deptno= resultSet.getInt("deptno"); Emp emp =new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno); list.add(emp); } }catch (Exception e){ e.printStackTrace(); }finally { if(null != resultSet){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; }
@Override public int updateEmp(Emp emp) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="update emp set ename =? ,job=?, mgr =?,hiredate =?,sal=?,comm=?,deptno=? where empno =?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,emp.getEname()); preparedStatement.setObject(2,emp.getJob() ); preparedStatement.setObject(3,emp.getMgr()); preparedStatement.setObject(4,emp.getHiredate()); preparedStatement.setObject(5,emp.getSal()); preparedStatement.setObject(6,emp.getComm()); preparedStatement.setObject(7,emp.getDeptno()); preparedStatement.setObject(8,emp.getEmpno()); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.DeptDao; import com.excepenxi.pojo.Dept;
import java.sql.*; import java.util.ArrayList; import java.util.List;
public class DeptDaolmpl implements DeptDao { private static String driver ="com.mysql.cj.jdbc.Driver"; private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; private static String user="root"; private static String password="root";
@Override public List<Dept> findAll() { Connection connection = null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; List<Dept> list =null; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="select * from dept"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); list=new ArrayList<Dept>() ; while(resultSet.next()){ int deptno = resultSet.getInt("deptno"); String dname = resultSet.getString("dname"); String loc = resultSet.getString("loc"); Dept dept =new Dept(deptno,dname,loc); list.add(dept); } }catch (Exception e){ e.printStackTrace(); }finally { if(null != resultSet){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; }
@Override public int addDept(Dept dept) { Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); String sql="insert into dept values(?,?,?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1,dept.getDeptno()); preparedStatement.setObject(2,dept.getDname()); preparedStatement.setObject(3,dept.getLoc() ); rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; } }
|
EmpManageSystem类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| package com.excepenxi.view;
import com.excepenxi.dao.DeptDao; import com.excepenxi.dao.EmpDao; import com.excepenxi.dao.impl.DeptDaolmpl; import com.excepenxi.dao.impl.EmpDaoImpl; import com.excepenxi.pojo.Dept; import com.excepenxi.pojo.Emp;
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Scanner;
public class EmpManageSystem { private static Scanner sc =new Scanner(System.in); private static EmpDao empDao =new EmpDaoImpl(); private static DeptDao deptDao =new DeptDaolmpl(); private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");;
public static void main(String[] args) { while(true){ showMenu(); System.out.print("请录入选项:"); int option =sc.nextInt(); switch (option){ case 1: case1(); break; case 2: case2(); break; case 3: case3(); break; case 4: case4(); break; case 5: case5(); break; case 6: case6(); break; case 7: sc.close(); System.exit(0); break; default: System.out.println("请正确输入选项!!!"); } } }
private static void case1(){ List<Emp> emps = empDao.findAll(); emps.forEach(System.out::println); } private static void case2(){ List<Dept> depts = deptDao.findAll(); depts.forEach(System.out::println); } private static void case3(){ System.out.print("请输入要删除的员工编号:"); int empno=sc.nextInt(); empDao.deleteByEmpno(empno); } private static void case4(){ System.out.print("请输入员工编号:"); int empno =sc.nextInt(); System.out.print("请输入员工姓名:"); String ename =sc.next(); System.out.print("请输入员工职位:"); String job =sc.next(); System.out.print("请输入员工上级:"); int mgr =sc.nextInt(); System.out.print("请输入员工入职日期,格式为yyyy-MM-dd:"); Date hiredate =null; try { hiredate = simpleDateFormat.parse(sc.next()); } catch (ParseException e) { e.printStackTrace(); } System.out.print("请输入员工工资:"); double sal =sc.nextDouble(); System.out.print("请输入员工补助:"); double comm=sc.nextDouble(); System.out.print("请输入员工部门号:"); int deptno =sc.nextInt(); Emp emp=new Emp(empno, ename, job, mgr, hiredate, sal, comm,deptno); empDao.updateEmp(emp); } private static void case5(){ System.out.print("请输入员工姓名:"); String ename =sc.next(); System.out.print("请输入员工职位:"); String job =sc.next(); System.out.print("请输入员工上级:"); int mgr =sc.nextInt(); System.out.print("请输入员工入职日期,格式为yyyy-MM-dd:"); Date hiredate =null; try { hiredate = simpleDateFormat.parse(sc.next()); } catch (ParseException e) { e.printStackTrace(); } System.out.print("请输入员工工资:"); double sal =sc.nextDouble(); System.out.print("请输入员工补助:"); double comm=sc.nextDouble(); System.out.print("请输入员工部门号:"); int deptno =sc.nextInt(); Emp emp=new Emp(null, ename, job, mgr, hiredate, sal, comm,deptno); empDao.addEmp(emp); } private static void case6(){ System.out.print("请录入部门号:"); int deptno =sc.nextInt(); System.out.print("请录入部门名称:"); String dname =sc.next(); System.out.print("请录入部门位置:"); String loc =sc.next(); Dept dept =new Dept(deptno,dname,loc); deptDao.addDept(dept); }
public static void showMenu(){ System.out.println("************************************"); System.out.println("* 1 查看所有员工信息"); System.out.println("* 2 查看所有部门信息"); System.out.println("* 3 根据工号删除员工信息"); System.out.println("* 4 根据工号修改员工信息"); System.out.println("* 5 增加员工信息"); System.out.println("* 6 增加部门信息"); System.out.println("* 7 退出"); System.out.println("************************************"); } }
|
测试结果
封装BaseDao
目的:处理大量的重复代码
BaseDAO代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| package com.excepenxi.dao;
import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List;
public abstract class BaseDao { private static String driver ="com.mysql.cj.jdbc.Driver"; private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; private static String user="root"; private static String password="root";
public int baseUpdate(String sql,Object ... args){ Connection connection = null; PreparedStatement preparedStatement=null; int rows=0; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password);
preparedStatement = connection.prepareStatement(sql); for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1, args[i]); } rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return rows; }
public List baseQuery(Class clazz, String sql, Object ... args) { Connection connection = null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; List list =null; try{ Class.forName(driver); connection = DriverManager.getConnection(url, user,password); preparedStatement = connection.prepareStatement(sql); for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1, args[i]); } resultSet = preparedStatement.executeQuery(); list=new ArrayList() ; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); } while(resultSet.next()){ Object obj = clazz.newInstance(); for (Field field : fields) { String fieldName = field.getName(); Object data = resultSet.getObject(fieldName); field.set(obj,data); } list.add(obj); } }catch (Exception e){ e.printStackTrace(); }finally { if(null != resultSet){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != connection){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } }
|
实现类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.BaseDao; import com.excepenxi.dao.EmpDao; import com.excepenxi.pojo.Emp;
import java.sql.*; import java.util.ArrayList; import java.util.List;
public class EmpDaoImpl extends BaseDao implements EmpDao {
@Override public int addEmp(Emp emp) { String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)"; return baseUpdate(sql,emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()); }
@Override public int deleteByEmpno(int empno) { String sql="delete from emp where empno =?"; return baseUpdate(sql,empno); }
@Override public List<Emp> findAll() { String sql="select * from emp"; return baseQuery(Emp.class,sql); }
@Override public int updateEmp(Emp emp) { String sql="update emp set ename =? ,job=?, mgr =?,hiredate =?,sal=?,comm=?,deptno=? where empno =?"; return baseUpdate(sql,emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.excepenxi.dao.impl;
import com.excepenxi.dao.BaseDao; import com.excepenxi.dao.DeptDao; import com.excepenxi.pojo.Dept; import com.excepenxi.pojo.Emp;
import java.sql.*; import java.util.ArrayList; import java.util.List;
public class DeptDaolmpl extends BaseDao implements DeptDao {
@Override public List<Dept> findAll() { String sql="select * from dept"; return baseQuery(Dept.class,sql); }
@Override public int addDept(Dept dept) { String sql="insert into dept values(?,?,?)"; return baseUpdate(sql,dept.getDeptno(),dept.getDname(),dept.getLoc()); } }
|
运行测试
连接池(性能优化)
连接池介绍
传统连接方式
首先调用Class.forName()方法加载数据库驱动,然后调用DriverManager.getConnection()方法建立连接.
连接池方式
连接池解决方案是在应用程序启动时就预先建立多个数据库连接对象,然后将连接对象保存到连接池中。当客户请求到来时,从池中取出一个连接对象为客户服务。当请求完成时,客户程序调用close()方法,将连接对象放回池中.对于多于连接池中连接数的请求,排队等待。应用程序还可根据连接池中连接的使用率,动态增加或减少池中的连接数。
传统方式存在问题
Connection对象在每次执行DML和DQL的过程中都要创建一次,DML和DQL执行完毕后,connection对象都会被销毁. connection对象是可以反复使用的,没有必要每次都创建新的.该对象的创建和销毁都是比较消耗系统资源的,如何实现connection对象的反复使用呢?使用连接池技术实现.
连接池的优势
1预先准备一些链接对象,放入连接池中,当多个线程并发执行时,可以避免短时间内一次性大量创建链接对象,减少计算机单位时间内的运算压力,提高程序的响应速度
2实现链接对象的反复使用,可以大大减少链接对象的创建次数,减少资源的消耗
具体实现如下
连接池代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| package com.excepenxi.dao;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.LinkedList;
public class MyConnectionPool { private static String driver ="com.mysql.cj.jdbc.Driver"; private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; private static String user="root"; private static String password="root"; private static int initSize=1; private static int maxSize=1;
private static LinkedList<Connection> pool;
static{ try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } pool=new LinkedList<Connection>(); for (int i = 0; i <initSize ; i++) { Connection connection = initConnection(); if(null != connection){ pool.add(connection); System.out.println("初始化连接"+connection.hashCode()+"放入连接池"); } } }
private static Connection initConnection(){ try { return DriverManager.getConnection(url,user,password); } catch (SQLException e) { e.printStackTrace(); } return null; }
public static Connection getConnection(){ Connection connection =null; if(pool.size()>0){ connection= pool.removeFirst(); System.out.println("连接池中还有连接:"+connection.hashCode()); }else{ connection = initConnection(); System.out.println("连接池空,创建新连接:"+connection.hashCode()); } return connection; }
public static void returnConnection(Connection connection){ if(null != connection){ try { if(!connection.isClosed()){ if(pool.size()<maxSize){ try { connection.setAutoCommit(true); System.out.println("设置连接:"+connection.hashCode()+"自动提交为true"); } catch (SQLException e) { e.printStackTrace(); } pool.addLast(connection); System.out.println("连接池未满,归还连接:"+connection.hashCode()); }else{ try { connection.close(); System.out.println("连接池满了,关闭连接:"+connection.hashCode()); } catch (SQLException e) { e.printStackTrace(); } } }else{ System.out.println("连接:"+connection.hashCode()+"已经关闭,无需归还"); } } catch (SQLException e) { e.printStackTrace(); } }else{ System.out.println("传入的连接为null,不可归还"); } } }
|
BaseDao代码修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| package com.excepenxi.dao;
import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List;
public abstract class BaseDao {
public int baseUpdate(String sql,Object ... args){ Connection connection = null; PreparedStatement preparedStatement=null; int rows=0;
try{ connection = MyConnectionPool.getConnection();
preparedStatement = connection.prepareStatement(sql); for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1, args[i]); } rows =preparedStatement.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } MyConnectionPool.returnConnection(connection); } return rows; }
public List baseQuery(Class clazz, String sql, Object ... args) { Connection connection = null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; List list =null; try{ connection = MyConnectionPool.getConnection(); preparedStatement = connection.prepareStatement(sql); for (int i = 0; i <args.length ; i++) { preparedStatement.setObject(i+1, args[i]); } resultSet = preparedStatement.executeQuery(); list=new ArrayList() ; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); } while(resultSet.next()){ Object obj = clazz.newInstance(); for (Field field : fields) { String fieldName = field.getName(); Object data = resultSet.getObject(fieldName); field.set(obj,data); } list.add(obj); } }catch (Exception e){ e.printStackTrace(); }finally { if(null != resultSet){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null != preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } MyConnectionPool.returnConnection(connection); } return list; } }
|
运行测试
Test1、EmpManageSystem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.excepenxi.test1;
import com.excepenxi.dao.MyConnectionPool; import java.sql.Connection;
public class Test1 { public static void main(String[] args) { Connection connection1 = MyConnectionPool.getConnection(); Connection connection2 = MyConnectionPool.getConnection(); Connection connection3 = MyConnectionPool.getConnection();
MyConnectionPool.returnConnection(connection1); MyConnectionPool.returnConnection(connection2); MyConnectionPool.returnConnection(connection3); } }
|
连接池(优化参数)
配置文件优化连接池参数存储
1 2 3 4 5 6 7 8 9
| driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true user=root password=root
initSize=1
maxSize=1
|
优化连接池代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| package com.excepenxi.dao;
import com.excepenxi.util.PropertiesUtil;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.LinkedList;
public class MyConnectionPool { private static String driver; private static String url; private static String user; private static String password; private static int initSize; private static int maxSize;
private static LinkedList<Connection> pool;
static{ PropertiesUtil propertiesUtil=new PropertiesUtil("/jdbc.properties"); driver=propertiesUtil.getProperties("driver"); url=propertiesUtil.getProperties("url"); user=propertiesUtil.getProperties("user"); password=propertiesUtil.getProperties("password"); initSize=Integer.parseInt(propertiesUtil.getProperties("initSize")); maxSize=Integer.parseInt(propertiesUtil.getProperties("maxSize"));
try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } pool=new LinkedList<Connection>(); for (int i = 0; i <initSize ; i++) { Connection connection = initConnection(); if(null != connection){ pool.add(connection); System.out.println("初始化连接"+connection.hashCode()+"放入连接池"); } } }
private static Connection initConnection(){ try { return DriverManager.getConnection(url,user,password); } catch (SQLException e) { e.printStackTrace(); } return null; }
public static Connection getConnection(){ Connection connection =null; if(pool.size()>0){ connection= pool.removeFirst(); System.out.println("连接池中还有连接:"+connection.hashCode()); }else{ connection = initConnection(); System.out.println("连接池空,创建新连接:"+connection.hashCode()); } return connection; }
public static void returnConnection(Connection connection){ if(null != connection){ try { if(!connection.isClosed()){ if(pool.size()<maxSize){ try { connection.setAutoCommit(true); System.out.println("设置连接:"+connection.hashCode()+"自动提交为true"); } catch (SQLException e) { e.printStackTrace(); } pool.addLast(connection); System.out.println("连接池未满,归还连接:"+connection.hashCode()); }else{ try { connection.close(); System.out.println("连接池满了,关闭连接:"+connection.hashCode()); } catch (SQLException e) { e.printStackTrace(); } } }else{ System.out.println("连接:"+connection.hashCode()+"已经关闭,无需归还"); } } catch (SQLException e) { e.printStackTrace(); } }else{ System.out.println("传入的连接为null,不可归还"); } } }
|
工具类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.excepenxi.util;
import java.io.IOException; import java.io.InputStream; import java.util.Properties;
public class PropertiesUtil { private Properties properties;
public PropertiesUtil(String path){ properties=new Properties(); InputStream inputStream = this.getClass().getResourceAsStream(path); try { properties.load(inputStream); } catch (IOException e) { e.printStackTrace(); } }
public String getProperties(String key){ return properties.getProperty(key); } }
|
运行测试
Test2、EmpManageSystem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.excepenxi.test1;
import java.io.IOException; import java.io.InputStream; import java.util.Properties;
public class Test2 { public static void main(String[] args) { Properties properties=new Properties(); InputStream inputStream = Test2.class.getResourceAsStream("/jdbc.properties"); try { properties.load(inputStream); } catch (IOException e) { e.printStackTrace(); } String property = properties.getProperty("driver"); System.out.println(property); } }
|
log4j日志框架
理论
如何记录日志
方式1:System.out.println(…..) e.printStackTrace();
缺点:不是保存到文件,不能长久存储
方式2:IO流 将System.out.println(…..) e.printStackTrace();写入文件
缺点:操作繁琐,IO流操作容易阻塞线程,日志没有等级,日志的格式不能很好的定制,要想实行编程复杂
方式3:使用现成的日志框架,比如log4j
优点:1 长久保存;2 有等级;3 格式可以很好的定制;4 代码编写简单
log4j日志的级别
FATAL: 指出现非常严重的错误事件,这些错误可能导致应用程序异常中止
ERROR: 指虽有错误,但仍允许应用程序继续运行
WARN: 指运行环境潜藏着危害
INFO: 指报告信息,这些信息在粗粒度级别上突出显示应用程序的进程
DEBUG: 指细粒度信息事件,对于应用程序的调试是最有用的
理解日志格式化字符的含义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| %p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如
test.TestLog4j.main(TestLog4j.java:10)。 %c:输出日志信息所属的类目,通常就是所在类的全名。 %M:输出产生日志信息的方法名。 %F:输出日志消息产生时所在的文件名称。 %L::输出代码中的行号。 %m::输出代码中指定的具体日志信息。 %n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。 %x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。 %%:输出一个"%"字符。
|
使用log4j记录日志
加入jar包 log4j-1.2.8.jar
加入属性文件 src 下 log4j.properties
- log4j.rootLogger=日志级别(debug),控制台输出(stdout),输出文件(logfile)
1 2 3 4 5 6 7 8 9 10
| log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=d:/excepenxi.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %F %p %m%n
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.excepenxi.test1;
import org.apache.log4j.Logger;
public class TestLog4j { public static void main(String[] args) { Logger logger = Logger.getLogger(TestLog4j.class);
logger.fatal("fatal message"); logger.error("error message"); logger.warn("warn message"); logger.info("info message"); logger.debug("debug message");
try { int i = 1/0; } catch (Exception e) { logger.warn("程序捕获到了异常",e); } } }
|
- 代码中记录日志
1 2 3 4 5 6 7
| private static final Logger logger = Logger.getLogger(DBUtil.class.getName());
logger.info("正确的读取了属性文件:"+prop); logger.debug("正确的关闭了结果集"); logger.error("DML操作错误:"+e);
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| package com.excepenxi.dao;
import com.excepenxi.util.PropertiesUtil; import org.apache.log4j.Logger;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.LinkedList;
public class MyConnectionPool { private static String driver; private static String url; private static String user; private static String password; private static int initSize; private static int maxSize; private static Logger logger; private static LinkedList<Connection> pool;
static{ logger=Logger.getLogger(MyConnectionPool.class); PropertiesUtil propertiesUtil=new PropertiesUtil("/jdbc.properties"); driver=propertiesUtil.getProperties("driver"); url=propertiesUtil.getProperties("url"); user=propertiesUtil.getProperties("user"); password=propertiesUtil.getProperties("password"); initSize=Integer.parseInt(propertiesUtil.getProperties("initSize")); maxSize=Integer.parseInt(propertiesUtil.getProperties("maxSize"));
try { Class.forName(driver); } catch (ClassNotFoundException e) { logger.fatal("找不到数据库驱动类"+driver,e); } pool=new LinkedList<Connection>(); for (int i = 0; i <initSize ; i++) { Connection connection = initConnection(); if(null != connection){ pool.add(connection); logger.info("初始化连接"+connection.hashCode()+"放入连接池"); } } }
private static Connection initConnection(){ try { return DriverManager.getConnection(url,user,password); } catch (SQLException e) { logger.fatal("初始化连接异常",e); } return null; }
public static Connection getConnection(){ Connection connection =null; if(pool.size()>0){ connection= pool.removeFirst(); logger.info("连接池中还有连接:"+connection.hashCode()); }else{ connection = initConnection(); logger.info("连接池空,创建新连接:"+connection.hashCode()); } return connection; }
public static void returnConnection(Connection connection){ if(null != connection){ try { if(!connection.isClosed()){ if(pool.size()<maxSize){ try { connection.setAutoCommit(true); logger.debug("设置连接:"+connection.hashCode()+"自动提交为true"); } catch (SQLException e) { e.printStackTrace(); } pool.addLast(connection); logger.info("连接池未满,归还连接:"+connection.hashCode()); }else{ try { connection.close(); logger.info("连接池满了,关闭连接:"+connection.hashCode()); } catch (SQLException e) { e.printStackTrace(); } } }else{ logger.info("连接:"+connection.hashCode()+"已经关闭,无需归还"); } } catch (SQLException e) { e.printStackTrace(); } }else{ logger.warn("传入的连接为null,不可归还"); } } }
|
三大范式
介绍
必须保证数据库设计的合理性,对数据库设计总结的一些经验性的规范,称之为范式(NF= NormalForm)
数据库设计关系整个系统的架构,关系到后续开发效率和运行效率
数据库的设计主要包含了设计表结构和表之间的联系
如何是合理数据库
结构合理
冗余较小
尽量避免插入删除修改异常
如何才能保证数据库设计水平
遵循一定的规则
在关系型数据库中这种规则就称为范式
什么是范式(NF= NormalForm)
范式是符合某一种设计要求的总结。
要想设计一个结构合理的关系型数据库,必须满足一定的范式。
范式分类
第一范式:列原子性
第二范式:数据和联合主键完全相关性
第三范式:数据和主键直接相关性
- Boyce Codd范式=BCNF
- 由Boyce和Codd提出的
- 比3NF又进了一步
- 通常认为是修正的第三范式
第四范式
第五范式
各个范式是依次嵌套包含的;范式越高,设计质量越高,在现实设计中也越难实现
一般数据库设计,只要达到第三范式,即可避免异常的出现
第一范式
要求
第二范式
要求
第三范式
要求
范式总结
优点
缺点
数据库的设计应该根据当前情况和需求做出灵活的处理。
示例
- 比如经常购物车条目的中除了条目编号,商品编号,商品数量外,可以增加经常使用的商品名称,商品价格等
数据库之间的三大关系
- 多对多
- A表中对应B表中多条数据,同样B表中对应A表中多条数据
- 多对多需要通过中间表体现关系
- 中间表讲多对多的关系转变成两个一对多