一。JDBC: Java DataBase Connective 是 Java连接数据库的规范 - 接口
-
java.sql -> JDBC 规范相关的接口,类 实现类: 各个数据库厂商来提供
-
1.Connection - 连接
a.引入jar包
mysql-connector-java-5.1.8-bin.jar
推荐数据库版本: 5.5 5.7 5.x
mysql-connector-java-8.0.16.jar
推荐数据库版本: 8.x
b.加载驱动 - 类
Class.forName(“驱动类名”);
oracle: oracle.jdbc.driver.OracleDriver
mysql: com.mysql.jdbc.Driver
c.获得连接
DriverManager.getConnection(url, username, password);
url: jdbc:mysql://ip:port/database?serverTimezone=GMT
username: 账号
password: 密码
d.获得执行SQL语句的Statement对象
e.执行SQL, 获得结果 boolean int ResultSet
f.释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo1 {
public static void main(String[] args) {
//加载驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");// cj 控制台升级
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//建立连接
try {
/*
账号或密码错误:SQLException: Access denied for user 'liuliudr'@'localhost' (using password: YES)
时区错误:java.sql.SQLException: The server time zone value
port错误:java.net.ConnectException:
ip错误:UnknownHostException
可能产生异常: SQLException
1.dataBase 指定错误
2.账号/密码错误
3.端口错误 -> Connection refused
4.ip错误 -> Network is unreachable
5.jdbc:mysql 错误 -> No suitable driver
结论: 连接数据库url需要匹配合适的驱动类
*/
// url:(jdbc:mysql://ip:port/database?serverTimezone=GMT),user,password;
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/work01?serverTimezone=GMT","liuliudr","123456");
// url也可写成jdbc:mysql:///database前提是localhost
//System.out.println(conn);
/*
Statement 中:
boolean execute(String sal)
执行DDL DQL 返回 false,执行DCL返回true。返回值看他有没有结果
*/
Statement statement = conn.createStatement();
//DDL
String sql="create table sks(id int(10) primary key auto_increment,name varchar(20));";
statement.execute(sql);
//DQL
String sql1="insert into sks value(1,'黑土');";
statement.execute(sql1);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
-
-
Statement 中执行sql语句的方法有三个
boolean execute(String sql) DDL DML: 返回false DQL: 返回true 因为DML 和 DQL有专门的执行方法, 所以该方法通常用来执行DDL 返回值: 有没有结果 int executeUpdate(String sql) 只能执行 DML 返回值: 影响了几行 ResultSet executeQuery(String sql) 只能执行 DQL 返回值: 查询出来的结果集
-
@Test
public void testDML() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_day01", "root", "root");
Statement stmt = conn.createStatement();
// 5.执行sql语句 DDL DML DQL
// 执行DML
String sql = "insert into u values(1, 'lucy')";
boolean b = stmt.execute(sql); // false
System.out.println(b);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Test
public void testDQL() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_day01", "root", "root");
Statement stmt = conn.createStatement();
// 5.执行sql语句 DDL DML DQL
// 执行DQL
String sql = "select * from u ";
boolean b = stmt.execute(sql); // true
System.out.println(b);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Test
public void testDML2() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_day01", "root", "root");
Statement stmt = conn.createStatement();
// 5.执行sql语句 DDL DML DQL
// 执行DML
String sql = "insert into u values(2, 'tom')";
int i = stmt.executeUpdate(sql); // 1
System.out.println(i);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
-
- ResultSet rs = stmt.executeQuery(sql); // 返回结果集
rs.next(); // 询问有没有下一个,并且指针向后移动
// ResultSet获得的数据 就是当前指针位置这一行的数据
// 获得这一行第一列的数据
- ResultSet rs = stmt.executeQuery(sql); // 返回结果集
@Test
public void testDQL() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/work01?serverTimezone=GMT", "liuliudr", "123456");
Statement stmt = conn.createStatement();
// 5.执行sql语句 DDL DML DQL
// 执行DQL
String sql1 = "select * from sks";
/*
将一整行数据作为一个整体, 并且存入ResultSet中
*/
ResultSet rs = stmt.executeQuery(sql1); // 返回结果集
rs.next(); // 询问有没有下一个,并且指针向后移动
// ResultSet获得的数据 就是当前指针位置这一行的数据
// 获得这一行第一列的数据
int id1 = rs.getInt(1);
String name1 = rs.getString(2);
System.out.println(id1 + " -- " + name1);
// 获得第二行数据
boolean is = rs.next();
int id2 = rs.getInt(1);
String name2 = rs.getString(2);
System.out.println(id2 + " -- " + name2);
// 如果rs.next()超出会报错 After end of result set
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Test
public void testDQL3Finally() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/work01?serverTimezone=GMT", "liuliudr", "123456");
stmt = conn.createStatement();
// 5.执行sql语句 DDL DML DQL
// 执行DQL
String sql = "select id i, name from sks ";
rs = stmt.executeQuery(sql); // 返回结果集
while (rs.next()) {
// ResultSet获得的数据 就是当前指针位置这一行的数据
// 获得列名为 i 的值
int id1 = rs.getInt("i");
String name1 = rs.getString("name");
System.out.println(id1 + " -- " + name1);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 6.释放资源 - finally
JDBCUtil.close(conn, stmt, rs);
/*try {
// 避免空指针
if (rs != null) {
rs.close();
}
stmt.close();
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}*/
}
}
二。链接的封装
封装文件和配置文件
1.分装
package Conne;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtil {//数据库连接封装
//静态成员变量
private static String driver;
private static String url;
private static String password;
private static String user;
//静态代码块读取内容
static {
/*
Properties类表示了一个持久的属性集,它是在一个文件中存储键值对儿的,其中键值对儿以等号分隔。
Properties可保存在流中或从流中加载。属性列表中的每个键及其所对应的值都是字符串。
Properties类是线程安全的:多个线程可以共享单个Properties对象而无需进行外部同步。
*/
Properties pro = new Properties();
try {
pro.load(JDBCUtil.class.getResourceAsStream("getResource.properties"));
driver = pro.getProperty("driver");
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//连接封装
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
//关闭方法封装1
public static void close(Connection cn, Statement st, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (cn != null) {
cn.close();
}
if (st != null) {
st.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭方法封装2
public static void close(Connection cn, Statement st) {
try {
if (cn != null) {
cn.close();
}
if (st != null) {
st.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2.配置文件.properties
url=jdbc:mysql://localhost:3306/work01?serverTimezone=GMT
user=liuliudr
password=123456
driver=com.mysql.cj.jdbc.Driver
-------------------------------------------------------------
@Test
//调用封装来驱动连接和关闭
public void de5() {
Connection conn = null;
Statement statement = null;
try {
conn = JDBCUtil.getConnection();
statement = conn.createStatement();
//DCL
String sql1 = "select * from sks";
ResultSet rs = statement.executeQuery(sql1);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id + "--" + name);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtil.close(conn, statement);
}
}
三。PreparedStatement预编译
1.PreparedStatement extends Statement
- 给占位符传参
1.有效防止SQL注入
2.当多次执行相同的/相似的SQL, 只需要预编译一次, 而Statement需要编译多次, PreparedStatement效率更高
@Test
public void de6() throws SQLException {
//PreparedStatement在进行多次的类似的插入时,效率更快
Connection connection = JDBCUtil.getConnection();
String sql = "insert into login(password,NAME) values(?,?);";
//PreparedStatement预编译sql一次
PreparedStatement stmt = connection.prepareStatement(sql);// SQLException抛出异常
stmt.setString(1, "武松");
stmt.setString(2, "黄菊");
stmt.executeUpdate();//插入。此时执行sql一次
}
2.设置节点和回滚
- JDBC中的事务, 绑定在连接对象上的, 都是默认自动提交
1.设置事务手动提交
conn.setAutoCommit(false)
2.代码正常结束, 提交事务
conn.commit();
3.代码出现异常, 回滚事务
conn.rollback()
4.了解:
保存事务结点 SavePoint a = conn.setSavePoint();
回滚到指定的结点 conn.rollback(a);
public class JDBCDemo06 {
@Test
public void testPreparedStatement() {
Connection conn = JDBCUtils.getConnection();
PreparedStatement stmt = null;
try {
conn.setAutoCommit(false); // 1.设置事务为手动提交
String sql = "insert into user values(null,?,?,?,?)";
// 预编译SQL, 一次
stmt = conn.prepareStatement(sql);
// 执行第一次sql - 传递一次参数
stmt.setString(1, "赵六11");
stmt.setInt(2, 28);
stmt.setString(3, "2020-08-01");
stmt.setString(4, "123");
// 执行一次sql
stmt.executeUpdate();
// 保存当前事务结点 => savepoint a - 了解
// Savepoint a = conn.setSavepoint();
stmt.setString(1, "赵老六1");
stmt.setInt(2, 28);
stmt.setString(3, "2020-08-01");
stmt.setString(4, "123");
// 第二次执行SQL
stmt.executeUpdate();
// 事务提交
conn.commit();
} catch (Exception throwables) {
// 事务回滚 -> 通常是在异常中回滚
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
} finally {
JDBCUtils.close(stmt, conn);
}
// 了解
// 回滚到保存的a结点中 => rollback to a
// conn.rollback(a);
}
}
本文介绍了JDBC中的Connection连接数据库的基本操作,包括加载驱动、获取连接和执行SQL。接着讲解了Statement对象的使用,并对比了PreparedStatement的预编译特性,强调其在防止SQL注入和提高效率上的优势。最后,文章探讨了JDBC事务管理,包括如何设置手动提交、回滚事务以及使用保存点。
3535

被折叠的 条评论
为什么被折叠?



