MySQL - JDBC&數據庫連接池
1 JDBC
1.1 概念
- Java Data Base Connectivity
- 執行SQL的Java API
- Java訪問多種數據庫的統一規范(接口)
- 數據庫廠商實現接口並提供驅動jar包
1.1.1 JDBC項目准備
- 新建項目並導入JDBC相關jar包

1.1.2 JDBC連接步驟
1.1.2.1 注冊驅動
Class.forName("com.mysql.jdbc.Driver");
原理:

- JDBC3開始可不用注冊驅動直接使用,該步驟可以省略
1.1.2.2 獲取連接
- connection接口表示連接對象,具體實現類由數據庫廠商實現
- Driver Manager的getConnection方法可以獲得連接對象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8","root","123456");
該Connection對象有com.mysql.jdbc提供
1.1.2.3 獲取語句執行對象
- statement類,語句對象,發送SQL語句給服務器,執行靜態SQL並返回結果
- 通過Connection連接對象的createStatement方法獲取
- statement常用方法:
- int executeUpdate(String sql); DML,DDL語句; 返回值代表受影響的行數
- ResultSet executeQuery(String sql); DQL語句; 返回ResultSet結果集對象
1.1.2.4 處理結果集對象(DQL)
- DQL語句得到的是ResultSet結果集對象
- ResultSet接口封裝了查詢的結果
- 接口方法:
- boolean next(); 如果下一行還有記錄返回true,沒有記錄返回false
- xxx getXxx (String or int); 重載方法; 通過列名返回,參數String,返回不同的類型; 通過列號返回,參數是int,從1開始,返回不同類型
Statement statement = connection.createStatement();
String sql = "SELECT * FROM jdbc_user";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString(2);
String password = resultSet.getString("PASSWORD");
Date birthday = resultSet.getDate(4);
System.out.println(id+" "+username+" "+password+" "+birthday);
}
1.1.2.5 釋放資源
- 先開起后關閉
- resultset(僅DQL查詢時使用) -> statement - > connection
resultSet.close();
connection.close();
statement.close();
1.2 JDBC工具類(Utils)
1.2.1 編寫JDBCUtils工具類
- 將連接信息定義成字符串常量
- 編寫靜態代碼塊注冊驅動
- 編寫靜態方法獲取連接對象
- 編寫關閉資源的方法(重載對於DQL和非DQL)
1.2.1.1 將連接信息定義成字符串常量
public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/bd4?characterEncoding=UTF-8";
public static final String USERNAME = "root";
public static final String PASSWORD = "123456";
1.2.1.2 編寫靜態代碼塊注冊驅動
static {
try {
Class.forName(DRIVERNAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
1.2.1.3 編寫靜態方法獲取連接對象
public static Connection getConnection(){
try {
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
1.2.1.4 編寫關閉資源的方法(重載對於DQL和非DQL)
public static void Close(Connection con, Statement statement){
if (con!=null && statement!= null){
try {
statement.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void Close(Connection con, Statement statement, ResultSet resultSet){
if (con!= null && statement!=null && resultSet!=null){
try {
resultSet.close();
statement.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
1.3 SQL注入問題
- 使用OR,前面用戶名密碼錯誤也可以拿到數據因為or1真為真
select * from jdbc_user where username = 'tom' and PASSWORD = '123' or '1' = '1';
代碼演示:SQL語句為
String sql = "select * from jdbc_user where username = '" + username + "' and PASSWORD = '" + password + "'";
當用戶輸入password為:
abc' or '1' = '1
就會產生SQL注入
1.3.1 如何解決SQL注入?
- 不能讓用戶輸入的密碼和SQL語句進行簡單的字符串拼接
- 輸入時使用Scanner.next而不是nextLine接收,這樣無法拼接空格
- 拿到數據后判斷SQL返回結果的用戶名是否與用戶輸入的用戶名相同
1.3.1.1 預處理對象防止SQL注入
-
PreparedStatement是Statement接口的子接口,繼承父接口所有方法
-
預編譯的SQL語句:
- 執行效率更高
- 更安全,可防止SQL注入
-
? 占位符來設置參數
具體流程:
- 編寫SQL,對於參數使用?占位符
- 通過Connection對象的preparestatement(sql) 有參方法拿到預處理對象
- 調用預處理對象的setXXX(int 占位符位置,XXX 要設置的值)給參數賦值
- 調用預處理對象的execute方法執行SQL查詢
示例:
Connection connection = JDBCUtils.getConnection();
String sql = "select * from jdbc_user where username = ? and PASSWORD = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"tom");
preparedStatement.setString(2,"123456");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("username")+" "+resultSet.getString("PASSWORD"));
}
JDBCUtils.Close(connection,preparedStatement,resultSet);
}
1.3.1.2 statement和preparedstatement
當執行SQL時,比如插入數據(insert into jdbc_user values .... )
-
statement對象每執行一條SQL語句就會先發給數據庫先編譯再執行
- 插入多少條數據數據庫就需要編譯多少次
- 執行靜態SQL
-
preparedstatement對象執行SQL語句數據庫只需要預編譯一次
- 然后將預編譯的SQL保存起來(緩存)
- 插入多條數據時只需設置參數即可
- 可包含動態參數"?"
1.4 事務API
Connection方法實現事務
方法 | 說明 |
---|---|
void setAutoCommit(boolean autocommit) | 是否自動提交,true自動提交 |
void commit() | 提交事務 |
viod rollback() | 回滾事務 |
示例:模擬轉賬操作
- 獲取connection連接對象
- 開啟事務(關閉事務自動提交)
- 獲取preparedstatement對象
- 設置參數,正常則手動提交
- 出現異常則回滾事務
- 關閉資源
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
connection.setAutoCommit(false);
String sql = "update account set money = ? where NAME = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setDouble(1,500.0);
preparedStatement.setString(2,"tom");
preparedStatement.executeUpdate();
preparedStatement.setDouble(1,1500.0);
preparedStatement.setString(2,"jack");
preparedStatement.executeUpdate();
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
JDBCUtils.Close(connection,preparedStatement);
}
}
2 數據庫連接池
2.1 連接池介紹
- 管理數據庫連接,可重復使用鏈接
- 關閉連接不代表銷毀connection,只是進行了歸還
如何使用連接池:
- Java官方為連接池提供了公共的接口java.sql.DataSource
- 廠商實現該接口用戶即可方便用戶切換不同連接池
- 常用連接池:
- DBCP
- C3P0
- Druid
2.2 常用連接池
2.2.1 DBCP連接池
2.2.1.1 概念:
- 開源
- 屬於Apache
- tomcat內置連接池
使用方法:
- 導入相關Jar包

2.2.1.2 DBCP工具類
- 定義常量保存數據庫連接相關信息(Drivername,url,username,password)
- 創建連接池對象BasicDataSource,由DBCP提供的實現類
- 編寫靜態代碼塊對連接池對象進行配置
- 編寫方法從連接池對象種獲取連接
- 釋放資源
代碼:
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBCPUtils {
public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
public static final String USERNAME = "root";
public static final String PASSWORD = "123456";
public static BasicDataSource dataSource = new BasicDataSource();
static {
dataSource.setDriverClassName(DRIVERNAME);
dataSource.setUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
}
public static Connection getConnection(){
try {
Connection connection = dataSource.getConnection();
return connection;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
public static void close(Connection con, Statement statement){
if (con!=null && statement != null){
try {
statement.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection con, Statement statement, ResultSet resultSet){
if (con!=null && statement != null && resultSet!= null){
try {
resultSet.close();
statement.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
測試類:
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = DBCPUtils.getConnection();
String sql = "select * from jdbc_user where username = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"tom");
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString("username")+" "+resultSet.getString(3));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBCPUtils.close(connection,preparedStatement,resultSet);
}
常見配置項:
屬性 | 描述 |
---|---|
driverClassName | 數據庫驅動名稱(mysql時 - com.mysql.jdbc.Driver) |
url | 數據庫地址 |
username | 用戶名 |
password | 密碼 |
maxActive | 最大連接數量(默認8) |
maxIdle | 最大空閑連接(默認8) |
minIdle | 最小空閑連接(默認0) |
intialSize | 初始化連接(默認0) |
2.2.2 C3P0連接池
2.2.2.1 概念
- 開源
- Hibernate,Spring框架使用
使用方式:

可配置xml文件存儲c3p0相關配置

c3p0-config.xml
<c3p0-config>
<!--默認配置-->
<default-config>
<!-- initialPoolSize:初始化時獲取三個連接,
取值應在minPoolSize與maxPoolSize之間。 -->
<property name="initialPoolSize">3</property>
<!-- maxIdleTime:最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。-->
<property name="maxIdleTime">60</property>
<!-- maxPoolSize:連接池中保留的最大連接數 -->
<property name="maxPoolSize">100</property>
<!-- minPoolSize: 連接池中保留的最小連接數 -->
<property name="minPoolSize">10</property>
</default-config>
<!--配置連接池mysql-->
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</named-config>
<!--配置連接池2,可以配置多個-->
</c3p0-config>
2.2.2.2 c3p0工具類
- 不需要定義常量保存數據庫連接相關信息(因為配置xml文件)
- 創建連接池對象ComboPooledDataSource,由c3p0提供的實現類
- new ComboPooledDataSource() 無參構造使用的是xml中的默認配置
- new ComboPooledDataSource(configName) 有參構造使用的是xml中的指定配置
- 編寫方法從連接池對象中拿到connection連接對象
- 釋放資源
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3P0Utils {
public static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");
public static Connection getConnection(){
try {
Connection connection = dataSource.getConnection();
return connection;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
public static void close(Connection con, Statement statement){
try {
if (con!= null && statement!= null){
statement.close();
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection con, Statement statement, ResultSet resultSet){
try {
if (con!= null && statement!= null && resultSet!=null){
resultSet.close();
statement.close();
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
C3P0測試類:
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = C3P0Utils.getConnection();
statement = connection.createStatement();
String sql = "select * from jdbc_user";
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getInt(1)+" "+resultSet.getString(2)+" "+ resultSet.getDate(4));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
C3P0Utils.close(connection,statement,resultSet);
}
2.2.3 Druid連接池
2.2.3.1 概念
使用方式:

配置文件:
- properties文件形式
- 名稱任意,文件路徑任意,建議放到統一的resource資源目錄下
druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
2.2.3.2 Druid工具類
- 不需要定義常量來保存數據庫連接相關信息(properties文件)
- 獲取數據庫連接池對象,通過工廠來獲取DruidDataSourceFactory的createDataSource方法
- createDataSource(Properties p)參數傳入properties屬性集對象
- properties屬性集對象通過load方法傳入從字節流獲取的對應properties文件 - getResourceAsStream()方法
- 通過從工廠中拿到的連接池對象創建connection對象
- 釋放資源
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtils {
public static DataSource dataSource;
static {
try {
Properties p = new Properties();
InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
p.load(resourceAsStream);
dataSource = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
Connection connection = dataSource.getConnection();
return connection;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
public static void close (Connection connection, Statement statement){
if (connection != null && statement != null){
try {
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close (Connection connection, Statement statement, ResultSet resultSet){
if (connection != null && statement != null && resultSet!= null){
try {
resultSet.close();
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
示例:查詢工資3000到5000的員工姓名
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = DruidUtils.getConnection();
statement = connection.createStatement();
String sql = "select ename from employee where salary between 3000 and 5000";
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("ename"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DruidUtils.close(connection,statement,resultSet);
}
2.2.4 DBUtils工具類
2.2.4.1 基礎概念
- 解決JDBC代碼冗余問題
- APache對JDBC進行簡單封裝的開源工具
使用方式:

核心功能:
-
QueryRunner
- SQL語句操作的API
-
ResulSetHandler接口
- DQL后自定義封裝結果集
-
DbUtils類
- 封裝了關閉資源和事務處理的方法
2.2.4.2 表和類的關系
JavaBean類對應一張表
- 實現序列化接口 Serializable
- 提供私有字段 private 類型 變量名 - 對應表中字段
- get和set方法
- 無參構造
2.2.4.3 QueryRunner 核心類
- 構造方法
- 手動模式:QueryRunner()
- 自動模式(傳入數據庫連接池對象):QueryRunner(DataSource ds) 提供數據源(連接池),DbUtils自動維護連接
//自定義Druid工具類中需要加入獲取連接池對象的方法
public static DataSource getDataSource(){
return dataSource;
}
//手動
QueryRunner queryRunner = new QueryRunner();
//自動
QueryRunner queryRunner1 = new QueryRunner(DruidUtils.getDataSource());
- 常用方法
- update(Connection con, String sql, Object ... params) 表數據的增刪改操作
- query(Connection con, String sql, ResultSetHandler
resultset, Object ... params) 表數據的查詢操作
update:
- 創建QueryRunner實例對象(手動模式調用update方法時需要傳入connection對象,自動模式調用update方法時不需要傳入connection對象)
- 編寫SQL語句,使用? 占位符
- 設置占位符參數
- 調用update方法
- 釋放資源
示例:插入一條數據
try {
QueryRunner queryRunner = new QueryRunner();
String sql = "insert into employee values(?,?,?,?,?,?)";
Object[] params = {null,"劉翔",35,"男",9000,"1997-09-18"};
Connection connection = DruidUtils.getConnection();
queryRunner.update(connection,sql,params);
DbUtils.closeQuietly(connection);
} catch (SQLException e) {
e.printStackTrace();
}
示例:修改一條數據
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql = "update employee set salary = ? where ename = ?";
Object[] params = {5000, "劉翔"};
queryRunner.update(sql,params);
} catch (SQLException e) {
e.printStackTrace();
}
示例:刪除一條數據
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql = "delete from employee where eid = ?";
queryRunner.update(sql,11);
} catch (SQLException e) {
e.printStackTrace();
}
2.2.4.4 ResulSetHandler (接口)
- 對查詢出來的ResultSet結果集進行處理
常用實現類:
ResultSetHandler 實現類 | 描述 |
---|---|
ArrayHandler | 將結果集中的第一條記錄封裝到一個Object[]數組中,數組中的每一個元素就是這 條記錄中的每一個字段的值 |
ArrayListHandler | 將結果集中的每一條記錄都封裝到一個Object[]數組中,將這些數組在封裝到List集 合中 |
BeanHandler | 將結果集中第一條記錄封裝到一個指定的javaBean中. |
BeanListHandler | 將結果集中每一條記錄封裝到指定的javaBean中,再將這些javaBean在封裝到List 集合中 |
ColumnListHandle | 將結果集中指定的列的字段值,封裝到一個List集合中 |
KeyedHandler | 將結果集中每一條記錄封裝到Map<String, Oject>,在將這個map集合做為另一個 Map的value,另一個Map集合的key是指定的字段的值 |
MapHandler | 將結果集中第一條記錄封裝到了Map<String, Oject>集合中,key就是字段名稱, value就是字段值 |
MapListHandler | 將結果集中每一條記錄封裝到了Map<String, Oject>集合中,key就是字段名稱, value就是字段值,在將這些Map封裝到List集合中 |
ScalarHandler | 它是用於封裝單個數據。例如 select count(*) from 表操作 |
3個不同map的區別
- MapListHandler (查詢結果為多條記錄):每一個Map對應表中的一條數據,Map里的key為字段名,value為值,然后用一個List將所有Map封裝起來對應表。 遍歷數據需要先遍歷List的每一個Map拿到每一條數據,再通過EntrySet拿到每一個Map的所有key:value對
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql= "select * from employee";
List<Map<String, Object>> query = queryRunner.query(sql, new MapListHandler());
for (Map<String, Object> map : query) {
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
System.out.print(entry.getKey()+":"+entry.getValue()+" ");
}
System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}
結果:
eid:1 ename:李清照 age:22 sex:女 salary:4000.0 empdate:2018-11-12
eid:2 ename:林黛玉 age:20 sex:女 salary:5000.0 empdate:2019-03-14
eid:3 ename:杜甫 age:40 sex:男 salary:6000.0 empdate:2020-01-01
eid:4 ename:李白 age:25 sex:男 salary:3000.0 empdate:2017-10-01
eid:9 ename:zzc age:18 sex:男 salary:3500.0 empdate:2019-09-16
eid:10 ename:abc age:18 sex:男 salary:3600.0 empdate:2019-09-16
- MapHandler(查詢結果為1條記錄):Map對應一條查詢到的語句,Map里的key為字段名,value為值,遍歷結果遍歷entrySet
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql= "select * from employee where ename = ?";
Map<String, Object> result = queryRunner.query(sql, new MapHandler(), "李白");
for (Map.Entry<String, Object> entry : result.entrySet()) {
System.out.print(entry.getKey()+":"+entry.getValue()+" ");
}
} catch (SQLException e) {
e.printStackTrace();
}
- KeyedHandler:每一條記錄對應一個Map,不同之處在於對於表該實現類用Map和每一條記錄的指定字段值來對應
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql= "select ename,age from employee";
Map<Object, Map<String, Object>> query = queryRunner.query(sql, new KeyedHandler<>());
for (Map.Entry<Object, Map<String, Object>> entry : query.entrySet()) {
System.out.print(entry.getKey()+": ");
Set<Map.Entry<String, Object>> entries = entry.getValue().entrySet();
for (Map.Entry<String, Object> objectEntry : entries) {
System.out.print(objectEntry.getKey()+":"+objectEntry.getValue()+" ");
}
System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}
使用Bean對象:
- 根據表的對應字段創建Bean對象
import java.io.Serializable;
import java.util.Date;
public class Employee implements Serializable {
/*
eidint(11) NOT NULL
enamevarchar(20) NULL
ageint(11) NULL
sexvarchar(6) NULL
salarydouble NULL
empdatedate NULL
*/
private static final long serialVersionUID = 2927021897478991450L;
private int eid;
private String ename;
private int age;
private String sex;
private double salary;
private Date empdate;
public Employee() {
}
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getEmpdate() {
return empdate;
}
public void setEmpdate(Date empdate) {
this.empdate = empdate;
}
@Override
public String toString() {
return "Employee{" +
"eid=" + eid +
", ename='" + ename + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", salary=" + salary +
", empdate=" + empdate +
'}';
}
}
示例:
try {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql= "select * from employee";
List<Employee> query = queryRunner.query(sql, new BeanListHandler<Employee>(Employee.class));
for (Employee employee : query) {
System.out.println(employee.toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
2.2.4.5 批處理
- 一次操作執行多條SQL語句
批處理的實現:
- Statement和PreparedStatement對象都支持批處理
- PreparedStatement:
- void addBatch() - 將指定SQL添加到次Statement對象中
- int[] executeBatch() - 提交一批命令到數據庫中,返回數組為受影響行數
mysql 批處理默認關閉,需要參數拼接在url后打開
rewriteBatchedStatements=true
例如: url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8&rewriteBatchedStatements=true
3 MySQL元數據
- 除了表之外的數據都是元數據
- 查詢結果信息: UPDATE 或 DELETE語句 受影響的記錄數
- 數據庫和數據表的信息: 包含了數據庫及數據表的結構信息
- MySQL服務器信息: 包含了數據庫服務器的當前狀態,版本號等
Mysql獲取元數據常用命令:
-- 元數據相關的命令介紹
-- 1.查看服務器當前狀態
show status;
-- 2.查看MySQl的版本信息
select version();
-- 3.查詢表中的詳細信息
show columns from table_name;
-- 4.顯示數據表的詳細索引信息
show index from table_name;
-- 5.列出所有數據庫
show databases:
-- 6.顯示當前數據庫的所有表
show tables :
-- 7.獲取當前的數據庫名
select database():
JDBC獲取元數據
元數據類:
- DatabaseMetaData - 描述數據庫的元數據對象
- ResultSetMetaData - 描述結果集的元數據對象
獲取元數據對象:調用 getMetaData ()方法
- connection 連接對象, 調用 getMetaData () 方法,獲取的是DatabaseMetaData 數據庫元數據對象
- PrepareStatement 預處理對象調用 getMetaData () , 獲取的是ResultSetMetaData , 結果集元數據對象
DatabaseMetaData 常用方法:
- getURL() : 獲取數據庫的URL
- getUserName(): 獲取當前數據庫的用戶名
- getDatabaseProductName(): 獲取數據庫的產品名稱
- getDatabaseProductVersion(): 獲取數據的版本號
- getDriverName(): 返回驅動程序的名稱
- isReadOnly(): 判斷數據庫是否只允許只讀 true 代表只讀
ResultSetMetaData的常用方法:
- getColumnCount() : 當前結果集共有多少列
- getColumnName(int i) : 獲取指定列號的列名, 參數是整數 從1開始
- getColumnTypeName(int i): 獲取指定列號列的類型, 參數是整數 從1開始