批处理
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>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<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());
}
}
}