2.4 JDBC应用

喜夏-厌秋 提交于 2019-12-28 04:13:29

本文是课上资料的总结非原创没有转载地址

JDBC应用

回顾

1 JDBC介绍 :

	Java Database Connectity java数据库连接技术

	定义一套连接数据库的规范和标准。

2 JDBC包含两个部分

	JDBC API 包括 DriverManger  Driver  Connection  Statement   ResultSet   SQLException 

	JDBC 驱动程序  MySQL驱动程序   不同数据库厂商有不同的驱动程序

3 JDBC的使用步骤

	1 导入驱动包  项目根目录下创建文件夹--->lib-->把数据库驱动文件jar包放在里面-->右键lib文件夹-->add as library

	2 注册驱动    Class.forName();

	3 获取连接   jdbc:mysql://localhost:3306/myschool   root  root

	4 创建命令   statement
 
	5 执行命令,处理结果   boolean execute(String sql); int executeUpdate(String sql); 
	ResultSet executeQuery(String sql)

	6 释放资源  close. 按依赖顺序关闭!rs   st   conn

4 JDBC的api  

	Driver  驱动

	DriverManager 驱动管理类

    Connection 负责连接数据库

	Statement  负责执行命令

	ResultSet   封装结果集

	PreparedStatment 预编译命令 

今日内容

1、封装工具类
2、ORM封装
3、DAO模式
4、Druid连接池

第一节 封装工具类

DbUtils类功能:1 注册驱动 2 获取连接 3释放资源

1.1重用性方案:

/**
 * 1 注册驱动
 * 2 获取连接
 * 3 释放资源
 * @author gq
 *
 */
public class DbUtils {
	
	//驱动名称
	static String driver="com.mysql.jdbc.Driver";
	//url连接字符串
	static String url="jdbc:mysql://localhost:3306/school";
	//用户名
	static String user="root";
	//密码
	static String password="root";
	static {
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			System.out.println("注册驱动失败");
		}
		
	}
	/**
	 * 获取连接
	 * @return
	 */
	public static Connection getConnection() {
		try {
			return DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 释放资源
	 * @param rs
	 * @param stat
	 * @param conn
	 */
	public static void closeAll(ResultSet resultSet,Statement stat,Connection connection) {
		 try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (stat != null) {
                    stat.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
	}
}

1.2跨平台方案:

db.properties配置文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb3
user=root
password=1234

DBUtils类

/**
 * 数据库相关的封装   获取连接  关闭连接 
 */
public class DbUtils {
    //1.声明属性。
    private static String driver;
    private static String url;
    private static String user;
    private static String password;

    static {
        try {
            //通过类加载器,加载资源(配置文件)!
            InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            //通过load方法,将配置文件资源加载到集合里
            properties.load(is);
            //获取集合里的键。对应的值是数据库连接的内容
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
			//注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //3.获取数据库连接对象的方法
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //4.关闭所有连接
    public static void closeAll(ResultSet rs, Statement st, Connection conn) {
        try {
            if (rs != null) {
                rs.close();
            }
            if (st != null) {
                st.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

第二节 ResultSet查询封装

ORM(Object Relational Mapping)实体类(Entity):零散数据的载体。

在应用开发中,我们从数据库查询出的结果集(ResultSet)一般都需要取得(get)其中的数据然后存放到(set)实体对象(Entity)中,以便进一步的处理需要。常用也最容易理解的方式就是从ResultSet中get相应的字段值后调用实体对象的对应的属性的set方法,把值保存在实体对象中。

实体类:

package com.qf.www.entity;

import java.util.Date;

public class Emp {
    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 Emp() {
    }

    public Emp(int empno, String ename, String job, int mgr, Date hiredate, double sal, double comm, int 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;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", 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;
    }
}

//根据员工编号查询单个员工,查到就封装成对象,返回 
public Emp getEmpByEmpNo(int empno) { 		
		connection = DbUtils.getConnection();
        String sql = "select * from emp where empno = ?";
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, empno);
            resultSet = preparedStatement.executeQuery();
            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);
                return emp;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeAll(resultSet, preparedStatement, connection);
        }
        return null;
 }

总结:

  1. 将一行中多个零散数据进行整理。
  2. 通过Entity的规则将表中的数据进行对象的封装。
  3. 表名=类名;列名=属性名;提供各属性的get、set方法。
  4. 提供无参构造方法(视情况添加有参构造方法)。

第三节 DAO模式

3.1 工具类封装

案例实现:实现emp表的查询、添加、删除、修改

3.1.1 封装DbUtils

  • 由于多个地方都需要使用数据库连接和释放,所以把功能封装到工具类中DbUtils

  • 四个功能:1注册驱动 2 获取连接 3 释放资源

public class DbUtils {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;

	static{
	
		try {			
			driver="com.mysql.jdbc.Driver";
          	 url="jdbc:mysql://localhost:3306/mydb1";
          	 user="root";
          	 password="1234";
			//加载驱动
			Class.forName(driver);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	/**
	 * 获取连接
	 * @return
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url,user,password);
	}
	
	/**
	 * 释放资源
	 * @param rs
	 * @param stat
	 * @param conn
	 */
	public static void release(ResultSet resultSet,Statement stat,Connection conn){
		try {
             if (resultSet != null) {
                 resultSet.close();
             }
             if (statement != null) {
                 statement.close();
             }
             if (connection != null) {
                 connection.close();
             }
         } catch (SQLException e) {
             e.printStackTrace();
         }
	}
}

1.1.2优化DbUtils工具类:把数据库连接信息封装到Properties文件中

项目下创建的db.properties error方式

src下创建db.properties could not initialize class com.qf.www.dbutils

	Properties properties=new Properties();
	InputStream is=DbUtils.class.getClassLoader().getResourceAsStream("database.properties");
	properties.load(is);
	//初始化参数
	driver=properties.getProperty("driver");
	url=properties.getProperty("url");
	user=properties.getProperty("user");
	password=properties.getProperty("password");

3.2 DAO设计模式

DAO(Database Access Object 数据库访问对象)

为了降低耦合性,提出了DAO封装数据库操作的设计模式。

它可以实现业务逻辑与数据库访问相分离。相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口,隔离了不同的数据库实现。

DAO模式的组成部分

  1. DAO接口(主要包含 添加 修改 查询 删除方法)
  2. DAO实现类
  3. 实体类 (domain、beans、entity、pojo、model)
    • 作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据
    • 实体类特征:
      • 属性一般使用private修饰
      • 提供public修饰的getter/setter方法
      • 实体类提供无参构造方法,根据业务提供有参构造
      • 实现java.io.Serializable接口,支持序列化机制
  4. 数据库连接和关闭工具类

设计的包名 :
entity、存放实体类
utils 存放工具类
dao 存放接口
dao.impl 存放实现类

使用DAO设计模式实现emp表的查询、添加、删除、修改

Employee类

/**
 * 员工类
 * 实体类
 * @author wgy
 *
 */
public class Emp 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 Emp() {
		// TODO Auto-generated constructor stub
	}

	public Emp(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 + "]";
	}
	
}

接口:

public interface EmpDao {
	
	 //1查询
	 List<Emp> findAll();
	 //2更新
	 void update(Emp e);
	 //3删除
	 void delete(int empno);
	 //4添加
	 void add(Emp e);
	 
	
}

实现类

public class EmpDaoImpl implements EmpDao{
		Connection conn=null;
		PreparedStatement pstat=null;
		ResultSet rs=null;
	@Override
	public List<Emp> findAll() {
		ArrayList<Emp> emps=new ArrayList<Emp>();
		//1获取连接
		
		try {
			conn=DbUtils.getConnection();
			pstat=conn.prepareStatement("select * from emp;");
			rs=pstat.executeQuery();
			while(rs.next()){
				int empno=rs.getInt("empno");
				String ename=rs.getString("ename");
				String job=rs.getString("job");
				int mgr=rs.getInt("mgr");
				Date date=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, date, sal, comm, deptno);
				emps.add(emp);
			}
			return emps;
		} catch (Exception e) {
			throw new RuntimeException("查询emp失败");
		} finally {
			DbUtils.closeAll(rs, pstat, conn);
		}
		
	}

	@Override
	public void update(Emp emp) {
		conn=DbUtils.getConnection();
        String sql = "update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno = ?";
        try {
        	pstat = conn.prepareStatement(sql);
            pstat.setObject(1,emp.getEname());
            pstat.setObject(2,emp.getJob());
            pstat.setObject(3,emp.getMgr());
            pstat.setObject(4,emp.getHiredate());
            pstat.setObject(5,emp.getSal());
            pstat.setObject(6,emp.emp.getComm());
            pstat.setObject(7,emp.getDeptno());
            pstat.setObject(8,emp.getEmpno());
            pstat.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException("修改emp失败");
        }finally {
			DbUtils.closeAll(rs, pstat, conn);
		}
	}

	@Override
	public void delete(int empno) {
		conn=DbUtils.getConnection();
        String sql = "delete from emp where empno = ?";
        try {
        	pstat = conn.prepareStatement(sql);
            pstat.setObject(1,empno);
            pstat.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException("删除emp失败");
        }finally {
			DbUtils.closeAll(rs, pstat, conn);
		}
	}

	@Override
	public void add(Emp emp) {
		conn=DbUtils.getConnection();
        String sql = "insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(?,?,?,?,?,?,?,?)";
        try {
        	pstat = conn.prepareStatement(sql);
            pstat.setObject(1,emp.getEmpno());
            pstat.setObject(2,emp.getEname());
            pstat.setObject(3,emp.getJob());
            pstat.setObject(4,emp.getMgr());
            pstat.setObject(5,emp.getHiredate());
            pstat.setObject(6,emp.getSal());
            pstat.setObject(7,emp.emp.getComm());
            pstat.setObject(8,emp.getDeptno());
            pstat.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException("新增emp失败");
        }finally {
			DbUtils.closeAll(rs, pstat, conn);
		}
	}
}

第四节 Druid连接池

4.1为什么使用连接池

  • 数据库连接池的发展
用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、宕机。
现流行的有:DBCP、C3P0、Druid等
  • Druid特点
Druid 是目前比较流行的高性能的,分布式列存储的OLAP框架(具体来说是MOLAP)。它有如下几个特点:
一. 亚秒级查询
     druid提供了快速的聚合能力以及亚秒级的OLAP查询能力,多租户的设计,是面向用户分析应用的理想方式。
二.实时数据注入
     druid支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性
三.可扩展的PB级存储
     druid集群可以很方便的扩容到PB的数据量,每秒百万级别的数据注入。即便在加大数据规模的情况下,也能保证时其效性
四.多环境部署
     druid既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括hadoop,spark,kafka,storm和samza等
五.丰富的社区
     druid拥有丰富的社区,供大家学习

4.2 使用步骤

  • 配置文件 database.properties:
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/school
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
maxWait=5000

4.2.1 导入jar包

​ druid-1.1.5.jar

​ mysql驱动包

4.2.2 编写工具类

 /**
 * 阿里的数据库连接池
 * 性能最好的
 * Druid
 * */
public class DbUtils {
	//声明连接池对象
	private static DruidDataSource ds;
	static{
		
		//实例化配置对象
		Properties properties=new Properties();
		try {
			//加载配置文件内容
              properties.load(DbUtils.class.getResourceAsStream("database.properties"));
              ds = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);	
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//获取连接对象
	public static Connection getConnection() {
		try {
			return ds.getConnection();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}	
}

4.2.3 测试

package com.qf.utils;

import java.sql.Connection;

public class Test {
	public static void main(String[] args) throws Exception {
		for(int i=0;i<100;i++) {
			Connection connection=DbUtils.getConnection();
			if(connection!=null) {
				System.out.println("连接成功"+i+"..."+connection.hashCode()+connection.toString());
			}
			connection.close();
		}
	}
}

作业题

1、实现一个学生管理系统,要求实现增删改查,基于控制台实现即可
	要求可以对学生信息进行添加、修改、删除、查询的功能

面试题

1、什么是JDBC,在什么时候会用到它?
2、execute,executeQuery,executeUpdate的区别是什么?
3、JDBC的PreparedStatement是什么?
4、相对于Statement,PreparedStatement的优点是什么?
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!