目录

Blob类型

简介:

四种类型

批量插入

数据库连接池

数据库连接池的必要性:

传统模式:

数据库连接池的基本思想

数据库连接池是如何实现的?

 数据库连接池技术的优点:

多种开源的数据库连接池


Blob类型

简介:

在MYSQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,可容纳不同大小的数据

注:插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型数据无法使用字符串拼接

四种类型

类型 大小(单位:字节)

TintBlob 最大255

Blob 最大65K

MediumBlob 最大16M

LongBlob 最大4G

我们可以根据不同的数据类型定义不同的Blob类型。

但是如果存储的文件过大,数据库的性能会下降
如果在指定了相关的blob类型以后,还报错xxx too large

解决方式:在mysql的安装目录下,找my.ini文件加上如下配置参数:"max_allowed_packet=16M",但修改后需要重启mysql服务

向数据表中插入大的数据

 修改数据表中Blob类型字段

从数据表中读取大的数据类型

//获取连接
Connection conn = JDBCUtils.getConnection();
		
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);

// 填充占位符
ps.setString(1, "徐海强");
ps.setString(2, "xhq@126.com");
ps.setDate(3, new Date(new java.util.Date().getTime()));
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("xhq.png");
ps.setBlob(4, fis);
//执行
ps.execute();
		
fis.close();
JDBCUtils.closeResource(conn, ps);

//修改数据表中Blob字段
Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);

// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png");
ps.setBlob(1, fis);
ps.setInt(2, 25);

ps.execute();

fis.close();
JDBCUtils.closeResource(conn, ps);

//读取
String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();
if(rs.next()){
	Integer id = rs.getInt(1);
    String name = rs.getString(2);
	String email = rs.getString(3);
    Date birth = rs.getDate(4);
	Customer cust = new Customer(id, name, email, birth);
    System.out.println(cust); 
    //读取Blob类型的字段
	Blob photo = rs.getBlob(5);
	InputStream is = photo.getBinaryStream();
	OutputStream os = new FileOutputStream("c.jpg");
	byte [] buffer = new byte[1024];
	int len = 0;
	while((len = is.read(buffer)) != -1){
		os.write(buffer, 0, len);
	}
    JDBCUtils.closeResource(conn, ps, rs);
		
	if(is != null){
		is.close();
	}
		
	if(os !=  null){
		os.close();
	}
    
}

批量插入

允许多条语句一次性提交给数据库批量处理,效率更高

三个方法:

addBatch(String):添加需要批量处理的SQL语句或是参数;

executeBatch():执行批量处理语句;

clearBatch():清空缓存的数据

两种批量执行sql语句:

多条SQL语句的批量处理

一个SQL语句的批量传参;

//向数据表中插入20000条数据
CREATE TABLE goods(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
/*
* 层次四:在层次三的基础上操作
* 使用Connection 的 setAutoCommit(false)  /  commit()* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
 * 修改2:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
 * 		 ?rewriteBatchedStatements=true 写在配置文件的url后面
 * 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar

*/
@Test
public void testInsert2() throws Exception{
	long start = System.currentTimeMillis();
		
	Connection conn = JDBCUtils.getConnection();
		
	//1.设置为不自动提交数据
	conn.setAutoCommit(false);
		
	String sql = "insert into goods(name)values(?)";
	PreparedStatement ps = conn.prepareStatement(sql);
		
	for(int i = 1;i <= 1000000;i++){
		ps.setString(1, "name_" + i);
			
		//1.“攒”sql
		ps.addBatch();
			
		if(i % 500 == 0){
			//2.执行
			ps.executeBatch();
			//3.清空
			ps.clearBatch();
		}
	}
		
	//2.提交数据
	conn.commit();
		
	long end = System.currentTimeMillis();
	System.out.println("花费的时间为:" + (end - start));//1000000条:4978 
		
	JDBCUtils.closeResource(conn, ps);
}

数据库连接池

数据库连接池的必要性:

传统模式:

在主程序(如servlet、beans)中建立数据库连接
进行sql操作
断开数据库连接

存在的问题:

1.数据库的连接资源并没有得到很好的重复利用
2.对于每一次数据库连接,使用完后都得断开
3.这种开发不能控制被创建的连接对象数

而数据库连接池就是为了解决传统开发中的数据库连接问题。

数据库连接池的基本思想

就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去

主要工作:负责分配,管理和释放数据库连接,允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个

数据库连接池是如何实现的?

数据库连接池在初始化时,将创建一定数量的数据库连接放到连接池中,
1.这些数据库连接的数量是由:”最小数据库连接数来设定的“。
2.无论数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。
3.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求被加入到等待队列中

工作原理:

 数据库连接池技术的优点:

1.资源重用

因为重用,避免了频繁创建,释放连接引起的大量性能开销
在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性

2.更快的系统反应速度

数据库连接池在初始化过程中,往往创建了若干个数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间

3.新的资源分配手段

对于应用共享同意数据库的系统而言,可以是应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有资源库资源

4.统一的连接管理,避免数据库连接泄露

在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露

多种开源的数据库连接池

JDBC 的数据库连接池使用 javax.sql.DataSource 来表示

DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现

常用(注:在使用前,必须先导入对应的jar包(数据库连接池驱动),文章末尾可下载):

1.DBCP(速度快,不稳定)

简介: 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。
速度相对c3p0较快
但因自身存在BUG,Hibernate3已不再提供支持

配置文件(dbcp.properties)

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=abc123
//可添加其他
initialSize=10

 实例:

//使用dbcp数据库连接池的配置文件方式,获取数据库的连接:推荐
private static DataSource source = null;
static{
	try {
		Properties pros = new Properties();
		
		InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");
			
		pros.load(is);
		//根据提供的BasicDataSourceFactory创建对应的DataSource对象
		source = BasicDataSourceFactory.createDataSource(pros);
	} catch (Exception e) {
		e.printStackTrace();
	}
		
}
public static Connection getConnection4() throws Exception {
		
	Connection conn = source.getConnection();
	
	return conn;
}

2.C3P0(稳定,速度不快)

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<named-config name="helloc3p0">
		<!-- 获取连接的4个基本信息 -->
		<property name="user">root</property>
		<property name="password">abc123</property>
		<property name="jdbcUrl">jdbc:mysql:///test</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		
		<!-- 涉及到数据库连接池的管理的相关属性的设置 -->
		<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
		<property name="acquireIncrement">5</property>
		<!-- 初始化数据库连接池时连接的数量 -->
		<property name="initialPoolSize">5</property>
		<!-- 数据库连接池中的最小的数据库连接数 -->
		<property name="minPoolSize">5</property>
		<!-- 数据库连接池中的最大的数据库连接数 -->
		<property name="maxPoolSize">10</property>
		<!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
		<property name="maxStatements">20</property>
		<!-- 每个连接同时可以使用的 Statement 对象的个数 -->
		<property name="maxStatementsPerConnection">5</property>

	</named-config>
</c3p0-config>

 实例:

public void testGetConnection() throws Exception{
		//获取c3p0数据库连接池
		ComboPooledDataSource cpds = new ComboPooledDataSource();
		cpds.setDriverClass( "com.mysql.jdbc.Driver" ); 
		cpds.setJdbcUrl( "jdbc:mysql://localhost:3306/test" );
		cpds.setUser("root");                                  
		cpds.setPassword("root");
		//通过设置相关的参数,对数据库连接池进行管理:
		//设置初始时数据库连接池中的连接数
		cpds.setInitialPoolSize(10);
		
		Connection conn = cpds.getConnection();
		System.out.println(conn);
		
		//销毁c3p0数据库连接池
//		DataSources.destroy( cpds );
	}

3.Druid(目前最好的连接池之一)

简介:

是阿里提供的数据库连接池
据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,
但是速度不确定是否有BoneCP快

配置文件(druid.properties)

url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver

initialSize=10
maxActive=20
maxWait=1000
filters=wall

实例:

package com.atguigu.druid;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

public class TestDruid {
	public static void main(String[] args) throws Exception {
		Properties pro = new Properties();		 pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
		DataSource ds = DruidDataSourceFactory.createDataSource(pro);
		Connection conn = ds.getConnection();
		System.out.println(conn);
	}
}

驱动下载(百度网盘):

链接:https://pan.baidu.com/s/1QG0HW7DoXyFRW0t1yLgH8Q 
提取码:1234

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐