目录
JDBC
Statement的不足
- 大量的字符串拼接,代码可读性降低。
- sql注入
SQL注入
bug
通过字符串的拼接,可以得到一个恒等的sql语句,可以跳过某些判断
import com.util.JDBCUtil;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Ch01 {
public static void main(String[] args) {
login("zxcvzxcvzxcv","b' or '1' = '1");
}
public static void login(String username,String password) {
Scanner sc = new Scanner(System.in);
// 1.获取连接
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
stmt = conn.createStatement();
// System.out.println("请输入用户名:");
// String username = sc.next();
// System.out.println("请输入密码:");
// String password = sc.next();
String sql = "select * from user where username = '"
+ username + "' and password = '" + password + "'";
// StringBuilder strb = new StringBuilder("select * from user where username = ");
// strb.append("'").append(username).append("'").append(" and password = '")
// .append(password).append("'");
// String sql = strb.toString();
System.out.println("sql:" + sql);
rs = stmt.executeQuery(sql);
if(rs.next()){
System.out.println("登录成功,欢迎回来:" + username);
}else {
System.out.println("账号或密码错误!");
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,stmt,rs);
}
}
}
PreparedStatement:预编译(预加载)接口
- 通过coon获取的对象
- 是Statement接口的子接口
- sql语句中可以传参。用?占位,通过setXXX方法来给?赋值
- 提高性能
- 避免sql注入
package com.morning_teacher;
import com.util.JDBCUtil;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Ch02 {
@Test
public void test03() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select * from user where username = ? and password = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"aaa");
pstmt.setString(2,"b' or '1' = '1");
rs = pstmt.executeQuery();
if(rs.next()) {
System.out.println("登录成功...");
}else {
System.out.println("账号或密码错误...");
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
}
@Test
public void test02() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select * from scores where s_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,7);
rs = pstmt.executeQuery();
while(rs.next()) {
int sId = rs.getInt("s_id");
int score = rs.getInt("score");
int cId = rs.getInt("c_id");
System.out.println("学号:" + sId + ",分数:" + score + ",科目号:" + cId);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
}
@Test
public void test01() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = JDBCUtil.getConnection();
String sql = "update teacher set name = ? where id = ?";
// 预编译
pstmt = conn.prepareStatement(sql);
// 给占位符赋值,根据位置
pstmt.setString(1,"JJ");
pstmt.setInt(2,6);
// 正式执行sql
int i = pstmt.executeUpdate();
System.out.println(i);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt);
}
}
}
案例
需求:查询学生姓名,分数,科目名
利用面向对象的思想
得到一个集合。
所有的查询和拼装集合的操作都在Dao类中去做
我们在Demo这个类中只做测试。
StudentScoreCourse类
public class StudentScoreCourse {
private String sname;
private Integer score;
private String cname;
public StudentScoreCourse() {
}
public StudentScoreCourse(String sname, Integer score, String cname) {
this.sname = sname;
this.score = score;
this.cname = cname;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "StudentScoreCourse{" +
"sname='" + sname + '\'' +
", score=" + score +
", cname='" + cname + '\'' +
'}';
}
}
StudentScoreCourseDao类
package com.morning_teacher.test;
import com.util.JDBCUtil;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class StudentScoreCourseDao {
private final Connection conn;
{
try {
conn = JDBCUtil.getConnection();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 查询的方法
* 查询学生姓名,分数,科目名
*/
public List<StudentScoreCourse> getAll() {
List<StudentScoreCourse> stus = new ArrayList<>(16);
String sql = "select s.name sname,r.score,c.name cname " +
"from student s " +
"left join scores r on s.id = r.s_id " +
"left join course c on c.id = r.c_id";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()){
String sname = rs.getString("sname");
int score = rs.getInt("score");
String cname = rs.getString("cname");
StudentScoreCourse ssc = new StudentScoreCourse(sname,score,cname);
stus.add(ssc);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
return stus;
}
/**
* 查询某一个学生的分数
*/
public List<StudentScoreCourse> getById(Integer sid) {
List<StudentScoreCourse> stus = new ArrayList<>(16);
String sql = "select s.name sname,r.score,c.name cname " +
"from student s " +
"left join scores r on s.id = r.s_id " +
"left join course c on c.id = r.c_id where s_id = ?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,sid);
rs = pstmt.executeQuery();
while(rs.next()){
String sname = rs.getString("sname");
int score = rs.getInt("score");
String cname = rs.getString("cname");
StudentScoreCourse ssc = new StudentScoreCourse(sname,score,cname);
stus.add(ssc);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
return stus;
}
/**
* 查询某一个学生的某一科的分数
*/
public StudentScoreCourse getBySidAndCid(Integer sid,Integer cid) {
PreparedStatement pstmt = null;
ResultSet rs = null;
StudentScoreCourse ssc = null;
String sql = "select s.name sname,r.score,c.name cname " +
"from student s " +
"left join scores r on s.id = r.s_id " +
"left join course c on c.id = r.c_id where s_id = ? and c_id = ?";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,sid);
pstmt.setInt(2,cid);
rs = pstmt.executeQuery();
while(rs.next()){
String sname = rs.getString("sname");
int score = rs.getInt("score");
String cname = rs.getString("cname");
ssc = new StudentScoreCourse(sname,score,cname);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
return ssc;
}
/**
* 查询某一个学生的总分
*/
public Integer getCount(Integer id) {
Integer score = 0;
String sql = "select sum(score) score " +
"from scores " +
"GROUP BY s_id HAVING s_id = ?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,id);
rs = pstmt.executeQuery();
while (rs.next()) {
score = rs.getInt("score");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JDBCUtil.close(conn,pstmt,rs);
}
return score;
}
/**
* 查询某一个学生的平均分
*/
/**
* 按照总分排序
*/
public List<Integer> getOrderScore() {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Integer> scores = new ArrayList<>();
String sql = "select sum(score) score " +
"from scores " +
"GROUP BY s_id ORDER BY score desc,s_id asc";
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
int score = rs.getInt("score");
scores.add(score);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return scores;
}
}
测试类
package com.morning_teacher.test;
import org.junit.Test;
import java.util.List;
public class Demo {
StudentScoreCourseDao dao = new StudentScoreCourseDao();
@Test
public void test01() {
// 查询学生姓名,成绩,科目名
// System.out.println(dao.getAll());
// System.out.println(dao.getById(2));
// System.out.println(dao.getBySidAndCid(2, 2));
// System.out.println(dao.getCount(1));
System.out.println(dao.getOrderScore());
}
}
ResultSetMetaData(了解即可)
import com.util.JDBCUtil;
import org.junit.Test;
import java.io.IOException;
import java.sql.*;
public class Ch01 {
@Test
public void test03() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select * from user";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
// 获取元数据
/*
元数据:表格本身的数据
表格的列名,结果集的列名
*/
ResultSetMetaData metaData = rs.getMetaData();
// System.out.println(metaData.getColumnName(1));
// System.out.println(metaData.getColumnName(2));
// System.out.println(metaData.getColumnCount());
// metaData.get
for (int i = 1; i <= metaData.getColumnCount() ; i++) {
metaData.getColumnName(i);
}
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println("id:" + id + ",username:" + username + ",password:" + password);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt,rs);
}
}
}
数据库事务
是数据库的特性
Mysql的数据库引擎4
- 在MySQL中,只有使用了Innodb引擎的数据库才支持事务
- 事务处理可以用来维护数据的完整性。保证sql语句要么全部执行,要么全部不执行。
- 发生在DML中,增删改。
事务的四大特征ACID
原子性 A。
一个事务,要么全部完成,要么全部不完成。
一致性 C。
在事务开始之前和事务结束之后,数据库的完整性没有被破坏。
隔离性 Isolation
数据库允许多个事务同时对数据进行处理。每个事务之间是相互隔离。
持久性 D
事务结束以后,对数据的增删改是永久性的。
术语
提交事务,回滚事务(事务回滚)
- 事务一旦提交,就不可能回滚。
- 当一个连接对象被创建时,默认情况下自动提交事务。
- 关闭连接时,数据会自动提交事务。
操作事务的步骤
- 关闭事务的自动提交
- 当做出增删改操作,把变化发生在内存中,提交事务,才会真正提交给数据库。
package com.afternoon_teacher;
import com.util.JDBCUtil;
import org.junit.Test;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Ch02 {
@Test
public void test01() {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
conn = JDBCUtil.getConnection();
// 关闭事务的自动提交
// true:开启(默认) false:关闭
// 开启一个事务
conn.setAutoCommit(false);
// 把id为1的账户余额-1000
String sql1 = "update bank set balance = balance - 1000 where id = 1";
pstmt1 = conn.prepareStatement(sql1);
pstmt1.executeUpdate();
String sql2 = "update bank set balance = balance + 1000 where id = 2";
pstmt2 = conn.prepareStatement(sql2);
pstmt2.executeUpdate();
int i = 10 / 0;
// 提交事务
conn.commit();
System.out.println("转账成功...");
} catch (Exception e) {
try {
// 事务回滚
conn.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
} finally {
JDBCUtil.close(conn,pstmt1);
JDBCUtil.close(null,pstmt2);
}
}
}
标签:rs,19,08,score,2022,sql,import,conn,pstmt
From: https://www.cnblogs.com/lurui711/p/16603343.html