登陆操作mysql -hlocalhost –uroot –p123456
退出操作exit
数据库操作建库:create database 库名;
卸载库:drop database 库名;
显示所有数据库:show databases;
选择库:use testjdbc;
表操作建表的sql语句
显示库中所有表:show tables;
显示某个表的结构:describe testjdbc;
SQL操作select
语句;insert
语句; update
语句; delete
语句;
表操作DDL语句(create, alter, drop
等);
先下载一个mysql-connector-java-8.0.16.jar
,其他版本也行
把这个jar添加到Java Build Path
中(我为了避免以后移动jar的时候找不到,就直接复制到项目路径下了)
(1)Driver接口
– Driver接口由数据库厂家提供,对于java开发者而言,只需要使用
Driver接口就可以了。
– 在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序。不
同的数据库有不同的装载方法。
– 驱动:就是各个数据库厂商实现的Sun公司提出的JDBC接口。 即对
Connection等接口的实现类的jar文件
– 装载MySql驱动
• Class.forName("com.mysql.jdbc.Driver");
– 装载Oracle驱动
• Class.forName("oracle.jdbc.driver.OracleDriver");
(2)DriverManager接口
– DriverManager是JDBC的管理层,作用于用户和驱动程序之间。
– DriverManager跟踪可用的驱动程序,并在数据库和相应的驱动程序
之间建立连接。
(3)Connection接口
– Connection与特定数据库的连接(会话),在连接上下文中执行 SQL
语句并返回结果。
– DriverManager的getConnection()方法建立在JDBC URL中定义的数
据库Connection连接上
– 连接MYSQL数据库:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root", "123456");// sql包中的接口
– 连接ORACLE数据库:
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@host:port:databse","user","password");
注意:建立connection是比较耗时、耗资源的,(连接对象内部其实包含的Socket对象,是一个远程的连接,比较耗时!这是Connection对象管理的一个要点!)经过测试,在本机上建立链接,耗时235ms。在真正的开发中,为了提高效率,都会使用连接池来管理连接对象!
(4)Statement接口:用于执行SQL语句、返回结果,是查询操作的核心
– 用于执行静态 SQL 语句并返回它所生成结果的对象。
– 三种Statement类:
• Statement:
– 由createStatement创建,用于发送简单的SQL语句。(不带参数的)
• PreparedStatement:
– 继承自Statement接口,由prepareStatement创建,用于发送含有一个或多个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入。我们一般都用PreparedStatement.
• CallableStatement:
– 继承自PreparedStatement 。由方法prePareCall创建,用于调用存储过程。
– 常用的Statement方法:
• execute()
:运行语句,返回是否有结果集。
• executeQuery()
:运行select语句,返回ResultSet结果集。
• executeUpdate()
:运行insert/update/delete操作,返回更新的行数。
Java中连接数据库的使用示例
// 测试MySQL的连接
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) {
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root", "123456");// sql包中的接口
System.out.println(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
The server time zone value ‘?й???’ is unrecognized or represents more than one time zone.
使用的数据库是MySQL,驱动是8.0.16,这是由于数据库和系统时区差异所造成的。
在jdbc连接的url后面加上serverTimezone=GMT即可解决问题:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root", "123456");// sql包中的接口
如果需要使用gmt+8时区,需要写成GMT%2B8,否则会被解析为空。
再一个解决办法就是:使用低版本的MySQL jdbc驱动,5.1.28不会存在时区的问题。
Loading class ‘com.mysql.jdbc.Driver’. This is deprecated. The new driver class is ‘com.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Class.forName("com.mysql.jdbc.Driver");
替换成Class.forName("com.mysql.cj.jdbc.Driver");
即可执行SQL语句示例
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCTest {
public static void main(String[] args) {
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC",
"root", "123456");
// 执行语句
Statement stat = conn.createStatement();
String sql = "INSERT INTO user (id, pwd) VALUES ('testName', '666666');";
stat.execute(sql);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
实际开发中,使用Statement比较少,因为参数需要拼接字符串来做。处理参数不方便。
另外,使用Statement容易发生SQL注入的危险。
为了避免注入,我们使用PreparedStatement
• execute()
:运行语句,返回是否有结果集。
• executeQuery()
:运行select语句,返回ResultSet结果集。
• executeUpdate()
:运行insert/update/delete操作,返回更新的行数。
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) {
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC",
"root", "123456");
// 执行语句
String sql = "INSERT INTO user (id, pwd,date) VALUES (?,?,?);";// ?占位符 避免拼接字符串时SQL注入
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "高淇");// 可以设置数据类型 参数索引从1开始计算
ps.setString(2, "888888");
ps.setDate(3, new Date(System.currentTimeMillis()));// import java.sql.Date;
ps.execute();// 返回是否有结果集
ps.setObject(1, "老高");// 不关心数据类型
ps.setObject(2, "222222");
ps.setObject(3, new Date(System.currentTimeMillis()));
int count = ps.executeUpdate();// 返回影响的数据条数
System.out.println(count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立链接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root",
"123456");
// 执行语句
String sql = "select * from user";
ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();// 返回结果集
while (rs.next()) {// 游标 返回true
System.out.print(rs.getObject(1) + " ");// 取出第1列
System.out.print(rs.getObject(2) + " ");// 取出第2列
System.out.print(rs.getObject(3) + " ");// 取出第3列
System.out.println(rs.getObject(4) + " ");// 取出第4列
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {// 关闭顺序:resultset->statement->connection 三个try catch一定要分开写 否则一个异常后面都不执行了
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
输出
老高 222222 110 2019-08-11
高淇 888888 119 2019-08-11
对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,当数据量特别大时,会发生异常。
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCTest {
public static void main(String[] args) {
Connection conn = null;
Statement stat = null;
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root",
"123456");
conn.setAutoCommit(false);// 把事务设置为手动提交
stat = conn.createStatement();
for (int i = 0; i < 100; i++) {
stat.addBatch(
"INSERT INTO user (id, pwd, phone, date) VALUES ('批量" + i + "', 'password', 100000, now());");
}
stat.executeBatch();
conn.commit();// 提交事务
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (stat != null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
一组事务要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元!
– 事务开始于:
• 连接到数据库上,并执行一条DML语句(INSERT、UPDATE或DELETE)。
• 前一个事务结束后,又输入了另外一条DML语句。
– 事务结束于:
• 执行COMMIT或ROLLBACK语句。
• 执行一条DDL语句,例如CREATE TABLE语句;在这种情况下,会自动执行COMMIT语句。
• 执行一条DCL语句,例如GRANT语句;在这种情况下,会自动执行COMMIT语句。
• 断开与数据库的连接。
• 执行了一条DML语句,该语句却失败了;在这种情况中,会为这个无效的DML语句执行ROLLBACK语句。
事务的四大特点(ACID)
– atomicity(原子性)
• 表示一个事务内的所有操作是一个整体,要 么全部成功,要么全失败;
– consistency(一致性)
• 表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前的状态;
– isolation(隔离性)
• 事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
– durability(持久性)
• 持久性事务完成之后,它对于系统的影响是永久性的。
事务隔离级别从低到高:
– 读取未提交(Read Uncommitted)
– 读取已提交(Read Committed)
– 可重复读(Repeatable Read)
– 序列化(serializable)
代码示例:使用事务,如果某一条语句执行失败,自动回滚conn.rollback()
package cn.hanquan.jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement ps1 = null;
try {
// 加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc?serverTimezone=UTC", "root",
"123456");
conn.setAutoCommit(false);// 将事务设置为手动提交
for (int i = 0; i < 10; i++) {
ps1 = conn.prepareStatement("INSERT INTO user (id, pwd, phone, date) VALUES (?, ?, ?, now());");
ps1.setObject(1, "auto" + i);
ps1.setObject(2, "000000" + i);
ps1.setObject(3, "10000" + i);
ps1.execute();
}
conn.commit();// 提交事务
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
conn.rollback();// 执行失败 回滚 我测试了一下 如果不加这句话 也会自动回滚 不知道为啥
} finally {
try {
if (ps1 != null) {
ps1.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}