jdbc mysql url写法_凯哥带你从零学大数据系列之数据库篇---第三章:JDBC基础

121efef1bba4fc29dc88f8fdcb76bef8.png

温馨提示:如果想学扎实,一定要从头开始看凯哥的一系列文章(凯哥带你从零学大数据系列),千万不要从中间的某个部分开始看,知识前后是有很大关联,否则学习效果会打折扣.

系列文章第一篇是拥抱大数据:凯哥带你从零学大数据系列-学习大数据前奏(必读)(点我)!

正课内容

知识点:

1.JDBC概述

2.JDBC原理

3.JDBC使用

4.事务

教学重点:

1.JDBC的使用

2.事务

第一章:JDBC的简介

1.1 需求

早期的数据库应用程序开发,因为没有通用的针对与数据库的编程接口,所以,开发人员需要学习相关数据库的API,才可以进行应用程序,这样增加了学习成本和开发周期。因此整个开发市场一直在呼吁有一套通用的编程接口

1.2 ODBC

因为有市场需要,微软定义了一组用于数据库应用程序的编程接口ODBC(open database connectivity)。这一套方案大大缩短了程序的开发周期,可以让开发人员只需要调用同一套编程接口,无需考虑具体实现。

935f7cb6b8fc3d97c39909f7b3d26ffd.png

ODBC分为四个部分:

1. 应用程序:开发人员所写的代码,ODBC提供的调用接口
2. 驱动程序管理器:用于管理驱动程序的。
3. 驱动程序:对接口的实现部分,各个数据库厂商来完成的。
4. 数据源:就是连接数据库的一些参数:url,username,password

1.3 JDBC

Sun公司参考了ODBC方案,制定了一组专门为java语言连接数据库的通用接口JDBC。方便了java开发人员,开发人员不需要考虑特定的数据库的DBMS。JDBC不直接依赖于DBMS,而是通过驱动程序将sql语句转发给DBMS,由DBMS进行解析并执行,处理结果返回。 

<font color='red'>注意:</font>驱动程序:由数据库厂商自己实现,程序员只需要拿来使用即可。

a8b4bcb413d8249418bfb627d3a21495.png

1.4 JDBC的工作原理

f20dda3ed17008f70e9f0f1092e8dbe7.png
第一步:注册驱动程序 
第二步: 请求连接 
第三步: 获取执行sql语句的对象,发送给DBMS 
第四步:返回结果集,程序员进行处理 
第五步: 关闭连接操作

1.5 JDBC中常用的接口和类

1.5.1 java.sql.DriverManager:类,用于连接数据库,返回Connection对象

getConnection(String url, String user, String password)
url: 连接指定数据库的地址 jdbc:mysql://ip:port/dbname 
user: 连接用户名 
password:密码

1.5.2 java.sql.Connection:是接口。

Statement createStatement();
作用:用于获取Statement对象

1.5.3 java.sql.Statement:接口

execute(String sql):通常用于DDL 
executeUpdate(String sql):通常用于DML 
executeQuery(String sql):用于DQL

1.5.4 java.sql.ResultSet:接口,其子类型封装了DQL的返回值

next():光标方法,向下移动一行,
​
getDate(int columnIndex)
getDate(String columnLabel)
​
getString(int columnIndex) 
getString(String columnLabel)
​
getInt(int columnIndex) 
getInt(String columnLabel)
​
getDouble(int columnIndex) 
getDouble(String columnLabel)

第二章:JDBC入门编程

2.1 编写步骤

1. 创建项目,加载相应的静态资源,如图片、第三方jar包等
  注意:jar包要add到Library里
2. 注册驱动
3. 建立连接
4. 获取执行对象
5. 处理结果集
6. 关闭连接

2.2 编写测试类:update

public static void main1(String[] args) throws ClassNotFoundException, SQLException {
    //第一步:加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    //第二步:建立连接
    Connection conn =DriverManager
    .getConnection("jdbc:mysql://localhost:3306/qianfeng","root","123456");
    //第三步:获取执行对象Statement
    Statement stat = conn.createStatement();
    String sql = "update emp set sal = 10000,comm = 500 where empno = 9000";
    //第四步:调用方法执行sql,即发送sql
    int num = stat.executeUpdate(sql);
    System.out.println("受影响的记录数目:"+num);
    //第五步:关闭连接
    conn.close();
}

3.3 编写DQL

public void test2(){
    Connection conn = null;
    Statement stat = null;
    ResultSet rs = null;
    try{
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //建立连接
        conn = DriverManager
        .getConnection("jdbc:mysql://localhost:3306/qianfeng","root","123456");
        //获取执行对象,执行sql
        stat = conn.createStatement();
        //返回结果集
        rs = stat.executeQuery("select * from emp");
        while(rs.next()){
            int empno = rs.getInt(1);
            String ename = rs.getString("ename");
            Date hiredate = rs.getDate("hiredate");
            double salary = rs.getDouble("sal");
            System.out.println(empno+","+ename+","+hiredate+","+salary);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try {
            rs.close();
            stat.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

2.4 练习:插入和删除的代码

1.完成向表中插入一条记录的代码
2.完成从表中删除一条记录的代码

2.5 DBUtil工具类的封装

2.5.1 配置文件db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/qianfeng
username=root
passwd=123456

2.5.2 DBUtil代码

/**
 * 封装了一些对数据库的连接和关闭操作
 */
public class DBUtil {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    static{

        try{
            //读取配置文件:
            InputStream is = DBUtil.class.getClassLoader()
            .getResourceAsStream("db.properties");
            //获取Properties对象
            Properties p = new Properties();
            //把流里的内容加载到p对象中
            p.load(is);
            //取value值
            driver = p.getProperty("driver");
            url = p.getProperty("url");
            username = p.getProperty("username");
            password = p.getProperty("pwd");
            //注册驱动
            Class.forName(driver);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 连接数据库的方法
     * @return Connection对象
     */
    public static Connection getConnection() throws SQLException{
        Connection conn = DriverManager.getConnection(url,username,password);
        return conn;
    }

    /**
     * 关闭连接操作
     *  关闭ResultSet对象
     *  关闭Statement对象
     *  关闭Connection对象
     */
    public static void closeConnection(Connection conn, Statement stat, ResultSet rs){
        try {
            if(rs!=null){
                rs.close();
            }
            if(stat!=null){
                stat.close();
            }
            if(conn !=null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws SQLException {
        Connection conn = getConnection();
        System.out.println(conn);
        closeConnection(conn,null,null);
    }
}`

2.5.3 修改代码:调用DBUtil工具

1)update代码的修改

public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Connection conn = DBUtil.getConnection();
        //第三步:获取执行对象Statement
        Statement stat = conn.createStatement();
        String sql = "update emp set sal = 10000,comm = 500 where empno = 9000";
        //第四步:调用方法执行sql,即发送sql
        int num = stat.executeUpdate(sql);
        System.out.println("受影响的记录数目:"+num);
        //第五步:关闭连接
        DBUtil.closeConnection(conn,stat,null);
}

2)DQL代码的修改

public void test1(){
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try{
            conn = DBUtil.getConnection();
            //获取执行对象,执行sql
            stat = conn.createStatement();
            //返回结果集
            rs = stat.executeQuery("select * from emp");
            while(rs.next()){
               int empno = rs.getInt(1);
               String ename = rs.getString("ename");
               Date hiredate = rs.getDate("hiredate");
               double salary = rs.getDouble("sal");
               System.out.println(empno+","+ename+","+hiredate+","+salary);
           }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
           DBUtil.closeConnection(conn,stat,rs);
        }
}`

2.6 jdbc的批处理

2.6.1 概念

每一次的sql操作都会占用数据库的资源。如果将N条操作先存储到缓存区中,然后再一次性刷到数据库中,这就减少了与数据库的交互次数。因此可以提高效率。

2.6.2 Statement

addBatch(String sql):将sql语句添加到缓存中
executeBatch():将缓存中的sql一次性刷到数据库中

2.6.3 代码

@Test
public void testBatch(){
    Connection conn = null;
    Statement stat = null;
    try{
        conn = DBUtil.getConnection();
        stat = conn.createStatement();
        int num = 0;
        while(num<1003){
            String sql = "insert into testbatch values (null,'zs"+num+"','f')";
            stat.addBatch(sql);//将sql语句添加到缓存中,
            if(num%50==0){
                stat.executeBatch();//缓存中每有50条都刷新一次。
            }
            num++;
        }
        stat.executeBatch();//循环结束后,将缓存中剩余的不足50条的全都刷新出去
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        DBUtil.closeConnection(conn,stat,null);
    }
}

第三章:SQL注入问题

3.1 登陆案例演示

3.1.1 登陆案例需求分析:

1.需求:实现输入用户名和密码后,实现跳转到主页面的功能
2.逻辑分析:
- 客户端:接收用户名和密码,并将这些信息发送到服务端
- 服务端:接收到客户端传过来的用户名和密码后,进行数据库校验是否存在这样的数据,如果存在,就将
用户名对应的这一条记录返回,并封装成一个User对象。返回给客户端。
- 客户端收到返回信息后,判断Account对象是否存在,如果存在,就实现跳转.....

数据:

drop table if exists bank_account;
create table bank_account (
id int primary key auto_increment comment '主键',
account_id varchar(18) not null comment '用户账号',
account_balance double(10,2) comment '账户余额',
user_name varchar(20) not null comment '用户名称',
user_pwd varchar(18) unique comment '用户密码',
user_idcard varchar(18) unique comment '身份证',
oper_time timestamp comment '操作日期',
gender enum('f','m') comment 'f 表示女性,m表示男性'
);

insert into bank_account values (null,'6225113088436225',200000,'zhugeliang','zgl123456','100000100010101000','2019-01-01 13:10:10','m');
insert into bank_account values (null,'6225113088436226',1000,'zhouyu','zy123456','100000100010101001','2019-03-01 14:10:10','m');
insert into bank_account values (null,'6225113088436227',210000,'caocao','cc123456','100000100010101002','2019-04-01 14:10:10','m');
insert into bank_account values (null,'6225113088436228',500,'niumo','nm123456','100000100010101003','2019-03-01 10:10:10','m');
commit;
select * from banK_account;

3.1.2 User类型的定义

package com.jdbc.day02.login;

import java.sql.Date;
import java.util.Objects;

/**
 * @Description 把表中的每一条记录封装成一个Account对象
 */
public class Account {
    private int id;
    private String accountId;
    private double balance;
    private String username;
    private String password;
    private String idcard;
    private Date operationTime;
    private String gender;

    public Account(){}

    public Account(int id, String accountId, double balance, String username, String password, String idcard, Date operationTime, String gender) {
        this.id = id;
        this.accountId = accountId;
        this.balance = balance;
        this.username = username;
        this.password = password;
        this.idcard = idcard;
        this.operationTime = operationTime;
        this.gender = gender;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getIdcard() {
        return idcard;
    }

    public void setIdcard(String idcard) {
        this.idcard = idcard;
    }

    public Date getOperationTime() {
        return operationTime;
    }

    public void setOperationTime(Date operationTime) {
        this.operationTime = operationTime;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account account = (Account) o;
        return id == account.id &&
                Double.compare(account.balance, balance) == 0 &&
                Objects.equals(accountId, account.accountId) &&
                Objects.equals(username, account.username) &&
                Objects.equals(password, account.password) &&
                Objects.equals(idcard, account.idcard) &&
                Objects.equals(operationTime, account.operationTime) &&
                Objects.equals(gender, account.gender);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, accountId, balance, username, password, idcard, operationTime, gender);
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", accountId='" + accountId + ''' +
                ", balance=" + balance +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                ", idcard='" + idcard + ''' +
                ", operationTime=" + operationTime +
                ", gender='" + gender + ''' +
                '}';
    }
}

3.1.3 服务端的代码

package com.jdbc.day02.login;

import com.jdbc.util.DButil;

import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * @Description 用于检查数据库中是否存在含有客户端发送过来的username和password这样的账号信息
 */
public class AppServer {
    public static Account checkLogin(String username,String password){
        //将形式参数放到一个sql语句中,发送到数据库中,进行检验
        Connection conn =null;
        Statement stat = null;
        ResultSet rs = null;
        Account account = null;
        try{
            conn = DButil.getConnection();
            stat = conn.createStatement();
            String sql = "select * from bank_account where user_name='"+username+"' and user_pwd='"+password+"'";
            rs = stat.executeQuery(sql);
            if(rs.next()){
                int id = rs.getInt("id");
                String accountId = rs.getString("account_id");
                double balance = rs.getDouble("account_balance");
                String idcard = rs.getString("user_idcard");
                Date operationTime = rs.getDate("oper_time");
                String gender = rs.getString("gender");
                account = new Account(id,accountId,balance,username,password,idcard,operationTime,gender);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DButil.closeConnection(conn,stat,rs);
        }
        return account;
    }
}

3.1.4 客户端的代码

package com.jdbc.day02.login;

import java.util.Scanner;

/**
 * @Description 模拟银行客户端程序
 */
public class Client {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.next();
        System.out.println("请输入密码:");
        String password = "haha' or '1' = '1";
        /**
         * 将数据发送到服务端:(调用服务端的相关方法)
         * 即调用服务端的静态方法checkLogin().
         * 如果能查询到信息,就返回一个Account类型的对象
         */
        Account account = AppServer.checkLogin(username,password);
        if(account!=null){
            System.out.println("--正在跳转到主页面--");
        }else{
            System.out.println("----用户名或密码错误,请重写输入----------");
        }
    }
}

3.2 SQL注入问题(安全隐患)

3.2.1 安全隐患

Statament对象发送的语句可以被改变结构,即如果之前在where中设置的是两个条件,那么可以通过一些参数 比如 添加or 后面再跟其他条件。此时,where子句中是三个条件。这种情况就叫做SQL注入。有安全隐患问题。

3.3 PreparedStatement类

3.3.1 预编译类的简介

- PreparedStatement是Statement的子类型
- 此类型可以确定SQL语句的结构,无法通过其它方式来增减条件。
- 此类型还通过占位符 "?"来提前占位,并确定语句的结构。
- 提供了相应的赋值方式:
  ps.setInt(int index,int value) 
  ps.setString(int index,String value) 
  ps.setDouble(int index,double value) 
  ps.setDate(int index,Date value)
​
index:表示sql语句中占位符?的索引。从1开始 
value:占位符所对应的要赋予的值
- 执行方法: 
  ps.execute() ;------用于DDL和DML 
  ps.executeUpdate();-----用于DML 
  ps.executeQuery();-----用于DQL

3.3.2 修改了Server里的代码

/**
 * @Description 使用PreparedStatement实现服务端
 */
public class PrepareServer {
    public static User checkLogin(String username,String pwd){
        if(username==null||username.length()==0){
            return null;
        }
        if(pwd==null||pwd.length()==0){
            return null;
        }
        //将数据传入持久层
        Connection conn = null;
        // 将Statement 换成 PreparedStatement
        PreparedStatement ps = null;
        ResultSet rs = null;
        User user = null;
        try{
            conn = DBUtil.getConnection();
            //sql语句放在获取预编译执行对象前,同时可以使用它占位符
            String sql = "select * from emp where ename = ? and empno = ?";
            //获取预编译执行对象,同时传入sql参数
            ps = conn.prepareStatement(sql);
            //给占位符赋值
            ps.setString(1,username);
            ps.setInt(2,Integer.valueOf(pwd));

            //调用执行查询的方法,不带参数。
            rs = ps.executeQuery();
            if(rs.next()){
                int empno = rs.getInt(1);
                String ename = rs.getString(2);
                String job = rs.getString(3);
                int mgr = rs.getInt(4);
                Date hiredate = rs.getDate(5);
                double salary = rs.getDouble(6);
                double comm = rs.getDouble(7);
                int deptno = rs.getInt(8);
                user = new User(empno,ename,job,mgr,hiredate,salary,comm,deptno);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            DBUtil.closeConnection(conn,ps,rs);
        }
        return user;
    }
}

3.3.3 客户端的代码

/**
 * @Description 修改客户端实现
 */
public class Client {
    public static void main(String[] args) {
        //        Scanner sc = new Scanner(System.in);
        //        System.out.println("请输入用户名:");
        //        String username = sc.next();
        //        System.out.println("请输入密码:");
        //        String password = sc.next();

        String username = "smith";
        String password = "222 or 1=1";
        //调用服务端的代码
        //User user = Server.checkLogin(username,password);
        //换成修改后的服务端的代码
        User user = PrepareServer.checkLogin(username,password);
        if(user!=null){
            System.out.println("登陆成功,页面跳转中..........");
        }else{
            System.out.println("登陆失败,请检查用户名或者密码");
        }
    }
}

第四章:JDBC的事务支持

4.1 银行转账案例演示

4.4.1 案例分析:

1.需求:一个账号fromAccount向另一个账号toAccount转入money元钱
2.分析:
- 检查两个账号是否存在,不存在的话,结束转账行为
- 检查转出账号的里金额是否充足,不充足,结束转账行为,充足的话,进行扣款money元
- 转入账号进行增加money元

4.4.2 代码实现:

/**
 * @Description 银行转账案例
 */
public class AccountTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要出账的账号和进账的账号");
        String fromAccount = sc.next();
        String toAccount = sc.next();
        System.out.println("请输入转账金额:");
        double money = sc.nextDouble();
        boolean flag = oneToOne(fromAccount,toAccount,money);
        if(flag){
            System.out.println("success");
        }else{
            System.out.println("fail");
        }
    }

    /**
     * 封装了两个人之间的转账逻辑
     *  true:表示转账成功
     *  false:表示转账失败
     */
    public static boolean oneToOne(String fromAccount,String toAccount,double money){
        /*第一步:先校验账户信息是否有效*/
        if(fromAccount==null||fromAccount.length()==0){
            return false;
        }
        if(toAccount==null||toAccount.length()==0){
            return false;
        }
        if(money<=0){
            return false;
        }
        Connection conn = null;
        //预编译sql语句执行对象
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
            
            //验证转出账号是否存在
            conn = DBUtil.getConnection();
            String sql1 = "select * from bank_account where account_id=?";
            ps = conn.prepareStatement(sql1);
            ps.setString(1,fromAccount);
            rs = ps.executeQuery();
            boolean flag = rs.next();
            if(!flag){
                System.out.println("出账账号不存在");
                return false;
            }
            
            //,如果存在,先提取出余额,保存到一个变量中
            double balance = rs.getDouble("account_balance");

            //验证进账账号是否存在
            sql1 = "select * from bank_account where account_id=?";
            ps = conn.prepareStatement(sql1);
            ps.setString(1,toAccount);
            rs = ps.executeQuery();
            flag = rs.next();
            if(!flag){
                System.out.println("进账账号不存在");
                return false;
            }
            
          
			/*第二步:检查formAccount账户内的余额,足够的前提下,修改余额*/
            //判断出账账号的余额是否充足
            if(money>balance){
                System.out.println("余额不足");
                return false;
            }

            //此时,来到此处后就可以进行转账业务了
            //先扣除出账账号的money
            String sql2 = "update bank_account set account_balance=account_balance-? where account_id = ?";
            ps = conn.prepareStatement(sql2);
            ps.setDouble(1,money);
            ps.setString(2,fromAccount);
            ps.executeUpdate();

            /*第三步:修改toAccount账户内的余额*/
            //进账账号再+money
            String sql3 = "update bank_account set account_balance=account_balance+? where account_id = ?";
            ps = conn.prepareStatement(sql3);
            ps.setDouble(1,money);
            ps.setString(2,toAccount);
            ps.executeUpdate();
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            DBUtil.closeConnection(conn,ps,rs);
        }
        return false;
    }
}

4.2 转账异常演示

在转出账户转出金额之后 和 转入账户收入金额之前模拟 空指针异常
​
String str = null;
System.out.println(str.length());

4.3 JDBC的事务支持

4.3.1 事务的概念:

当一个业务需求涉及到N个DML操作时,这个业务(或者时N个DML操作)当成一个整体来处理。在处理的过程中,如果有失败或异常,我们要回到业务开始时。如果成功处理,我们再将数据持久化到磁盘中。这样一个过程我们称之为一个事务。具有原子性。不可切割。
关键字:
commit
rollback
savepoint

4.3.2 事务的特性:

59d55c178864fa06673d0702dca4b001.png

4.3.3 MySQL事务

- 默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。
- 如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。
开启事务:start transaction;
结束事务:commit或rollback;

回滚情况

START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
SELECT * FROM account;
UPDATE account SET balance=balance+10000 WHERE id=2;
ROLLBACK;

提交情况

START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
SELECT * FROM account;
UPDATE account SET balance=balance+10000 WHERE id=2;
COMMIT;

4.3.4 JDBC的事务支持

Connection.setAutoCommit(boolean flag):此方法可以取消事务的自动提交功能,值为false。  
Connection.commit():进行事务提交   。  
Connection.rollback():进行事务回滚。  

4.3.3 多事务的情况:

14ec78d363a1fe79b12408c19bd36fee.png

4.3.4 隔离机制

55819cdded199220d682f88de871e83c.png

4.4 修改转账代码:改为手动提交

public static boolean oneToOne(String fromAccount, String toAccount, double money) {
    /*第一步:先校验账户信息是否有效*/
    if (fromAccount == null || fromAccount.length() == 0) {
        return false;
    }
    if (toAccount == null || toAccount.length() == 0) {
        return false;
    }
    if (money <= 0) {
        return false;
    }
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
        conn = DBUtil.getConnection();
        
        //取消事务自动提交功能,改为手动提交
        conn.setAutoCommit(false);
        
        String sql1 = "select * from bank_account where account_id=?";
        ps = conn.prepareStatement(sql1);
        ps.setString(1, fromAccount);
        rs = ps.executeQuery();
        boolean flag = rs.next();
        if (!flag) {
            System.out.println("出账账号不存在");
            return false;
        }
        /*第二步:检查formAccount账户内的余额,足够的前提下,修改余额*/
        //取出余额
        double balance = rs.getDouble("account_balance");

        //sql1 = "select * from bank_account where account_id=?";
        //ps = conn.prepareStatement(sql1);
        ps.setString(1, toAccount);
        rs = ps.executeQuery();
        flag = rs.next();
        if (!flag) {
            System.out.println("进账账号不存在");
            return false;
        }
		
        //判断出账账号的余额是否充足
        if (money > balance) {
            System.out.println("余额不足");
            return false;
        }

        //此时,来到此处后就可以进行转账业务了
        //先扣除出账账号的money
        String sql2 = "update bank_account set account_balance=account_balance-? where account_id = ?";
        ps = conn.prepareStatement(sql2);
        ps.setDouble(1, money);
        ps.setString(2, fromAccount);
        ps.executeUpdate();

        //模拟一个空指针异常
        String str = null;
        System.out.println(str.length());
		/*第三步:修改toAccount账户内的余额*/
        //进账账号再+money
        String sql3 = "update bank_account set account_balance=account_balance+? where account_id = ?";
        ps = conn.prepareStatement(sql3);
        ps.setDouble(1, money);
        ps.setString(2, toAccount);
        ps.executeUpdate();

        //手动提交事务
        conn.commit();
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        //当出现异常,我们才需要回滚事务
        try{
            conn.rollback();
        }catch (Exception e1){
            e1.printStackTrace();
        }
    } finally {
        DBUtil.closeConnection(conn, ps, rs);
    }
    return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值