一.预编译命令对象
1.PreparedStatement
- 继承自 statement接口
- 预编译的sql语句对象;
- 对sql语句进行预编译,存储到PreparedStatement对象中,可以多次执行命令,提高效率。
- 杜绝sql注入式攻击,安全性高。使用的是参数式的sql命令。
使用PrepareStatement实现数据库操作
String sql =
"select * from student where name=? or sex = ? or phone=?"
PreparedStatement pst = 连接对象.prepareStatement(sql);
pst.setObject(1,"张三");
pst.setObject(2,"男");
pst.setObject(3,"131123123");
pset.setObject(4,"xx"); #没有第四个参数,不能写,报错
二.获取自增列的值
关键代码:
/获取自增返回的结果集对象
rs = pst.getGeneratedKeys();
int id=0;
if(rs.next()){
id=rs.getInt(1);
}
三.事务
什么是事务?
一种机制:确保一系列的数据操作作为原子(整体)去执行,要么都执行,要么都不执行(回滚);
数据库表:
create table bank
(
bid int auto_increment primary key,
accountName varchar(20),
money float(5,1)
)
insert into bank
(accountName,money)
select '张三',9999.9 union
select '李四',9999.9
java中如何处理事务?
事务的四个特性:ACID是原子性(atomicity)、一致性(consistency)、隔离性 (isolation)和持久性(durability)的缩写。
事务的原子性:事务作为整体执行,要么都成功,要么都回滚。
事务的一致性:表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态。
事务的隔离性:多个事务在并发执行过程中,是相互独立的(隔离的)比如:售票过程。
事务的持久性:事务对数据库所做的操作是永久性的。
JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。
java.sql.Connection 提供了以下控制事务的方法:
public void setAutoCommit(boolean) 设置事务的提交方式
public boolean getAutoCommit() --获取自动提交的状态
public void commit() --提交事务
public void rollback() --回滚事务
关键代码:
con = getConnection();
//设置手动事务
con.setAutoCommit(false);
//提交事务
con.commit();
//回滚事务
con.rollback();
完整应用实例,封装BaseDao
为了减少冗余代码
BaseDao:
package com.util;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BaseDAO {
// 四大金刚
private static String driver = "com.mysql.cj.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/qy149_student?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
private static String user = "root";
private static String password = "123456";
// 获取连接
public static Connection getConnection(){
Connection con = null;
try{
// 加载mysql驱动类
Class.forName(driver);
// 用DriverManager获取连接对象
con = DriverManager.getConnection(url,user,password);
}catch(Exception ex){
ex.printStackTrace();
}
return con;
}
// 关闭数据库对象
public static void closeAll(Connection con,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
if(st!=null){
try{
st.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
if(con!=null){
try{
con.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
//通用设置参数的方法
public static void setParams(PreparedStatement pst,Object...params){
for(int i=0;i<params.length;i++){
try {
pst.setObject(i+1,params[i]);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
// 通用增删改
// Object...params:可变长度参数,本质是数组
public static int executeUpdate(String sql,Object...params){
// 定义连接对象
Connection con = null;
//定义预编译命令对象
PreparedStatement pst = null;
//定义返回的影响行数
int count = -1;
try{
// 获取连接
con = getConnection();
// 获取预编译命令对象
pst = con.prepareStatement(sql);
// 设置参数
setParams(pst,params);
//执行sql
count = pst.executeUpdate();
}catch(Exception ex){
ex.printStackTrace();
}finally{
closeAll(con,pst,null);
}
// 返回行数
return count;
}
// 通用查询:传入sql和参数,返回一个List<Map>集合
public static List<Map> executeQuery(String sql, Object...params){
// 定义集合用于存储查询结果的表数据
List<Map> rows = new ArrayList<>();
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
// 获取连接
con = getConnection();
// 获取命令对象
pst = con.prepareStatement(sql);
// 设置参数
setParams(pst,params);
// 执行查询
rs = pst.executeQuery();
// 获取结果集的结构对象
ResultSetMetaData rsmd = rs.getMetaData();
// 遍历读取结果数据
while (rs.next()){
// 定义Map存储遍历到的当前行的各个列的数据
Map map = new HashMap();
// 循环遍历当前行的各个列
// 注意:i从1开始,小于等于列的长度
for (int i=1;i<=rsmd.getColumnCount();i++){
//map.put(列名,列值): 列明属于结构要用rsmd获取 列值是内容用rs获取
map.put(rsmd.getColumnName(i),rs.getObject(i));
}
// 将存储号的当前行的各个列的数据封装的Map,放入到List中
rows.add(map);
}
}catch (Exception ex){
ex.printStackTrace();
}finally {
closeAll(con,pst,rs);
}
// 返回封装的表结果
return rows;
}
}