第一节 工具类封装、DAO模式和自定义连接池
1.1 工具类封装
案例实现:实现emp表的查询、添加、删除、修改
1.1.1 封装DbUtils
由于多个地方都需要使用数据库连接和释放,所以把功能封装到工具类中DbUtils
四个功能:1注册驱动 2 获取连接 3 释放资源 4 执行命令 【5 执行查询】
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/school";
// 数据库MySQL8.0使用:jdbc:mysql://localhost:3306/mydb2? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT
user="root";
password="root";
//加载驱动
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 rs,Statement stat,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 根据参数执行sql语句 Insert Delete Update
* @param sql
* @param params
* @return
*/
public static int executeUpdate(String sql, Object...params){
Connection conn=null;
PreparedStatement pstat=null;
try {
//1创建连接
conn=getConnection();
//2创建命令对象
pstat=conn.prepareStatement(sql);
//3设置参数
for (int i = 0; i < params.length; i++) {
pstat.setObject(i+1, params[i]);
}
//4执行
int result=pstat.executeUpdate();
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
release(null, pstat, conn);
}
}
}
1.1.2优化DbUtils工具类:把数据库连接信息封装到Properties文件中
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");
部分改动代码:
public class DbUtils {
private static String driver;
private static String url;
private static String user;
private static String password;
static{
// driver="com.mysql.jdbc.Driver";
// url="jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8";
// user="root";
// password="root";
//注册驱动
try {
//读取文件1
// Properties properties=new Properties();
// FileInputStream fis=new FileInputStream("src\\db.properties");
// properties.load(fis);
// fis.close();
//读取文件2 使用类加载器 加载配置文件
Properties properties=new Properties();
InputStream is= DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
properties.load(is);
is.close();
driver=properties.getProperty("driver");
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
System.out.println("注册驱动失败");
}
}
public static Connection getConnection(){
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
1.2 DAO设计模式
DAO(Database Access Object 数据库访问对象)
为了降低耦合性,提出了DAO封装数据库操作的设计模式。
它可以实现业务逻辑与数据库访问相分离。相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口,隔离了不同的数据库实现。
DAO模式的组成部分
1 DAO接口(主要包 添加 修改 查询 删除方法)
2 DAO实现类
3 实体类 (domain(领域)、beans、entity、pojo、model)
PO (VO)(Persistent Object, Value Object)
VO (View Object)
DTO (Data Transfer Object)
--作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据
--实体类特征:
◦属性一般使用private修饰
◦提供public修饰的getter/setter方法
◦实体类提供无参构造方法,根据业务提供有参构造
◦实现java.io.Serializable接口,支持序列化机制
4 数据库连接和关闭工具类
设计的包名 :
domain 存放实体类
utils 存放工具类
dao 存放接口
dao.impl 存放实现类
使用DAO设计模式实现emp表的查询、添加、删除、修改
Emp类
package com12.qf0827.Demo2.domain;
import java.io.Serializable;
import java.util.Date;
/**
* 2019/8/2720:19
* <p>
* 未知的事情 永远充满变数
*/
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() {
}
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;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
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 "Emp{" +
"empno=" + empno +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", mgr=" + mgr +
", hiredate=" + hiredate +
", sal=" + sal +
", comm=" + comm +
", deptno=" + deptno +
'}';
}
}
DbUtils工具类别:
package com.qf.utils;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/*
* 2019/8/26 14:28
*/
/*四个功能
* (1)注册驱动(一次)
* (2)获取连接
* (3)释放资源
* (4)执行SQL (增删改)
*
* */
public class DbUtils {
private static String driver;
private static String url;
private static String user;
private static String password;
static{
// driver="com.mysql.jdbc.Driver";
// url="jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8";
// user="root";
// password="root";
//注册驱动
try {
//读取文件1
// Properties properties=new Properties();
// FileInputStream fis=new FileInputStream("src\\db.properties");
// properties.load(fis);
// fis.close();
//读取文件2 使用类加载器 加载配置文件
Properties properties=new Properties();
InputStream is= DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
properties.load(is);
is.close();
driver=properties.getProperty("driver");
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
System.out.println("注册驱动失败");
}
}
public static Connection getConnection(){
try {
return DriverManager.getConnection(url, user, password);
} 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();
}
}
public static int executeUpdate(String sql,Object...params){ //insert update delete ?????
Connection conn =null;
PreparedStatement pstat=null;
try {
conn = getConnection();
pstat = conn.prepareStatement(sql);
//设置参数
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstat.setObject(i+1, params[i]);
}
}
return pstat.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(conn, pstat, null);
}
return -1;
}
//返回List集合的方法
public static <T> List<T> findList(String sql, Class<T> class1,Object... params){
List<T> list=new ArrayList<>();
Connection conn=null;
PreparedStatement pstat=null;
ResultSet rs=null;
//查询数据
try {
conn=getConnection();
pstat = conn.prepareStatement(sql);
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstat.setObject(i+1, params[i]);
}
}
rs = pstat.executeQuery();
//获取rs中的列名
ResultSetMetaData metaData = rs.getMetaData();
while(rs.next()){
//创建一个对象
T t=convertToObject(metaData, rs, class1);
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
closeAll(conn, pstat, rs);
}
return list;
}
//返回单个对象的方法
public static <T> T findSingle(String sql,Class<T> class1,Object...params ){
Connection conn=null;
PreparedStatement pstat=null;
ResultSet rs=null;
//查询数据
try {
conn=getConnection();
pstat = conn.prepareStatement(sql);
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstat.setObject(i+1, params[i]);
}
}
rs = pstat.executeQuery();
//获取rs中的列名
ResultSetMetaData metaData = rs.getMetaData();
if(rs.next()){
//创建一个对象
return convertToObject(metaData, rs, class1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
closeAll(conn, pstat, rs);
}
return null;
}
public static <T> T convertToObject(ResultSetMetaData metaData,ResultSet rs,Class<T> class1){
try {
T t=class1.newInstance();
for(int i=0;i<metaData.getColumnCount();i++){
String columnLabel=metaData.getColumnLabel(i+1);
Object value = rs.getObject(columnLabel);//empno ename job
//System.out.println(columnLabel+"==="+value);
//创建属性描述符
try {
PropertyDescriptor pd=new PropertyDescriptor(columnLabel, class1);
if(pd!=null){
//System.out.println(pd.getName());
Method writeMethod = pd.getWriteMethod(); //setEmpno setEname setJob
writeMethod.invoke(t,value);
}
} catch (Exception e) {
continue;
}
}
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
db.properties 文件内容:
#驱动
driver=com.mysql.cj.jdbc.Driver
#连接字符串
url=jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT
#用户名
user=root
#密码
password=root
接口:。
package com12.qf0827.Demo2.dao;
import com12.qf0827.Demo2.domain.Emp;
import java.util.List;
/**
* 2019/8/2720:27
* <p>
* 未知的事情 永远充满变数
*/
//接口
public interface EmployeeDao {
//查询
List<Emp>findAll();
//更新
void update(Emp e);
//删除
void delete(int empno);
//添加
void add(Emp e);
}
实现类
package com12.qf0827.Demo2.dao.impl;
import com12.qf0827.Demo2.dao.EmployeeDao;
import com12.qf0827.Demo2.domain.Emp;
import com12.qf0827.Demo2.utils.DbUtils;
import java.util.List;
/**
* 2019/8/2720:37
* <p>
* 未知的事情 永远充满变数
*/
public class EmployeeDaoImpl implements EmployeeDao {
@Override
public List<Emp> findAll() {
ArrayList<Employee> employees=new ArrayList<Employee>();
//1获取连接
Connection conn=null;
PreparedStatement pstat=null;
ResultSet rs=null;
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");
Employee employee=new Employee(empno, ename, job, mgr, date, sal, comm, deptno);
employees.add(employee);
}
return employees;
} catch (Exception e) {
throw new RuntimeException("查询emp失败");
} finally {
DbUtils.closeAll(rs, pstat, conn);
}
}
@Override //更新
public void update(Emp e) {
Object[] params={e.getEname(),e.getJob(),e.getMgr(),e.getHiredate(),e.getSal(),e.getComm(),e.getDeptno(),e.getEmpno()};
DbUtils.executeUpd("update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno=?",params);
}
@Override
public void delete(int empno) {
DbUtils.executeUpd("delete from emp where empno=?",empno);
}
@Override
public void add(Emp e) {
Object [] params = {e.getEmpno(),e.getEname(),e.getJob(),e.getMgr(),e.getHiredate(),e.getSal(),e.getComm(),e.getDeptno()};
DbUtils.executeUpd("insert into emp values(?,?,?,?,?,?,?,?)",params);
}
}
测试类:
package com12.qf0827.Demo2;
import com12.qf0827.Demo2.dao.impl.EmployeeDaoImpl;
import com12.qf0827.Demo2.domain.Emp;
import org.junit.Test;
import java.util.Date;
/**
* 2019/8/2720:16
* <p>
* 未知的事情 永远充满变数
*/
public class test {
EmployeeDaoImpl empDao=new EmployeeDaoImpl();
@Test
public void testAdd(){
Emp emp=new Emp(77232,"hello" ,"java开发" ,6666 ,new Date(),20000.0 ,0.0 ,20 );
empDao.add(emp);
}
@Test
public void testudpate(){
Emp emp=new Emp(7934,"dd" ,"java开发" ,6666 ,new Date(),30000.0 ,0.0 ,20 );
empDao.update(emp);
}
}
1.3 自定义实现连接池
为什么要使用连接池:
用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
Java为连接池实现提供了一个规范(接口),规范的写法,我们需要实现DataSource接口!
package com12.qf0827.连接池.自定义连接池;
import com12.qf0827.Demo2.utils.DbUtils;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
/**
* 2019/8/2722:02
* <p>
* 未知的事情 永远充满变数
*/
public class MyDbpool implements DataSource {
public static List<Connection> connections=null;
static {
connections= Collections.synchronizedList(new LinkedList<Connection>());
for(int i=0;i<5;i++){
Connection connection =DbUtils.getConnection();
connections.add(connection);
}
}
@Override
public Connection getConnection() throws SQLException {
synchronized (connections){
if(connections.size()>0){
Connection connection = connections.remove(0);
System.out.println("获取一个连接池。。"+connection.hashCode());
System.out.println("池中还有"+connections.size());
return connection;
}
}
return null;
}
//把连接池放入池中
public void release(Connection connection){
connections.add(connection);
System.out.println("放入一个连接"+ connection.hashCode());
System.out.println("池中还有"+connections.size());
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
测试:
package com12.qf0827.连接池.自定义连接池;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 2019/8/2721:58
* <p>
* 未知的事情 永远充满变数
*/
public class Test01 {
public static void main(String[] args) {
MyDbpool myDbpool = new MyDbpool();
for (int i = 0; i <10 ; i++) {
try {
Connection conn= myDbpool.getConnection();
if(conn!=null){
System.out.println("获取了:"+conn.hashCode());
}else {
System.out.println("没有获取");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
第二节 DBCP连接池
DBCP(DataBase Connection Pool),[数据库连接池]。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
#####2.1 DBCP连接池的使用
2.1.1 创建项目
创建Java项目
2.1.2 导入相应jar包
mysql驱动包
commons-dbcp.jar
commons-pool.jar
commons-logging.jar 日志支持
2.1.3 硬编码使用DBCP
所谓的硬编码方式就是在代码中添加配置
在DBCP连接池获取连接 在代码中写入连接信息
连接成功后更改表emp的信息sal 为5002.0 然后关闭连接释放资源
代码:
package com.qf.c3p0;
import org.apache.commons.dbcp2.BasicDataSource;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 2019/9/117:57
* <p>
* 未知的事情 永远充满变数
*/
public class Test1 {
@Test
public void demo1() throws Exception{
//TODO 硬编码 使用DBCP连接池子
BasicDataSource source = new BasicDataSource();
//设置连接信息
source.setDriverClassName("com.mysql.cj.jdbc.Driver");
source.setUrl("jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT");
source.setUsername("root");
source.setPassword("root");
Statement stat=null;
Connection connection=null;
try {
connection = source.getConnection();
System.out.println("连接成功!");
stat = connection.createStatement();
int s =stat.executeUpdate("update emp set sal=5002.0 where empno=7369");
System.out.println(s);
} catch (SQLException e) {
e.printStackTrace();
}finally {
stat.close();
connection.close();
}
}
}
2.1.4 软编码使用DBCP
所谓的软编码,就是在项目中添加配置文件,这样就不需要每次代码中添加配合!
- 项目中添加配置
文件名称: dbcp.properties
文件位置: src下
#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT
username=root
password=root
#<!-- 初始化连接-->
initialSize=10
#最大连接数
maxTotal=50
#<!-- 最大空闲连接数-->
maxIdle=20
#<!-- 最小空闲连接-->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒
maxWaitMillis=5000
代码实现
package com.qf.c3p0;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;
/**
* 2019/9/119:07
* <p>
* 未知的事情 永远充满变数
*/
public class Test2 {
// 软编码使用连接池
@Test
public void testSoft()throws Exception{
Properties properties = new Properties();
properties.load(new FileInputStream("src/dbcp.properties"));
//生成连接池子 需要配置文件
//InputStream is = Test2.class.getClassLoader().getResourceAsStream("properties");
DataSource source = BasicDataSourceFactory.createDataSource(properties);
Connection connection = source.getConnection();
Statement stat =connection.createStatement();
int s =stat.executeUpdate("update emp set sal=5003.0 where empno=7369");
System.out.println(s);
stat.close();
connection.close();
}
}
第三节 C3P0连接池
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。
c3p0与dbcp区别
1.
dbcp没有自动回收空闲连接的功能
c3p0有自动回收空闲连接功能
2.
dbcp需要手动加载配置文件
c3p0自动加载
3.1 使用步骤
3.1.1 创建项目
3.1.2 导入jar包
c3p0-0.9.1.2.jar
mchange-commons-java-0.2.11.jar
mysql驱动包
3.1.3.添加配置文件
c3p0是在外部添加配置文件,工具直接进行应用,因为直接引用,所以要求固定的命名和文件位置
文件位置: src
文件命名:c3p0-config.xml/c3p0.properties
<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<!-- 基本配置 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/school</property>
<property name="user">root</property>
<property name="password">root</property>
<!--扩展配置-->
<!-- 连接超过10秒报错-->
<property name="checkoutTimeout">10000</property>
<!--30秒检查空闲连接 -->
<property name="idleConnectionTestPeriod">30</property>
<!-- 初始大小 -->
<property name="initialPoolSize">10</property>
<!-- 每次增长的个数 -->
<property name="acquireIncrement">5</property>
<!-- 30秒不适用丢弃-->
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">50</property>
<property name="minPoolSize">5</property>
</default-config>
<!-- 命名的配置 -->
<named-config name="bj1805">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day2</property>
<property name="user">root</property>
<property name="password">111</property>
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">20</property>
<property name="minPoolSize">10</property>
<property name="maxPoolSize">40</property>
</named-config>
</c3p0-config>
c3p0.properties
c3p0.driverClass=com.mysql.cj.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/mydb2? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT
c3p0.user=root
c3p0.password=root
c3p0.acquireIncrement=5
c3p0.initialPoolSize=20
c3p0.minPoolSize=10
c3p0.maxPoolSize=40
c3p0.checkoutTimeout=5000
1: c3p0的配置文件内部可以包含命名配置文件和默认配置文件!默认是选择默认配置!如果需要切换命名配置可以在创建c3p0连接池的时候填入命名即可!
2:如果xml配置文件和属性文件都存在时,xml优先级高于属性文件
package com.qf.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.Statement;
/**
* 2019/9/122:48
* <p>
* 未知的事情 永远充满变数
*/
public class Test01 {
public static void main(String[] args)throws Exception {
//创建ComboPooledDataSource对象使用默认配置、
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//1创建C3P0连接池子
Connection connection = dataSource.getConnection();
Statement createStatment = connection.createStatement();
int s =createStatment.executeUpdate("update emp set sal=5004.0 where empno=7369");
System.out.println(s);
createStatment.close(); //"update emp set sal=5003.0 where empno=7369"
createStatment.close();
}
}
第四节 Druid连接池
Druid 是目前比较流行的高性能的,分布式列存储的OLAP框架(具体来说是MOLAP)。它有如下几个特点:
一. 亚秒级查询
druid提供了快速的聚合能力以及亚秒级的OLAP查询能力,多租户的设计,是面向用户分析应用的理想方式。
二.实时数据注入
druid支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性
三.可扩展的PB级存储
druid集群可以很方便的扩容到PB的数据量,每秒百万级别的数据注入。即便在加大数据规模的情况下,也能保证时其效性
四.多环境部署
druid既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括hadoop,spark,kafka,storm和samza等
五.丰富的社区
druid拥有丰富的社区,供大家学习
4.1 使用步骤
配置文件 database.properties:
#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:jdbc:mysql://localhost:3306/mydb2? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone = GMT
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=5000
4.1.1 导入jar包
druid-1.1.5.jar
4.1.2 编写工具类
package com.qf.druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* 2019/9/28:42
* <p>
* 未知的事情 永远充满变数
*/
public class TEst01 {
private static DruidDataSource ds;
static{
//实列化配置对象
Properties properties= new Properties();
try {
// properties.load(TEst01.class.getResourceAsStream("database.properties")); 会报空指针异常
properties.load(new FileInputStream("database.properties"));
ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
4.1.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();
}
}
}
第五节 DBUtils使用
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
5.1 DBUtils简介
DBUtils是java编程中的数据库操作实用工具,小巧简单实用,
1.对于数据表的读操作,可以把结果转换成List,Array,Set等java集合,便于程序员操作。
2.对于数据表的写操作,也变得很简单(只需写sql语句)。
DBUtils包括主要类
DbUtils类:启动类
ResultSetHandler接口:转换类型接口
--ArrayHandler类:实现类,把记录转化成数组
--ArrayListHandler类:把记录转化成数组,并放入集合中
--ColumnListHandler类:取某一列的数据。封装到List中。
–ScalarHandler类:适合获取一行一列数据。
–BeanHandler类:实现类,把记录转成对象。
–BeanListHandler类:实现类,把记录转化成List,使记录为JavaBean类型的对象
QueryRunner类:执行SQL语句的类
5.2 DBUtils工具类封装
5.2.1 项目准备
-
创建项目
-
导入jar包 工具类 配置文件
commons-dbutils-1.6.jar
druid-1.1.5.jar
DruidUtils.java工具类
database.properties配置文件(同上)package com.qf.druid; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; /** * 2019/9/218:55 * <p> * 未知的事情 永远充满变数 */ public class DruidUtils { private static DruidDataSource dataSource; static { try { Properties properties = new Properties(); InputStream is =new FileInputStream("database.properties"); properties.load(is); dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } public static DruidDataSource getDataSource(){ return dataSource; } }
package com.qf.DBUtils;
import com.qf.druid.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
/**
-
2019/9/219:00
-
-
未知的事情 永远充满变数
*/
public class ResultHanlder {
@Test
public void testArrayHander()throws SQLException{
//ArrayHandler:适合读取一条记录。把该记录的每列值封装到一个数组OBject中
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
Object[] arr = qr.query(“select * from emp where empno=?”,new ArrayHandler(),7499);
Object[] arr1 = qr.query("select * from emp ",new ArrayHandler());
for (Object o : arr1) {
System.out.println(o);
}}
@Test
public void testArrayListHander() throws Exception{
//ArrayListHandler 适合读取多tiao记录 然后把其封装到集合中
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());List<Object[]> query = qr.query("select * from emp",new ArrayListHandler()); for (Object[] objects : query) { System.out.println(Arrays.toString(objects)); }
}
@Test
public void testColumnListHander()throws Exception{
//ColumnListHandler 取某一列的数据 ,封装到List中
QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());
List qu = runner.query(“select * from emp”,new ColumnListHandler() );
for (Object o : qu) {
System.out.println(o);
}}
@Test
public void testScalarHandler()throws Exception{QueryRunner runner = new QueryRunner(DruidUtils.getDataSource()); Object qery = runner.query("select count(*) from emp", new ScalarHandler<>()); System.out.println(qery); } @Test public void testBeanListHandler() throws SQLException { // BeanHandler:适合取多行多列数据 QueryRunner runner = new QueryRunner(DruidUtils.getDataSource()); List<Employee> query2 = runner.query("select * from emp", new BeanListHandler<Employee>(Employee.class)); for (Employee employee : query2) { System.out.println(employee); } } }
总结
1 封装工具类
2 Dao设计模式: 把数据访问代码抽离出来。降低代码的耦合性和提高扩展性。
dao接口
dao实现
实体类
数据库工具类
3 连接池
dbcp
c3p0
druid重点
4 Dbutils工具