实训四十一天 JDBC(PreparedStatement ,事务)
1.学习重点
1.PreparedStatement
2.事务处理
2.学习心得
今天是在黑夜中学习的一天...
3.学习内容
PreparedStatement
Statement的不足
1、大量的字符串拼接,代码可读性降低。
2、sql注入
SQL注入:BUG
通过字符串的拼接,可以得到一个恒等的sql语句,可以跳过某些判断。
PreparedStatement:预编译(预加载)接口
1、通过conn获取的对象
2、是Statement接口的子接口
3、sql语句中可以传参。用?占位,通过setXXX方法来给?赋值
4、提高性能
5、避免sql注入
案例
需求:查询学生姓名,分数,科目名
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
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 Integer getAvg(Integer id) {
Integer score = 0;
String sql = "select avg(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;
}
}
获取元数据
元数据:表格本身的数据
表格的列名,结果集的列名
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();
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的数据库引擎
1.在MySQL中,只有使用了Innodb引擎的数据库才支持事务
2.事务处理可以用来维护数据的完整性。保证sql语句要么全部执行,要么全部不执行。
3.发生在DML中,增删改。
事务的四大特征ACID
1、原子性 A。
一个事务,要么全部完成,要么全部不完成。
2、一致性 C。
在事务开始之前和事务结束之后,数据库的完整性没有被破坏。
3、隔离性 Isolation
数据库允许多个事务同时对数据进行处理。每个事务之间是相互隔离。
4、持久性 D
事务结束以后,对数据的增删改是永久性的。
术语:提交事务,回滚事务(事务回滚)
1、事务一旦提交,就不可能回滚。
2、当一个连接对象被创建时,默认情况下自动提交事务。
3、关闭连接时,数据会自动提交事务。
操作事务的步骤
关闭事务的自动提交,当做出增删改操作,把变化发生在内存中,提交事务,才会真正提交给数据库。
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);
}
}
}
标签:String,rs,19,张鑫,08,score,id,conn,pstmt
From: https://www.cnblogs.com/zxscj/p/16603379.html