JDBC总结1
一、概述
- 概念:JDBC(Java DataBase Connectivity),Java数据库连接。
- 本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包,把数据库厂商写的这套实现类,称之为数据库驱动。
结构演示:
二、使用
2.1 JDBC使用步骤
- 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
- 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
- .右键–>Add As Library
- 加载驱动jar包
- 获取数据库连接对象 Connection
- 定义sql操作语句
- 获取执行sql语句的对象 Statement
- 执行sql,接受返回结果
- 处理结果
- 释放资源
代码演示:
public class JDBC {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象 Connection
String url = "jdbc:mysql://localhost:3306/mydb";
Connection conn = DriverManager.getConnection(url, "root", "123");
//获取操作对象
Statement statement = conn.createStatement();
//发送sql语句
String sql = "insert into student(name,age,address) values('张无忌',20,'西安市')";
//执行executeUpdate(sql) 增删改的语句
int count = statement.executeUpdate(sql);
//处理结果
System.out.println(count);
if (count > 0) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
//释放资源。
conn.close();
statement.close();
}
}
2.1 详解使用类
-
Class.forName(“com.mysql.jdbc.Driver”); 加载驱动,也可以省略不写。mysql5之后的驱动jar包可以省略注册驱动的步骤。
-
当你不写时,Driver里面存在的静态代码块会替你注册。
static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } }
-
-
DriverManager:驱动管理对象
- Java提供的管理一组 JDBC 驱动程序的基本服务。
-
Connection:获取数据库连接。
连接方法:
static Connection getConnection(String url, String user, String password)
参数:
-
url:指定连接的路径。
- 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
- 例如:jdbc:mysql://localhost:3306/mydb
提示:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
-
user:用户名
-
password:密码
-
-
Statement:获取数据库操作对象
- 获取操作对象的方法:
Statement createStatement()
-
执行sql命令
boolean b = statement.execute(sql);
用来执行所有的SQL语句。该方法执行SQL语句可能返回多个结果。- 如果第一个结果为 ResultSet 对象,则返回 true
- 如果其为更新计数或者不存在任何结果,则返回 false
int i = statement.executeUpdate(sql);
用来执行DML语句,用来对表中数据进行增删改。返回值是影响的行数。ResultSet rs = executeQuery(String sql);
用来执行DQL语句,用来对表进行查询。该语句返回单个 ResultSet 对象。
-
ResultSet:结果集对象,封装查询结果
boolean next()
: 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true。getXxx(参数)
:获取数据- Xxx:代表数据类型。如: int getInt() ,String getString()
- int:代表列的编号,从1开始。如:getString(1)
- String:代表列名称。如:getDouble(“balance”)
代码演示:
while (resultSet.next()) { int id = resultSet.getInt(1); String content = resultSet.getString("username"); System.out.println(id + "---" + content); }
-
PreparedStatement:执行sql的对象
- SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。
- 输入用户任意,输入密码:‘a’ or ‘a’ = 'a
- sql:
select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
- 解决sql注入问题:使用PreparedStatement对象来解决。
- 预编译的SQL:参数使用?作为占位符
代码演示:
public class JDBC2 { public static void main(String[] args) throws SQLException, ClassNotFoundException { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/mydb"; String user = "root"; String password = "123"; Connection conn = DriverManager.getConnection(url, user, password); String sql = "select * from user where username = ? and password = ?"; PreparedStatement preparedStatement = conn.prepareStatement(sql); preparedStatement.setString(1, "张三"); preparedStatement.setString(2, "123"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { int id = resultSet.getInt(1); String u = resultSet.getString(2); String p = resultSet.getString(3); System.out.println(id + "---" + u + "---" + p); } //释放资源 conn.close(); preparedStatement.close(); resultSet.close(); } }
注意:后期都会使用PreparedStatement来完成增删改查的所有操作
- 可以防止SQL注入
- 效率更高
- SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。
三、抽取JDBC工具类
- 目的:简化书写
- 使用配置文件解决传递参数的问题properties
工具类:
public class JDBCUtils {
private static String url;
private static String username;
private static String password;
private static String driver;
//想要把获取连接对象和释放资源的操作,抽取到工具类当中
private JDBCUtils() {
}
static {
try {
Properties pro = new Properties();
pro.load(new FileInputStream("jdbc.properties"));
//获取数据,赋值
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConnection() throws SQLException {
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
//释放资源
public static void close(Connection conn, Statement statement, ResultSet resultSet) throws SQLException {
if (conn != null) {
conn.close();
}
if (statement != null) {
statement.close();
}
if (resultSet != null) {
resultSet.close();
}
}
//释放资源
public static void close(Connection conn, Statement statement) throws SQLException {
if (conn != null) {
conn.close();
}
if (statement != null) {
statement.close();
}
}
}
配置文件:
url=jdbc:mysql://localhost:3306/mydb4
username=root
password=123
driver=com.mysql.jdbc.Driver
测试类:
public class MyTest2 {
public static void main(String[] args) throws SQLException {
Connection conn = JDBCUtils.getConnection();
String sql = "select * from user where id>?";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setInt(1, 0);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
int id = resultSet.getInt(1);
String content = resultSet.getString("username");
System.out.println(id + "---" + content);
}
//释放资源
JDBCUtils.close(conn,preparedStatement,resultSet);
}
}
四、JDBC控制事物
4.1 概述
-
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
-
事物的ACID特性
- 原子性(Atomicity):是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
- 隔离性(Isolation):多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
- 持久性(Durability):是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
4.2 事务操作和管理
- 操作:
- 开启事务
- 提交事务
- 回滚事务
- 使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 注意:在执行sql之前开启事务
- 提交事务:commit()
- 当所有sql都执行完提交事务
- 回滚事务:rollback()
- 在catch中回滚事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
4.3 代码演示
模拟张三给李四借钱:
- 当操作正常时,借钱过程正常进行。
- 当存在异常时,事物启动回滚操作,避免损失。
public class JDBC1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps1= null;
PreparedStatement ps2= null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//2.定义sql
//2.1 张三 - 500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2 李四 + 500
String sql2 = "update account set balance = balance + ? where id = ?";
//3.获取执行sql对象
ps1 = conn.prepareStatement(sql1);
ps2 = conn.prepareStatement(sql2);
//4. 设置参数
ps1.setDouble(1,500);
ps1.setInt(2,1);
ps2.setDouble(1,500);
ps2.setInt(2,2);
//5.执行sql
ps1.executeUpdate();
// 手动制造异常
int i = 3/0;
ps2.executeUpdate();
//提交事务
conn.commit();
} catch (SQLException e) {
//事务回滚
try {
if(conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
JDBCUtils.close(conn,ps1);
JDBCUtils.close(null,ps2);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}