JDBC_03
A.批处理
1.概述
当我们需要向数据库存储大量数据时,就需要使用批处理
2.主要方法
PreparedStatment addBatch():调用批处理
PreparedStatment execuyeBatch():执行批处理
PreparedStatment clearBatch():清空批处理
3.代码实现
需求:存放100个数据信息
a.在数据库中创建一个表,具有主键增长
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) );
b.导入驱动jar包和jdbc连接数据库工具类、配置文件
配置文件package org.xxxx.jdbc.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ResourceBundle; /** * * 这是一个jdbc连接数据库的工具类 * * @author wpf * */ public class JDBCUtil { private static String url; private static String user; private static String password; private static String classname; // 读取配置信息 static { try { // 获取对象 ResourceBundle rb = ResourceBundle.getBundle("config"); url = rb.getString("url"); user = rb.getString("user"); password = rb.getString("password"); classname = rb.getString("classname"); // 加载驱动 Class.forName(classname); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 不能创建对象 private JDBCUtil() { } // 获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } // 释放资源 public static void close(ResultSet resultSet, Statement statement, Connection conn) throws SQLException { if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (conn != null) { conn.close(); } } public static void close(Statement statement, Connection conn) throws SQLException { if (statement != null) { statement.close(); } if (conn != null) { conn.close(); } } }
url=jdbc:mysql://localhost:3306/mydb_01 user=root password=root classname=com.mysql.jdbc.Driver
c.写一个User类作为javaBean存放对象
package org.xxxx.jdbc.bean; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private int id; private String username; public User() { super(); } public User(int id, String username) { super(); this.id = id; this.username = username; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User [id=" + id + ", username=" + username + "]"; } }
d.测试类
package org.xxxx.jdbc; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import org.xxxx.jdbc.bean.User; import org.xxxx.jdbc.util.JDBCUtil; public class JDBCDemo { public static void main(String[] args) throws SQLException { // 建立集合存放对象 ArrayList<User> list = new ArrayList<>(); // 存放数据 for (int i = 0; i < 100; i++) { // 为了便于观察 编号为1000+i,username为"姓名+i" User user = new User(i + 1000, "张三" + i); list.add(user); } //连接数据库 Connection conn = JDBCUtil.getConnection(); // 定义sql语句 String sql = "insert into user values(?, ?)"; // 获取预编译对象 PreparedStatement statement = conn.prepareStatement(sql); // 用批处理执行 // 遍历集合 for (User u : list) { statement.setInt(1, u.getId()); statement.setString(2, u.getUsername()); // 调用批处理,将数据加入缓存 statement.addBatch(); } // 执行批处理 statement.executeBatch(); // 清空批处理 statement.clearBatch(); // 释放资源 JDBCUtil.close(statement, conn); } }
B.获取自增长键值
1.概述
如果我有两张表,添加了外键约束user 表是主表,订单表是从表
这两张表通过外键关联起来,如果说我在user表里面添加了一个用户,用户的id 是主键
那我想在订单表里面,描述这个用户的订单,那我就得拿到这个用户的id
2.主要方法
public prepareStatment(sql, PreparedStatment.RETURN_GENERATED_KEYS):
该构造方法主要返回主键
prepareStatment setNull(1,Types.INTEGER):
插入整数空值,适用于自增长主键
ResultSet getGeneratedKeys():
获取自增长键,返回结果集
3.需求
插入一个用户信息,并返回用户主键(id)
package org.xxxx.jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.xxxx.jdbc.util.JDBCUtil; import com.mysql.jdbc.PreparedStatement; public class JDBCAutoKeyValue { public static void main(String[] args) throws SQLException { // 获取链接对象 Connection conn = JDBCUtil.getConnection(); // 定义sql语句 String sql = "insert into user values(?, ?)"; // 获取预编译对象 java.sql.PreparedStatement statement = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); // 给占位符赋值 statement.setNull(1, Types.INTEGER); statement.setString(2, "李四"); // 执行 int i = statement.executeUpdate(); // 获取自增长键的值 ResultSet resultSet = statement.getGeneratedKeys(); // 遍历 while (resultSet.next()) { int keys = resultSet.getInt(1); System.out.println(keys); } // 释放资源 JDBCUtil.close(resultSet, statement, conn); } }
C.DBCP
1.连接池
存放多个连接对象的容器,我们每获取一次链接对象
底层会很耗费资源,连接池可以提高项目的性能
2.DBCP
阿帕奇基金组织出产的高效的管理链接对象
3.主要方法
BasicDataSourceFactory.createDataSource(Properties prop);
创建连接池,读取配置信息必须用Properties
4.代码实现
a.导入DBCP的两个jar包和数据库驱动jar包(一共三个),下图是DBCPjar包
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 org.xxxx.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(); } }
D.C3P0
1.在hibernate和spring框架中常用,有自动回收空闲连接功能
2.主要方法
建立连接池
public ComboPooledDataSource();
public ComboPooledDataSource(String str);选择配置信息
3.代码实现
a.导入jar包和mysql驱动
b.导入配置信息c3p0.properties或者c3p0-config.xml(先介绍properties)
要求
1)配置文件和后缀名固定:c3p0.properties
2)必须放在src目录下
使用者就不需要再读取配置信息,驱动中会自动读取
c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///mydb_01 c3p0.user=root c3p0.password=root
c.测试类
package org.xxxx.c3p0; 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 { // 建立连接池 ComboPooledDataSource ds = new ComboPooledDataSource(); // 链接数据库 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(); } }
控制台的提示信息不用管
4.c3p0-config.xml配置文件
这个配置文件和properties只能存在一个<c3p0-config> <!-- 默认配置,如果没有指定则使用这个配置 --> <default-config> <!-- 基本配置 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb_01</property> <property name="user">root</property> <property name="password">root</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>
用法和properties一样
不同地方:命名配置
设置named_config,若要读取该配置信息,则使用有参构造
ComboPooledDataSource ds = new ComboPooledDataSource("myname");
E.DBUtils
1.概述
阿帕奇基金组织出品,封装操作对象的增删改查
2.主要方法
配合C3P0使用
public QueryRunner(ComboPooledDataSource ds);
将连接池对象传进去
List<> query(sql, new BeanListHandler<>(User.class));
查处所有数据,并封装为对象,装到集合里
3.需求
查询user中的所有数据
a.在C3P0的基础上,导入jar包和驱动
b.建立javaBean存储对象
package org.xxxx.c3p0.bean; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private int id; private String username; public User() { super(); } public User(int id, String username) { super(); this.id = id; this.username = username; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User [id=" + id + ", username=" + username + "]"; } }
c.代码实现
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()); } } }