这是一种不太合规的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的规范写法有所了解才可以!
将编程看作是一门艺术,而不单单是个技术。 敲打的英文字符是我的黑白琴键, 思维图纸画出的是我编写的五线谱。 当美妙的华章响起,现实通往二进制的大门即将被打开。