package com.summarize.jdbc;
/*
我们操作数据库的步骤:
1、建立连接
2、执行SQL语句
3、获取返回结果
4、退出(exit,关闭连接,释放资源)
Java程序操作数据库的过程:
1、注册驱动
2、建立连接
3、获取SQL执行平台
4、执行SQL语句
5、处理结果集
6、退出(关闭连接,释放资源)
*/
// 以下程序测试Java程序是如何连接MySQL并执行SQL语句的
import org.junit.Test;
import java.sql.*;
import java.util.Properties;
public class FooDemo {
@Test
public void testJDBC() throws SQLException {
// 注册驱动
Driver driver = new com.mysql.jdbc.Driver();
// 建立连接
String url = "jdbc:mysql://localhost:3306/jdbc_db?useSSL=false";
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "123456");
Connection conn = driver.connect(url, info);
// 获取SQL执行平台
Statement stmt = conn.createStatement();
// 执行SQL语句
String sql = "select * from user";
ResultSet res = stmt.executeQuery(sql);
// 处理结果集
while (res.next()) {
int id = res.getInt(1);
String name = res.getString(2);
int age = res.getInt(3);
String balance = res.getString(4);
System.out.println(id + " " + name + " " + age + " " + balance);
}
// 释放资源
res.close();
stmt.close();
conn.close();
}
}
package com.summarize.driver;
import org.junit.Assert;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/*
Driver
Connection connect(String url, Properties info)
info;至少应该包括"user" 和 "password"属性。
DriverManager:
static void registerDriver(Driver driver)
static void deregisterDriver(Driver driver)
static Connection getConnection(String url, String user, String password)
*/
public class DriverDemo {
// 版本一:通过 Driver获取连接
@Test
public void testDriver1() throws SQLException {
String url = "jdbc:mysql://localhost:3306/jdbc_db?useSSL=false";
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "123456");
Driver driver = new com.mysql.jdbc.Driver();
Connection conn = driver.connect(url, info);
Assert.assertNotNull(conn);
}
// 版本二:通过DriverManager链接
@Test
public void testDriver2() throws Exception {
// 读取配置文件
Properties info = new Properties();
try(Reader reader = new FileReader("jdbc.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
String driverClass = info.getProperty("driverClass");
String url = info.getProperty("url");
String uer = info.getProperty("username");
String password = info.getProperty("password");
// 注册驱动
Class<?> driverType = Class.forName(driverClass);
Driver driver = (Driver) driverType.newInstance();
DriverManager.registerDriver(driver);
// 获取连接
Connection conn = DriverManager.getConnection(url, uer, password);
Assert.assertNotNull(conn);
}
//版本三:通过DriverManager链接
@Test
public void testDriver3() throws SQLException {
// 读取配置文件
Properties info = new Properties();
try(Reader reader = new FileReader("jdbc.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
String url = info.getProperty("url");
String uer = info.getProperty("username");
String password = info.getProperty("password");
// 获取连接
Connection conn = DriverManager.getConnection(url, uer, password);
Assert.assertNotNull(conn);
}
}
// 配置文件:jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false
username=root
password=123456
我们可以通过 Statement 执行各种 SQL 语句,包括 DDL、DCL、DML、DQL等。
通过 Statement 创建数据库、创建表、插入数据、更新数据、查找数据、删除表、删除数据库
package com.summarize.statement;
import org.junit.Assert;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;
/*
Statement:
boolean execute(String sql): 可以执行任何SQL语句, 如果有结果集返回true, 否则返回false.
int executeUpdate(String) 可以执行DDL和DML, 返回受影响的行数
ResultSet executeQuery(String sql) 执行DQL,返回结果集。不管有没有满足查询条件的记录,ResultSet都不为null.
我们可以通过ResultSet的next()方法判断是否有满足查询条件的记录。
*/
public class StatementDemo {
//创建连接(连接mysql数据库)
private Connection getConnection() throws Exception {
// 通过DriverManager获取连接
Properties info = new Properties();
try(Reader reader = new FileReader("jdbc.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
String driverClass = info.getProperty("driverClass");
String url = info.getProperty("url");
String uer = info.getProperty("user");
String password = info.getProperty("password");
// 注册驱动
Class<?> driverType = Class.forName(driverClass);
Driver driver = (Driver) driverType.newInstance();
DriverManager.registerDriver (driver);
// 获取连接
return DriverManager.getConnection(url,uer,password);
}
// 通过 Statement 创建数据库、创建表、插入数据、更新数据、查找数据、删除表、删除数据库
// 创建数据库
@Test
public void createDatabase() throws Exception {
// 获取连接
Connection conn = getConnection();
Statement stmt = conn.createStatement();
// 创建数据库cba
String sql = "create database if not exists `cba`";
boolean b = stmt.execute(sql);
Assert.assertFalse(b);
}
// 创建表
@Test
public void createTable() throws Exception {
// 获取连接
Connection conn = getConnection();
Statement stmt = conn.createStatement();
// 创建在数据库cba中创建一个球员表player,包含字段id、name、height、position
String sql1 = "use cba";
String sql2 = "create table if not exists player(id int primary key, name varchar(20), height float, position varchar(20));";
boolean b1 = stmt.execute(sql1);
boolean b2 = stmt.execute(sql2);
Assert.assertFalse(b1);
Assert.assertFalse(b2);
}
// 插入数据
@Test
public void insertValues() throws Exception {
// 获取数据库连接
Connection conn = getConnection();
// 向user表中插入6条数据
String sql = "insert into user values (null, '王梦薇', 25, 2000000),(null, '马建旭', 25, 2000000)," +
"(null, '杨广硕', 25, 2000000),(null, '张玮轩', 25, 2000000)," +
"(null, '戴俊杰', 25, 2000000),(null, '李灿鹏', 25, 2000000);";
Statement stmts = conn.createStatement();
boolean b = stmts.execute(sql);
stmts.executeQuery(sql);
// int rows = stmts.executeUpdate(sql); 返回受影响的行数
Assert.assertFalse(b);
}
// 更新数据
@Test
public void testUpdate() throws Exception {
Connection conn = getConnection();
Statement stmt = conn.createStatement();
String sql = "update user set balance='5000000' where id=8";
int rows = stmt.executeUpdate(sql);
Assert.assertEquals(1, rows);
}
// 查询数据
@Test
public void testQuery() throws Exception {
Connection conn = getConnection();
Statement stmt = conn.createStatement();
String sql = "select * from user where id=10";
ResultSet rs = stmt.executeQuery(sql);
Assert.assertTrue(rs.next());
}
}
//jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false&useServerPrepStmts=true&cachePrepStmts=true
user=root
password=123456
通常我们只需一条SQL语句要经过下面三个过程。
我们把这种普通的SQL语句称为Immediate Statements。
但是很多情况下,一条SQL语句可能被反复的执行。或者反复执行的SQL语句,他们的结构相似,只是参数不同而已。如果每次执行的时候都要经过上面的词法语义解析、优化SQL、制定执行计划等,那效率就明显不行了。
MySQL提供了预编译语句,可以帮我们解决这个问题。在预编译语句中,我们占位符?代替参数,这样我们只需改变参数就可以执行多条SQL语句,提供统一的模板。我们把这种SQL语句称为PreparedStatements。
预编译语句的优势有以下两点:
语法:
# 编译
prepare stmt_name from prepare_stmt;
# 执行
execute stmt_name [using @var_name [, @var_name] ...];
# 删除
{deallocate | drop} prepare stmt_name
我们需要开启服务端预编译,在 url 后面添加一些参数。
url=jdbc:mysql://localhost:3306/jdbc_db?
useServerPrepStmts=true&cachePrepStmts=true
useServerPrepStmts: 是否启用服务端预编译, true表示启用。
cachePrepStmts:是否缓存预编译语句, true表示缓存。
不管是 Statement 还是 PreparedStatement,执行一条 SQL 语句,客户端都要和服务器进行一次通信,这样效率就比较低下。因此,MySQL 提供了批处理功能。
默认情况下,MySQL 没有开启批处理模式。需要在 url 后面添加 rewriteBatchedStatements=true 参数。
代码演示:
package DbUtils;
/*
需要的jar包:
1、mysql驱动jar包
2、单元测试jar包(junit4)
Java操作数据库的步骤:
1、注册驱动
2、建立连接
3、获取SQL执行平台
4、执行SQL语句
5、获取结果集
6、退出(关闭连接、释放资源)
*/
import org.junit.Assert;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;
/*
Statement:
void addBatch(String sql)
void clearBatch()
int[] executeBatch()
*/
public class BatchDemo {
// 获取连接
private Connection getConnection() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
// 1、读取配置文件
Properties info = new Properties();
try(Reader reader = new FileReader("jdbc.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
String driverClass = info.getProperty("driverClass");
String url = info.getProperty("url");
String user = info.getProperty("user");
String password = info.getProperty("password");
// 2、获取注册驱动
// 通过反射获取驱动类型,并创建改类型对象
Class<?> driverType = Class.forName(driverClass);
Driver driver = (Driver) driverType.newInstance();
// 注册驱动
DriverManager.registerDriver(driver);
// 3、建立连接
return DriverManager.getConnection(url, user, password);
}
// 批处理
@Test
public void testPerformance() throws Exception {
Connection conn = getConnection();
String sql = "insert into t_user (name, age, balance) values (?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
if (i % 1000 == 0) {
pstmt.executeBatch(); // 执行
pstmt.clearBatch(); // 清空
}
pstmt.setString(1, "张三" + i);
pstmt.setString(2, "1" + i);
pstmt.setString(3, "1000000" + i);
// 添加到Batch
pstmt.addBatch();
}
long end = System.currentTimeMillis();
System.out.println(end - start + "ms");
}
}
# 配置文件jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false&useServerPrepStmts=true&rewriteBatchedStatements=true
user=root
password=123456
Java 中用 ResultSet 接口代表数据库返回的结果集。
ResultSet 封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前。ResultSet 的 next() 方法,可以判断是否有还有下一行数据。如果有,返回 true, 将游标指向该行,我们可以通过 ResultSet 对象获取该行的数据。如果没有,返回
false。
常用API
getXXX(int index)
getXXX(String columnName)
next()
previous()
absolute(int row)
beforeFirst()
afterLast()
代码实现:
package DbUtils;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;
public class ResultSet {
// 获取连接
public Connection getConnection() throws Exception {
// 读取配置文件
Properties info = new Properties();
try(Reader reader = new FileReader("jdbc.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
String driverClass = info.getProperty("driverClass");
String url = info.getProperty("url");
String user = info.getProperty("user");
String password = info.getProperty("password");
// 获取驱动类型并通过该类型的Class对象创建驱动
Class<?> driverType = Class.forName(driverClass);
Driver driver = (Driver) driverType.newInstance();
// 注册驱动
DriverManager.registerDriver(driver);
// 获取连接
return DriverManager.getConnection(url, user, password);
}
// ResultSet测试
/*
常用API测试:
getXXX(int index) getXXX(String columnName) next()
previous()
absolute(int row) beforeFirst()
afterLast()
*/
@Test
public void testResultSet() throws Exception {
// 获取连接
Connection conn = getConnection();
String sql = "select * from user";
PreparedStatement pstmt = conn.prepareStatement(sql);
java.sql.ResultSet res = pstmt.executeQuery();
// 处理结果集
System.out.println("正向遍历:");
while (res.next()) {
int id = res.getInt(1);
String name = res.getString(2);
String age = res.getString(3);
String balance = res.getString(4);
System.out.println(id + " " + name + " " + age + "" + balance);
}
System.out.println("\n 逆向遍历:");
while (res.previous()) {
String name = res.getString("name");
String balance = res.getString("balance");
int id = res.getInt("id");
int age = res.getInt("age" );
System.out.println(id + " " + name + " " + age + " " + balance);
}
res.close();
conn.close();
}
}
# 配置文件同上
后续内容在下一篇博客更新!