天天看点

一种不太合规的PreparedStatement使用方式

这是一种不太合规的PreparedStatement调用使用方式 , 没有让Dao单独执行它单纯的任务.

AccountDao.java

package heartl_jdbc;

/**
 * 银行操作系统构建snapshot
 */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class AccountDao {
    static Scanner in = new Scanner(System.in);
    String sql;

    ////////////////////////////////////////////////////
    ///// * 获取Connection连接对象 
    ///// * public static Connection jdbcStart() 
    ////////////////////////////////////////////////////
    public static Connection jdbcStart() throws ClassNotFoundException, SQLException {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:XE", "hr", "system");
        return conn;
    }

    /////////////////////////////////////////////////////////////////////////////////////
    ///// * 插入新用户 
    ///// * insertAccount() 
    /////////////////////////////////////////////////////////////////////////////////////
    protected void insertAccount() throws ClassNotFoundException, SQLException {
        String sql = "insert into Account values(seq_account.nextval,?,?,?)";
        PreparedStatement ps = jdbcStart().prepareStatement(sql);
        // 将新的ps传入到insertPPS
        PreparedStatement psnew = TestAccountDao.insertPS(ps);

        long start = System.currentTimeMillis();
        boolean insertOk = psnew.execute();
        if (insertOk) {
            System.out.println("插入数据成功!");
            long end = System.currentTimeMillis();
            long useTime = end - start;
            System.out.println("与数据库交互完成!,耗时:" + useTime + "毫秒.");
            psnew.close();
            ps.close();
            jdbcStart().close();
        }

    }

    /////////////////////////////////////////////////////////////////////////////////////
    ///// * 更改用户的:用户名/密码/余额 
    ///// * updateAccount(String 选择number) 
    /////////////////////////////////////////////////////////////////////////////////////
    protected static void updateAccount(String selectStr) throws ClassNotFoundException, SQLException {
        String nameSql = "update Account set user_name = ? where user_name= ?";
        String passSql = "update Account set user_password = ? where user_name= ?";
        String balanceSql = "update Account set user_balance = user_balance  +? where user_name = ?";
        if (selectStr.equals("1")) {
            PreparedStatement namePs = AccountDao.jdbcStart().prepareStatement(nameSql);
            PreparedStatement namePsNew = TestAccountDao.updatePS(namePs, "1");
            long start = System.currentTimeMillis();
            int nChange = namePsNew.executeUpdate();
            if (nChange == 1) {
                System.out.println("姓名更改成功!");
                long end = System.currentTimeMillis();
                long useTime = end - start;
                System.out.println("与数据库交互完成!,耗时:" + useTime + "毫秒.");
                namePsNew.close();
                namePs.close();
                jdbcStart().close();
            }
        } else if (selectStr.equals("2")) {
            PreparedStatement passPs = AccountDao.jdbcStart().prepareStatement(passSql);
            PreparedStatement passPsNew = TestAccountDao.updatePS(passPs, "2");
            long start = System.currentTimeMillis();
            int pChange = passPsNew.executeUpdate();
            if (pChange == 1) {
                System.out.println("密码更改成功!");
                long end = System.currentTimeMillis();
                long useTime = end - start;
                System.out.println("与数据库交互完成!,耗时:" + useTime + "毫秒.");
                passPsNew.close();
                passPs.close();
                jdbcStart().close();
            }

        } else if (selectStr.equals("3")) {
            PreparedStatement balancePs = AccountDao.jdbcStart().prepareStatement(balanceSql);
            PreparedStatement balancePsNew = TestAccountDao.updatePS(balancePs, "3");
            long start = System.currentTimeMillis();
            int bChange = balancePsNew.executeUpdate();
            if (bChange == 1) {
                System.out.println("余额更改成功!");
                long end = System.currentTimeMillis();
                long useTime = end - start;
                System.out.println("与数据库交互完成!,耗时:" + useTime + "毫秒.");
                balancePsNew.close();
                balancePs.close();
                jdbcStart().close();
            }
        }

    }

    //////////////////////////////////////////////////////////////////////////////////
    ///// * 按照用户名删除整个用户元组数据 
    ///// * deleteAccount()
    //////////////////////////////////////////////////////////////////////////////////
    protected void deleteAccount() throws ClassNotFoundException, SQLException {
        String sql = "delete from Account where user_name = ?";
        PreparedStatement ps = jdbcStart().prepareStatement(sql);
        PreparedStatement psNew = TestAccountDao.deletePS(ps);
        long start = System.currentTimeMillis();
        boolean isDelete = psNew.execute();
        if (isDelete) {
            System.out.println("删除账户成功~!");
            long end = System.currentTimeMillis();
            long useTime = end - start;
            System.out.println("与数据库交互完成!,耗时:" + useTime + "毫秒.");
        }
    }

}      

TestAccountDao.java

package heartl_jdbc;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

/**
 * Dao的测试类
 * 
 * @author SeeClanUkyo
 *
 */
public class TestAccountDao {

    private static Scanner in = new Scanner(System.in);

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 创建Dao层对象
        AccountDao ad = new AccountDao();
        // TestAccountDao test = new TestAccountDao();
        getHello(ad);

    }

    /////////////////////////////////////////////////////////
    ///// * STEP 1 . 欢迎界面
    ///// * public static void getHello(AccountDao ad) 
    /////////////////////////////////////////////////////////
    public static void getHello(AccountDao ad) throws ClassNotFoundException, SQLException {

        System.out.println("欢迎来到魔偶银行系统,管理员,请选择您要执行的操作\n1.设置账户初始化\n2.更改账户信息\n3.删除账户\n4.下载数据库文件");

        String selectNum = in.next();
        boolean isRightInput = selectNum.equals("1") || selectNum.equals("2") || selectNum.equals("3")
                || selectNum.equals("4");
        if (isRightInput) {
            if (selectNum.equals("1")) {

                ad.insertAccount();
            } else if (selectNum.equals("2")) {
                select_2();
            } else if (selectNum.equals("3")) {
                ad.deleteAccount();
            } else if (selectNum.equals("4")) {
                MariaDownload.downLoadTableData();
            }
        } else {
            System.out.println("对不起,您输入有误,请重新输入:");
            getHello(ad);
        }

    }

    //////////////////////////////////////////////////////////////////////////////////////
    ///// * 插入用户的,用户输入界面
    ///// * protected static PreparedStatement insertPS(PreparedStatement ps) 
    ///// * 半成品的插入SQL语句传递过来,并使用setObject(index,data)方式设置填充SQL(ps)内容并返回.
    //////////////////////////////////////////////////////////////////////////////////////
    protected static PreparedStatement insertPS(PreparedStatement ps) throws SQLException, ClassNotFoundException {
        showUser();
        System.out.println("请输入不同于以上的用户名(用户名大于3位)");
        String username = in.next();
        System.out.println("请输入密码(13位<=密码=>6位)");
        long password = in.nextInt();
        System.out.println("请输入存款金额(金额不能为null,不能为负数,最小为0)");
        String balance = in.next();
        ps.setObject(1, username);
        ps.setObject(2, password);
        ps.setObject(3, balance);

        return ps;
    }

    //////////////////////////////////////////////////////////////
    ///// *选择为2时,再进行区分,询问用户具体要更改哪个字段
    ///// *根据不同的选择,执行不同的字段的操作 
    //////////////////////////////////////////////////////////////
    protected static void select_2() throws ClassNotFoundException, SQLException {
        System.out.println("请问您要更改哪个字段?");
        System.out.println("1.user_name\n2.user_password\n3.user_balance");
        String selectUp = in.next();
        boolean isRightNum = selectUp.equals("1") || selectUp.equals("2") || selectUp.equals("3");
        if (isRightNum) {
            if (selectUp.equals("1")) {
                AccountDao.updateAccount("1");
            } else if (selectUp.equals("2")) {
                AccountDao.updateAccount("2");
            } else if (selectUp.equals("3")) {
                AccountDao.updateAccount("3");
            }
        } else {
            System.out.println("选择错误,没有该字段,请重新选择:");
            select_2();
        }
    }

    /////////////////////////////////////////////////////////////////
    ///// * 更改用户信息,对应上面的select2_() 
    ///// * AccountDao传递过来半成品的Update类型SQL语句.
    ///// * 之后该方法用于接受具体输入,并将设置完整的SQL语句返回给AccountDao执行操作
    /////////////////////////////////////////////////////////////////
    protected static PreparedStatement updatePS(PreparedStatement ps, String selectUp)
            throws ClassNotFoundException, SQLException {

        if (selectUp.equals("1")) {
            showUser();
            System.out.println("请输入您要更改的用户姓名:(现有)");// 单独把遍历用户名的方法提取
            String oldname = in.next();
            ps.setObject(2, oldname);
            System.out.println("请输入要更替为的姓名:(新名称)");
            String newname = in.next();
            ps.setObject(1, newname);
            return ps;

        } else if (selectUp.equals("2")) {
            showUser();
            System.out.println("请输入您要更替密码的用户名:");
            String nameAboutPassword = in.next();
            ps.setObject(2, nameAboutPassword);
            System.out.println("请输入新密码:(13<=密码=>6)number类型");
            long passWNew = in.nextInt();// 超过13 要更改为String 或使用long
            ps.setObject(1, passWNew);
            return ps;
        } else if (selectUp.equals("3")) {
            showUser();
            System.out.println("请输入您要更替余额的账户名称:");
            String nameAboutBalance = in.next();
            ps.setObject(2, nameAboutBalance);
            System.out.println("请输入要+的钱数或-的钱数,加上+/-号");
            long changBalance = in.nextLong();
            ps.setObject(1, changBalance);
            return ps;
        } else {
            return ps;
        }

    }

    ////////////////////////////////////////////////////////////////
    ///// * 接受半成品删除SQL语句,该方法进行完整设置并返回到AccountDao进行执行
    ////////////////////////////////////////////////////////////////
    public static PreparedStatement deletePS(PreparedStatement ps) throws ClassNotFoundException, SQLException {
        showUser();
        System.out.println("请输入要删除的用户名:");
        String deleteName = in.next();
        ps.setObject(1, deleteName);
        return ps;
    }

    ///////////////////////////////////////////////////////////////////////////////
    ///// * 遍历现有用户 from Account */////
    ///// * public static void showUser() *////////////////////////////////////////
    public static void showUser() throws ClassNotFoundException, SQLException {
        System.out.println("现有用户为:");
        String sqlname = "select user_name from Account";
        PreparedStatement nameps = AccountDao.jdbcStart().prepareStatement(sqlname);
        ResultSet rsnow = nameps.executeQuery();
        while (rsnow.next()) {
            System.out.println(rsnow.getString("user_name"));
        }
    }

}      

PreparedStatement预防sql注入危险,传值时使用setObject(位置,数据)进行传值预处理. (或者setString(),,setInt()等.)

这样对PreparedStatement的实例ps进行了来回的传送,看起来很繁琐.也可以这样,似乎好了些:

其中一边传入数据.

ArrayList<Object> userDatas_Reg = new ArrayList<>();
            String register_SQL = null;
            userDatas_Reg.add(getUserName());
            userDatas_Reg.add(getPassWord());
            userDatas_Reg.add(getSex());
            userDatas_Reg.add(getNickName());
            userDatas_Reg.add(getAge());
            userDatas_Reg.add(getIdentity());
            register_SQL = "insert into lib_users values(seq_lib_users.nextval,?,?,?,?,?,?,sysdate,seq_card_id.nextval)";
            MariaSQLManager.sql_Handler(register_SQL,userDatas_Reg);
                  

另一边的接收半成品sql和数据集合,其将这两个传入值传入getFullPreparedStatementPS进行了设置

//设置sql_Handler的重载形式 多个值的设置
        protected static void sql_Handler(String half_SQL, ArrayList<Object> userDatas) {
        // Connection conn = MariaTools.jdbcStart();
        // PreparedStatement ps = conn.prepareStatement(half_SQL);
        int sql_type = sql_Judger(half_SQL);
        PreparedStatement ps = MariaTools.getFullPreparedStatementPS(half_SQL, userDatas);
        ResultSet rs = null;
        LoginStuff log = new LoginStuff();
        log.set_NamePasswordOk(false);
        try {

            if (sql_type == 1) {
                rs = ps.executeQuery();
                if (rs.next()) {
                    log.set_NamePasswordOk(true);
                }
            }
            if (sql_type == 2) {
                for (int i = 0; i < userDatas.size(); i++) {
                    ps.setObject(i + 1, userDatas.get(i));
                }
                ps.executeUpdate();
            }
            // 如果有结果集返回,说明用户名和密码正确了
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }      

但因为都是setObject,而没有针对某一种数据进行不同的set,显得不是很合规

///// * 对半成品的sql进行填全工具 */////
    public static PreparedStatement getFullPreparedStatementPS(String sql, ArrayList<Object> userDatas) {
        // 传入一个setObject的需求的总数量
        PreparedStatement ps = null;
        try {
            ps = MariaTools.jdbcStart().prepareStatement(sql);
            for (int i = 0; i < userDatas.size(); i++) {
                ps.setObject(i + 1, userDatas.get(i));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ps;
    }      

看来需要对整个的JDBC的规范写法有所了解才可以!

将编程看作是一门艺术,而不单单是个技术。

敲打的英文字符是我的黑白琴键,

思维图纸画出的是我编写的五线谱。

当美妙的华章响起,现实通往二进制的大门即将被打开。