【JavaWeb笔记】批处理,连接池(DBCP,C3P0),DBUtils

1 篇文章 0 订阅
1 篇文章 0 订阅

批处理

1.概述

一次性执行大量数据。将多条数据缓存起来,然后一次性执行。

for循环执行,会产生多次连接,每执行一次连接一次,耗费资源,性能差,所以采用批处理的方式。


2.主要方法

void addBatch(String sql) 添加批处理

void clearBatch() 清空批处理 

int[] executeBatch()执行批处理


3.实现过程

需求:存放100个数据

a.先创建一个具有ID、name两个字段的表,ID字段具有主键增长;

b.导入驱动jar包和配置文件;

package JDBC;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;

import Bean.User;

public class JDBCBatch {
	public static void main(String[] args) throws SQLException {
		ArrayList<User> list=new ArrayList<>();
		for(int i=0;i<100;i++){
			User user=new User(i, "张三"+i);
			list.add(user);
		}
		
		Connection conn=JDBCUtil.getConnection();//创建工具类对象
		String sql="insert into user values(?,?)";
		PreparedStatement statement = conn.prepareStatement(sql);
		
		for(User u:list){
			statement.setInt(1, u.getId());//设定问号内容
			statement.setString(2, u.getName());
			statement.addBatch();//添加批处理
		}
		
		statement.executeBatch();//执行批处理
		statement.clearBatch();//清除批处理
		
		JDBCUtil.close(conn, statement);
	}

}

JDBCUtil工具类内容:

package JDBC;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
	//工具类
	public static String url=null;
	public static String user=null;
	public static String password=null;
	
	static{
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream("jdbc.properties"));
			url=properties.getProperty("url");
			user=properties.getProperty("user");
			password=properties.getProperty("password");
			Class.forName(properties.getProperty("driverclass"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private JDBCUtil(){
		super();
	}
	
	//返回连接对象
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url,user,password);
	}
	
	//释放资源
	public static void close(Connection conn,Statement stat,ResultSet result) throws SQLException{
		if(conn!=null){
			conn.close();
		}
		if(stat!=null){
			stat.close();
		}
		if(result!=null){
			result.close();
		}
		
		
	}
	
	public static void close(Connection conn,Statement stat) throws SQLException{
		if(conn!=null){
			conn.close();
		}
		if(stat!=null){
			stat.close();
		}
	}
}


User对象类:

package Bean;

import java.io.Serializable;

public class User implements Serializable{

	
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;
	
	
	public User() {
		super();
	}


	public User(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}


	public int getId() {
		return id;
	}


	public void setId(int id) {
		this.id = id;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public static long getSerialversionuid() {
		return serialVersionUID;
	}


	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}
	
	

}


配置文件内容:

url=jdbc:mysql:///mydb_01
user=root
password=root
driverclass=com.mysql.jdbc.Driver


获取自增长键的值

1.需求

如果我有两张表,添加了外键约束 user 表是主表,订单表是从表,这两张表通过外键关联起来,如果说我在user表里面添加了一个用户,用户的id是主键,那我想在订单表里面描述这个用户的订单,那我就得拿到这个用户的id。


2.代码实现

package JDBC;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;



public class JDBCAutoKey {
	public static void main(String[] args) throws SQLException {
		Connection conn = JDBCUtil.getConnection();
		String sql="insert into user values(?,?)";
		PreparedStatement statement = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
						//返回主键
		statement.setNull(1, Types.INTEGER);//插入整数空值,自增长主键自行增加
		statement.setString(2, "李四");
		
		int i=statement.executeUpdate();
		ResultSet keys = statement.getGeneratedKeys();//获取结果集
		while(keys.next()){
			int key=keys.getInt(1);
			System.out.println(key);
		}
		//释放资源
		JDBCUtil.close(conn, statement, keys);
		
		
				
	}

}


连接池

1.概述

存放多个连接对象的容器。因为每获取一次连接,底层会耗费资源,那么连接池能够高效的管理连接对象。


2.市面上常见的连接池产品

DBCP:阿帕奇基金组织出品,Tomcat的连接池组件,高效的管理连接对象;

C3P0:一个开源的JDBC连接池,Hibernate,Spring的连接池组件。


  DBCP和C3P0的区别:

DBCP没有自动回收空闲连接功能;

     C3P0有自动回收空闲连接功能。


3.DBCP

a.导入DBCP的两个jar包和数据库驱动jar包


b.导入配置文件dbcp.properties

#连接基本设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb_01
username=root
password=root


#<!--扩展配置 了解-->
#初始化连接
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
c.代码实现

package DBCP;  
  
import java.io.FileInputStream;  
import java.sql.Connection;  
import java.sql.PreparedStatement;  
import java.sql.Types;  
import java.util.Properties;  
  
import javax.sql.DataSource;  
  
import org.apache.commons.dbcp.BasicDataSourceFactory;  
  
public class DBCPDemo {  
    public static void main(String[] args) throws Exception {  
        // 读取配置信息  
        Properties prop = new Properties();  
        prop.load(new FileInputStream("src//dbcp.properties"));  
          
        // 创建连接池  
        DataSource ds = BasicDataSourceFactory.createDataSource(prop);  
          
        // 链接数据库  
        Connection conn = ds.getConnection();  
          
        // 定义sql语句  
        String sql = "insert into user values(?, ?)";  
          
        // 获取预编译对象  
        PreparedStatement statement = conn.prepareStatement(sql);  
          
        // 赋值  
        statement.setNull(1, Types.INTEGER);  
        statement.setString(2, "王五");  
          
        // 执行语句  
        statement.executeUpdate();  
          
        // 释放资源  
        statement.close();  
        conn.close();  
    }  
}  
硬编码方式与这种方法类似,用到了setDriverName()、setUrl()、setUsername()、setPasswprd()方法。


4.C3P0

a.导入c3p0的jar包和驱动jar包;

b.两种配置文件c3p0.properties、c3p0-config.xml,均可被自动读取,两种方式选一即可;

要求:

1)配置文件的文件名和后缀名不能修改;

2)必须放在src目录下。

c3p0.properties:

c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///day07
c3p0.user=root
c3p0.password=1234


c3p0-config.xml:


<c3p0-config>
	<!-- 默认配置,如果没有指定则使用这个配置 -->
	<default-config>
		<!-- 基本配置 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/day07</property>
		<property name="user">root</property>
		<property name="password">1234</property>
	
		<!--扩展配置-->
		<property name="checkoutTimeout">30000</property>
		<property name="idleConnectionTestPeriod">30</property>
		<property name="initialPoolSize">10</property>
		<property name="maxIdleTime">30</property>
		<property name="maxPoolSize">100</property>
		<property name="minPoolSize">10</property>
		<property name="maxStatements">200</property>
	</default-config> 
	
	
	<!-- 命名的配置 -->
	<named-config name="myname">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/xxxx</property>
		<property name="user">root</property>
		<property name="password">1234</property>
		
		
		<!-- 如果池中数据连接不够时一次增长多少个 -->
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">20</property>
		<property name="minPoolSize">10</property>
		<property name="maxPoolSize">40</property>
		<property name="maxStatements">20</property>
		<property name="maxStatementsPerConnection">5</property>
	</named-config>
</c3p0-config> 

c3p0-config.xml配置文件提供了一些扩展配置,可以再配第二连接,创建对象时的参数是第二配置名称。


c.具体实现

package JDBC;  
  
import java.sql.Connection;  
import java.sql.PreparedStatement;  
import java.sql.SQLException;  
import java.sql.Types;  
  
import com.mchange.v2.c3p0.ComboPooledDataSource;  
  
public class C3P0Demo {  
    public static void main(String[] args) throws SQLException {  
        // 建立连接池 (配置文件为c3p0.properties) 
        ComboPooledDataSource ds = new ComboPooledDataSource(); 
	// 建立连接池 (配置文件为c3p0-config.xml) 
        //ComboPooledDataSource ds = new ComboPooledDataSource(named-config name); 

  
        // 链接数据库  
        Connection conn = ds.getConnection();  
  
        // 定义sql语句  
        String sql = "insert into user values(?, ?)";  
  
        // 获取预编译对象  
        PreparedStatement statement = conn.prepareStatement(sql);  
          
        // 赋值  
        statement.setNull(1, Types.INTEGER);  
        statement.setString(2, "王五");  
          
        // 执行语句  
        statement.executeUpdate();  
          
        // 释放资源  
        statement.close();  
        conn.close();  
        ds.close();  
    }  
}  

DBUtils工具类

1.概述

阿帕奇出品的JDBC工具类,封装了 对操作对象的增删改查,配合c3p0使用。


2.主要方法

public QueryRunner(ComboPooledDataSource ds);

将连接池对象传进去

List<> query(sql, new BeanListHandler<>(User.class));

查处所有数据,并封装为对象,装到集合里


3.代码实现

import org.xxxx.c3p0.bean.User;  
  
import com.mchange.v2.c3p0.ComboPooledDataSource;  
  
public class DBUtils {  
    public static void main(String[] args) throws SQLException {  
        // 创建连接池  
        ComboPooledDataSource ds = new ComboPooledDataSource();  
          
        // 创建增删改查对象  
        QueryRunner runner = new QueryRunner(ds);  
          
        // 定义sql语句  
          
        String sql = "select * from user";  
          
        // 执行语句,并封装对象到集合  
        List<User> list = runner.query(sql, new BeanListHandler<>(User.class));  
          
        // 遍历  
        for (User u : list) {  
            System.out.println(u.getId() + "---" + u.getUsername());  
        }  
    }  
}  













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值