JDBC操作MySQL
添加操作
Class.forName(diverClassName);
是为了兼容老版本,老版本驱动为com.mysql.jdbc.Driver
,之后的驱动为com.mysql.cj.jdbc.Driver
,可以自动加载驱动,不用写forName
语句- 新版?要在url的数据库名后加
?serverTimezone=UTC&useSSL=false
进行其他设置 - 使用Statement对象的话导入的是
java.sql.Statement
这个包,不是mysql。也可以使用java.sql.PreparedStatement
里的PreparedStatement预编译。 - 数据库名datasheet,数据表名person,表内字段"name",“age”,“gender”。
package com.cc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Test {
public static void main(String[] args) throws Exception {
// 四个参数
String diverClassName = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://127.0.0.1:3306/datasheet?serverTimezone=UTC&useSSL=false";
String name = "root";
String passWord = "123123";
// 为兼容老版本加载驱动,之后可以不写,自动加载驱动
Class.forName(diverClassName);
// 创建连接
Connection c = DriverManager.getConnection(url, name, passWord);
//-------------------------------方案一---------------------------------------
// SQL语句
String sql = "INSERT INTO person VALUES('bb','12','dd')";
// 得到Statement对象(注意:使用的是 java.sql.Statement)
Statement stmt = c.createStatement();
// 执行sql语句
stmt.executeUpdate(sql);
// 关闭操作
stmt.close();
c.close();
//-------------------------------方案二---------------------------------------
// sql语句
String sql = "INSERT INTO person VALUES(?,?,?)";
// 预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "chen");
preparedStatement.setInt(2, 122);
preparedStatement.setString(3, "hh");
preparedStatement.execute();
// 关闭连接
preparedStatement.close();
connection.close();
}
}
删除和更改操作和添加操作只是在sql语句上不同,其他基本一致。
删除语句:DELETE FROM person WHERE name=“星星”;
更新语句: UPDATE person SET age=18 WHERE name=“星星”;
查询操作
package com.cc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Test {
public static void main(String[] args) throws Exception {
// 四个参数
String diverClassName = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://127.0.0.1:3306/datasheet?serverTimezone=UTC&useSSL=false";
String name = "root";
String passWord = "123123";
// 为兼容老版本加载驱动,之后可以不写,自动加载驱动
Class.forName(diverClassName);
// 创建连接
Connection c = DriverManager.getConnection(url, name, passWord);
// SQL语句
// String sql = "INSERT INTO person VALUES(?,?,?)";
String sql = "select * from person where name = ?";
// 预编译对象
PreparedStatement preparedStatement = c.prepareStatement(sql);
preparedStatement.setString(1, "星星");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString("name") + resultSet.getInt("age") + resultSet.getString("gender"));
}
//关闭连接
resultSet.close();
preparedStatement.close();
c.close();
}
}
JDBC连接池
与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。
如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建.
使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。
-
ConnectionPool() 构造方法约定了这个连接池一共有多少连接
-
在init() 初始化方法中,创建了size条连接。 注意,这里不能使用try-with-resource这种自动关闭连接的方式,因为连接恰恰需要保持不关闭状态,供后续循环使用
-
getConnection, 判断是否为空,如果是空的就wait等待,否则就借用一条连接出去
-
returnConnection, 在使用完毕后,归还这个连接到连接池,并且在归还完毕后,调用notifyAll,通知那些等待的线程,有新的连接可以借用了。
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ConnectionPool {
List<Connection> cs = new ArrayList<Connection>();
int size;
public ConnectionPool(int size) {
this.size = size;
init();
}
public void init() {
//这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < size; i++) {
Connection c = DriverManager
.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");
cs.add(c);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized Connection getConnection() {
while (cs.isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Connection c = cs.remove(0);
return c;
}
public synchronized void returnConnection(Connection c) {
cs.add(c);
this.notifyAll();
}
}
事务的四大特性
- 原子性
事务中的操作是不可分割的原子单位,要么全部成功,要么全部失败 - 一致性
事务执行后,数据库的状态与其他业务规则保持一致,如转账,无论成功与否,参与转账的两个账号余额是不变的 - 隔离性
在并发操作中,不同的事务应隔离开,每个并发中的事务不会相互干扰 - 持久性
事务提交成功,事务中所有的数据操作都必须持久化到数据库中,及时崩溃也能恢复数据