JDBC
我的第一个JDBC程序
package com.wan.lesson01;
import java.sql.*;
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 原本的写法
Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动
//2.用户信息和url
//useUnicode=true&characterEncoding=utf8&&useSSL=true
String url = "jdbc:mysql://localhost:3306/新思路例会分享?useUnicode=true&characterEncoding=utf8&&useSSL=true";
String username = "root";
String password="654321";
//3.链接成功,数据库对象 Connection 代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//4.执行sql的对象
Statement statement = connection.createStatement();
//5.查看所有结果
String sql = "SELECT * FROM `student_table`";
ResultSet resultSet = statement.executeQuery(sql); //返回的结果集,封装了全部的查询结果
while (resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("number="+resultSet.getObject("number"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("birthday="+resultSet.getObject("birthday"));
System.out.println("sex="+resultSet.getObject("sex"));
System.out.println("--------------------------------------");
}
//6.释放连接
connection.close();
statement.close();
resultSet.close();
}
}
运行结果:
id=1
number=B190901
name=小王
birthday=1995-01-01
sex=0
--------------------------------------
id=2
number=B190902
name=小张
birthday=1994-03-06
sex=1
--------------------------------------
id=3
number=B190903
name=小李
birthday=1995-02-07
sex=1
--------------------------------------
id=4
number=B190904
name=小红
birthday=1997-08-22
sex=0
--------------------------------------
id=5
number=B190905
name=新思路
birthday=2001-03-12
sex=2
--------------------------------------
id=6
number=B190906
name=新思路java
birthday=
sex=2
--------------------------------------
id=7
number=B190905
name=mysql
birthday=
sex=2
--------------------------------------
id=8
number=B190907
name=mysql
birthday=
sex=2
--------------------------------------
步骤总结:
- 加载驱动
- 连接数据库 DriverManager
- 获得执行sql的对象 Statement
- 获得返回的结果
- 释放连接
DriverManager
//1.加载驱动 // DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 原本的写法 Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动 String username = "root"; String password="654321";
URL
//2.用户信息和url //useUnicode=true&characterEncoding=utf8&&useSSL=true String url = "jdbc:mysql://localhost:3306/新思路例会分享?useUnicode=true&characterEncoding=utf8&&useSSL=true"; //mysql 默认端口 -- 3306 // 协议://主机:端口号/数据库名?参数1&参数2&参数3 //oracle 默认端口 -- 1521 // jdbc:oracle:thin:@localhost:1521:sid
Connection
//3.链接成功,数据库对象 Connection 代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
// 数据库设置自动提交
// connection.setAutoCommit(true);
// 事务提交
// connection.commit();
// 事务回滚
// connection.rollback();
statement执行SQL对象,PrepareStatement执行SQL的对象
String sql = "SELECT * FROM `student_table`";
statement.executeQuery();//查询操作返回ResultSet
statement.execute();//可以执行任何操作,效率低
statement.executeUpdate();//更新,插入,删除都用这个,返回一个受影响的行数
ResultSet:查询的结果集,封装了所有的结果
//在不知道类型的情况下使用
resultSet.getObject(12);
resultSet.getObject("新思路");
//在知道类型的情况下使用
resultSet.getString("");
resultSet.getInt(001);
resultSet.getLong("");
//更多方法在API帮助文档方法区去查看
获得指定的数据类型:
ResultSet resultSet = statement.executeQuery(sql); //返回的结果集,封装了全部的查询结果
resultSet.getObject();//在不知道的情况下使用
resultSet.getString()//如果知道列的类型,就是用指定的类型
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
遍历,指针:
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面一个
resultSet.next();//移动到下一行
resultSet.previous();//移动到上一行
resultSet.absolute(3);//移动到指定行
释放资源:
connection.close();
statement.close();
resultSet.close();
statement对象
statement执行SQL对象,PrepareStatement执行SQL的对象
String sql = "SELECT * FROM `student_table`";
statement.executeQuery();//查询操作返回ResultSet
statement.execute();//可以执行任何操作,效率低
statement.executeUpdate();//更新,插入,删除都用这个,返回一个受影响的行数
API帮助文档:
public interface Statement
extends Wrapper, AutoCloseable用于执行静态SQL语句并返回其生成的结果的对象。
默认情况下,每个Statement对象只能有一个ResultSet对象同时打开。 因此,如果一个ResultSet对象的读取与另一个对象的读取交错,则ResultSet对象必须由不同的Statement对象生成。 在所有执行方法Statement接口隐式关闭当前ResultSet声明的对象,如果一个开放的存在。
jdbc中的Statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。 ==
Statement对象中的executeUpdata方法,用于向对象发送增删改的sql语句,executeUpdata方法执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
新建一个配置文件 mew file
新建一个工具类
package statement对象.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
//提升作用域
private static String driver=null;
private static String url=null;
private static String username=null;
private static String password=null;
//获取配置文件,src目录下可以通过反射拿到
static {
try{
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
//读入流
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//1.加载驱动
Class.forName(driver);
/*} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}*/
//可以使用最大的异常捕获
} catch (Exception e) {
e.printStackTrace();
}
}
//2.获取连接
/* public static void getConnection() throws SQLException {
DriverManager.getConnection(url, username, password);
}*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//3.释放资源
public static void release(Connection connection, Statement statement, ResultSet resultSet){
//倒着关闭
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//到此,工具类就写完了
}
}
insert
package statement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestInsert {
public static void main(String[] args) {
//finally获取不到,因此提升作用域
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
//获取链接
try {
connection = JdbcUtils.getConnection(); //获取数据库连接
statement = connection.createStatement();//获取SQL的执行对象
String sql ="INSERT INTO `student`(`id`,`name`,`sex`,`birthday`,`address`,`email`)" +
"VALUES(2,'wan2','男',0916,'民大','943010372@qq.com' )";
int i = statement.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}else {
System.out.println("插入失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
// JdbcUtils.release(connection,statement,resultSet);
JdbcUtils.release(connection,statement, null);
}
}
}
delete
package statement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDelete {
public static void main(String[] args) {
//finally获取不到,因此提升作用域
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
//获取链接
try {
connection = JdbcUtils.getConnection(); //获取数据库连接
statement = connection.createStatement();//获取SQL的执行对象
String sql ="DELETE FROM `student` WHERE `id`=1";
int i = statement.executeUpdate(sql);
if(i>0){
System.out.println("删除成功!");
}else {
System.out.println("删除失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
// JdbcUtils.release(connection,statement,resultSet);
JdbcUtils.release(connection,statement, null);
}
}
}
update
package statement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) {
//finally获取不到,因此提升作用域
Connection connection=null;
Statement statement=null;
ResultSet resultSet=null;
//获取链接
try {
connection = JdbcUtils.getConnection(); //获取数据库连接
statement = connection.createStatement();//获取SQL的执行对象
String sql ="UPDATE `student` SET `name`='wan1'WHERE `id`=1";
int i = statement.executeUpdate(sql);
if(i>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
// JdbcUtils.release(connection,statement,resultSet);
JdbcUtils.release(connection,statement, null);
}
}
}
select
package statement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
public static void main(String[] args) {
Connection connection=null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtils.getConnection();
statement = connection.createStatement();
//执行SQL语句
String sql="SELECT *FROM `student`WHERE `id`=1";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,statement,null);
}
}
}
CRUD操作
使用Statement.executeQuery(String sql)完成数据添加操作,示例操作:
//添加操作
Statement statement1 = connection.createStatement();
// String sql = "
" +
// "INSERT INTO `student_table` (`number`,`name`,`birthday`,`sex`)
" +
// "VALUES(`B190909`,`晚风花间寺中人`,`2020-3-28`,`2`);";
String sql = "insert into user (...) value(...)";
int i = statement1.executeUpdate(sql);
if(i>0){
System.out.println("插入成功!");
}
删除操作,
//删除操作
Statement statement1 = connection.createStatement();
String sql = "DELETE FROM `student_table` WHERE id =8;";
int i = statement1.executeUpdate(sql);
if(i>0){
System.out.println("删除成功!");
}
修改操作:
//修改操作
Statement statement1 = connection.createStatement();
String sql = "UPDATE `student_table` SET `name`=`JDBC` WHERE `name`=`mysql`;";
int i = statement1.executeUpdate(sql);
if(i>0){
System.out.println("修改成功!");
}
查询操作:
//查询操作操作
Statement statement1 = connection.createStatement();
String sql = "SELECT *FROM `student_table` WHERE `id`=7";
// int i = statement1.executeUpdate(sql);
ResultSet resultSet1 = statement1.executeQuery(sql);
while ((resultSet1.next())){
//根据获取列的数据类型,分别调用resultSet1的相应方法映射到java对象中
}
SQL注入问题
存在漏洞,会被攻击导致数据泄露 SQL被拼接
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
login("'or '1=1","民大");
SQL注入
package statement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
public static void main(String[] args) {
// login("'or '1=1","民大");
login("wan1","民大");
}
//定义一个登陆业务方法
public static void login(String name,String address){
Connection connection=null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtils.getConnection();
statement = connection.createStatement();
//执行SQL语句
//SELECT *FROM `student`WHERE `name`='wan1'AND `address`='民大'
String sql="SELECT *FROM `student`WHERE `name`='"+name+"'AND`address`='"+address+"'";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("address"));
System.out.println("=======================");
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,statement,null);
}
}
}
PreparedStatement对象
PreparedStatement可以防止SQL注入,效率更高
1.增加
package PreparedStatement对象;
import statement对象.utils.JdbcUtils;
import java.sql.*;
public class TestInsert {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try{
connection= JdbcUtils.getConnection();
//区别
//使用?占位符1代表参数
String sql=" INSERT INTO `student`(`id`,`name`,`sex`,`birthday`,`address`,`email`)" +
"VALUES(?,?,?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);//预编译SQL,先写sql,然后不执行
//手动给参数赋值
preparedStatement.setInt(1,6);
preparedStatement.setString(2,"wan6");
preparedStatement.setString(3,"男");
preparedStatement.setDate(4,new java.sql.Date(new Date(4).getTime()));
preparedStatement.setString(5,"计科");
preparedStatement.setString(6,"1008610086@qq.com");
//执行
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2.删除
package PreparedStatement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestDelete {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try{
connection= JdbcUtils.getConnection();
//区别
//使用?占位符1代表参数
String sql="DELETE FROM `student` WHERE `id`=?";
preparedStatement = connection.prepareStatement(sql);//预编译SQL,先写sql,然后不执行
//手动给参数赋值
preparedStatement.setInt(1,6);
//执行
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("删除成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3.更新
package PreparedStatement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestUpdate {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
try{
connection= JdbcUtils.getConnection();
//区别
//使用?占位符1代表参数
String sql="update `student` set`name` =? where`id`=? ;";
preparedStatement = connection.prepareStatement(sql);//预编译SQL,先写sql,然后不执行
//手动给参数赋值
preparedStatement.setString(1,"万万");
preparedStatement.setInt(2,6);
//执行
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("更新成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4.查询
package PreparedStatement对象;
import statement对象.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
public static void main(String[] args) {
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try{
connection = JdbcUtils.getConnection();
String sql="select *from `student`where `id`=?";
preparedStatement= connection.prepareStatement(sql);
//传递参数
preparedStatement.setInt(1,1);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println("查询成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,preparedStatement,resultSet);
}
}
}
5.防止SQL注入(标记一下)
package PreparedStatement对象;
import statement对象.utils.JdbcUtils;
import java.sql.*;
public class SQL注入 {
public static void main(String[] args) {
// login("'or '1=1","民大"); //技巧
login("wan1","民大");
}
//定义一个登陆业务方法
public static void login(String name,String address){
Connection connection=null;
PreparedStatement st = null;
ResultSet rs = null;
try {
connection = JdbcUtils.getConnection();
// PreparedStatement 防止SQL注入的本质,把传递进来的参数当作字符
String sql="SELECT *FROM `student`WHERE `name`=?AND `address`=?";
st = connection.prepareStatement(sql);
st.setString(1,name);
st.setString(2,address);
rs = st.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("address"));
System.out.println("=======================");
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,st, null);
}
}
}
使用IDEA连接数据库
IDEA操作事务
事务
要么都成功,要么都失败
1.事务的基本要素(ACID)
- 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
- 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。
- 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。
- 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
2.隔离性会产生的问题
-
脏读:一个事务读取了另一个没有提交的事务
-
不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
-
虚读(幻读):用户A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是用户B就在这个时候插入了一条具体分数的记录,当修改A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
3.操作步骤
- 取消掉自动提交:每次执行数据库更新的时候实际上发出SQL命令之后就已经提交上去了。
- 开始事务
- 进行一系列操作
- 如果操作一切合格,则提交事务
- 如果发现一个地方有问题,则可以回滚
package jdbc;
import statement对象.utils.JdbcUtils;
import java.sql.*;
public class transaction {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//关闭数据库的自动提交,自动会开启事务.setAutoCommit方法,是指在事务当中,是否执行一条语句就自动提交一次。 如果想在一个事务里进行多个操作。就必然将setAutoCommit的参数设置成false,在多个操作的最后调用conn.commit()方法,进行手动提交
conn.setAutoCommit(false); //开启事务
String sql1 = "UPDATE `account` set cash = cash-100 where name = 'A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "UPDATE `account` set cash = cash+100 where name = 'B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("成功");
} catch (SQLException e) {
conn.rollback(); //如果失败则回滚事务
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}