时间:2021-07-01 10:21:17 帮助过:5人阅读
上面的查询使用的是Statement对象,但是有一个缺点就是可能存在Sql攻击德尔问题,可以使用PreapredStatement对象最为替代,
1 import java.io.IOException; 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.Statement; 8 9 import org.junit.Test; 10 11 12 /** 13 * PreapredStatement的使用: 14 * 防SQL攻击 15 * @author cxf 16 * 17 */ 18 public class Demo2 { 19 /** 20 * 登录 21 * 使用username和password去查询数据 22 * 若查出结果集,说明正确!返回true 23 * 若查出不出结果,说明用户名或密码错误,返回false 24 * @param username 25 * @param password 26 * @return 27 * @throws Exception 28 */ 29 public boolean login(String username, String password) throws Exception { 30 /* 31 * 一、得到Connection 32 * 二、得到Statement 33 * 三、得到ResultSet 34 * 四、rs.next()返回的是什么,我们就返回什么 35 */ 36 // 准备四大参数 37 String driverClassName = "com.mysql.jdbc.Driver"; 38 String url = "jdbc:mysql://localhost:3306/test"; 39 String mysqlUsername = "root"; 40 String mysqlPassword = "920346"; 41 // 加载驱动类 42 Class.forName(driverClassName); 43 // 得到Connection 44 Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword); 45 46 // 得到Statement 47 Statement stmt = con.createStatement(); 48 49 // 给出sql语句,调用stmt的executeQuery(),得到ResultSet 50 String sql = "select * from j_stu where username=‘" + username + "‘ and password=‘" + password + "‘"; 51 System.out.println(sql); 52 ResultSet rs = stmt.executeQuery(sql); 53 54 return rs.next(); 55 } 56 57 /** 58 * SQL攻击! 59 * @throws Exception 60 */ 61 @Test 62 public void fun1() throws Exception { 63 //select * from t_user where username=‘a‘ or ‘a‘=‘a‘ and password=‘a‘ or ‘a‘=‘a‘ 64 String username = "a‘ or ‘a‘=‘a"; 65 String password = "a‘ or ‘a‘=‘a"; 66 boolean bool = login(username, password); 67 System.out.println(bool); 68 } 69 70 public boolean login2(String username, String password) throws Exception { 71 /* 72 * 一、得到Connection 73 * 二、得到Statement 74 * 三、得到ResultSet 75 * 四、rs.next()返回的是什么,我们就返回什么 76 */ 77 // 准备四大参数 78 String driverClassName = "com.mysql.jdbc.Driver"; 79 String url = "jdbc:mysql://localhost:3306/test?useServerPrepStmts=true&cachePrepStmts=true"; 80 String mysqlUsername = "root"; 81 String mysqlPassword = "920346"; 82 // 加载驱动类 83 Class.forName(driverClassName); 84 // 得到Connection 85 Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword); 86 87 /////////////////////////////////////// 88 /////////////////////////////////////// 89 90 91 /* 92 * 一、得到PreparedStatement 93 * 1. 给出sql模板:所有的参数使用?来替代 94 * 2. 调用Connection方法,得到PreparedStatement 95 */ 96 String sql = "select * from j_stu where username=? and password=?"; 97 PreparedStatement pstmt = con.prepareStatement(sql); 98 99 /* 100 * 二、为参数赋值 101 */ 102 pstmt.setString(1, username);//给第1个问号赋值,值为username 103 pstmt.setString(2, password);//给第2个问号赋值,值为password 104 105 ResultSet rs = pstmt.executeQuery();//调用查询方法,向数据库发送查询语句 106 107 //重复使用赋值,需要关闭上次的结果流,并清空原设置 108 rs.close(); 109 pstmt.clearParameters(); 110 111 pstmt.setString(1, "liSi"); 112 pstmt.setString(2, "123"); 113 rs = pstmt.executeQuery();//调用查询方法,向数据库发送查询语句 114 115 return rs.next(); 116 } 117 118 @Test 119 public void fun2() throws Exception { 120 //select * from t_user where username=‘a‘ or ‘a‘=‘a‘ and password=‘a‘ or ‘a‘=‘a‘ 121 String username = "zhangSan"; 122 String password = "123"; 123 boolean bool = login2(username, password); 124 System.out.println(bool); 125 } 126 127 /** 128 * 测试JdbcUtils.getConnection() 129 * @throws SQLException 130 * @throws ClassNotFoundException 131 * @throws IOException 132 */ 133 @Test 134 public void fun3() throws SQLException { 135 Connection con = JdbcUtils.getConnection(); 136 System.out.println(con); 137 Connection con1 = JdbcUtils.getConnection(); 138 System.out.println(con1); 139 } 140 }使用PreapredStatement防止sql攻击
1 import java.sql.Connection; 2 import java.sql.SQLException; 3 4 import org.junit.Test; 5 6 public class Demo5 { 7 /*jdbc中使用事务的演示:转账 8 * !!!事务是由连接对象管理,所以事务过程必须使用同一个连接对象 9 */ 10 public void transfers(String from,String to,Double money){ 11 Connection conn=null; 12 try{ 13 conn=JdbcUtils.getConnection(); 14 //开启事务 15 conn.setAutoCommit(false); 16 //执行事务内容 17 AccountDao dao=new AccountDao(); 18 dao.updateBalance(conn,from, -money); 19 dao.updateBalance(conn,to, money); 20 //提交事务 21 conn.commit(); 22 conn.close(); 23 }catch(Exception e){ 24 try { 25 conn.rollback(); 26 conn.close(); 27 } catch (SQLException e1) { 28 throw new RuntimeException(e); 29 } 30 } 31 } 32 @Test 33 public void fun1(){ 34 transfers("zs","lisi",100.00); 35 } 36 }事务管理
从上面的基础代码可以看出有三个对象非常重要:Connection,Statement/PreparedStatement,ResultSet.还有就是注册驱动有多种方式,上面使用的是推荐用法。
以上就是JDBC的基本使用,但是也存在一些问题,
①数据库连接使用完之后需要释放,如果经常需要连接影响性能。
②数据库的使用代码有很多都是重复的,例如获取Connection对象,异常处理等。
③对查询结果集Result对象的处理
针对上面问题的解决方案:
①使用连接池代替原始的数据库连接,连接池就是一种装饰者模式,对连接对象的close()进行增强。
1 import java.beans.PropertyVetoException; 2 import java.sql.Connection; 3 import java.sql.SQLException; 4 5 import org.apache.commons.dbcp.BasicDataSource; 6 import org.junit.Test; 7 8 import com.mchange.v2.c3p0.ComboPooledDataSource; 9 10 public class Demo6 { 11 /*使用数据库连接池获取连接对象,连接池的配置还可以在配置文件中作为资源进行配置,称为JNDI, 12 * 1、DBCP连接池 13 * 2、C3P0连接池 14 */ 15 @Test 16 public void fun1() throws SQLException{ 17 //数据库连接池是装饰者模式,是对Connection对象进行增强, 18 //获取连接池对象 19 BasicDataSource dataSource=new BasicDataSource(); 20 //配置连接参数,因为连接池也要依靠四大参数连接数据库,并且也需要使用数据库驱动 21 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 22 dataSource.setUrl("jdbc:mysql://localhost:3306/test"); 23 dataSource.setUsername("root"); 24 dataSource.setPassword("920346"); 25 //配置池参数:有默认值, 26 dataSource.setMaxActive(20); //最大活动连接数 27 dataSource.setMaxIdle(3); //最大空闲连接数 28 29 //获取连接对象 30 Connection conn=dataSource.getConnection(); 31 System.out.println(conn.getClass().getName()); 32 33 //注意这里的close()被增强,不是关闭连接,而是将连接对象归还连接池 34 conn.close(); 35 } 36 37 @Test 38 public void fun2() throws SQLException, PropertyVetoException{ 39 //获取连接池对象,和上面操作相似,只是名字有所不同 40 ComboPooledDataSource dataSource=new ComboPooledDataSource(); 41 42 //注意方法名和上面不同 43 dataSource.setDriverClass("com.mysql.jdbc.Driver"); 44 dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); 45 dataSource.setUser("root"); 46 dataSource.setPassword("920346"); 47 48 //配置池参数:有默认值, 49 dataSource.setAcquireIncrement(5); 50 dataSource.setInitialPoolSize(20); 51 52 //获取连接对象 53 Connection conn=dataSource.getConnection(); 54 System.out.println(conn.getClass().getName()); 55 56 //注意这里的close()被增强,不是关闭连接,而是将连接对象归还连接池 57 conn.close(); 58 } 59 @Test 60 public void fun3() throws SQLException{ 61 /*c3p0连接池的配置参数可以直接写在配置文件中, 62 * 只要将配置文件保存在类路径下即可在创建类时自动寻找 63 * 注意:默认情况下使用的是默认配置,如果在代码中在进行配置就会将配置文件中的覆盖 64 */ 65 ComboPooledDataSource dataSource=new ComboPooledDataSource(); 66 67 Connection conn=dataSource.getConnection(); 68 System.out.println(conn.getClass().getName()); 69 70 conn.close(); 71 } 72 public void fun4() throws SQLException{ 73 //在配置文件中可以有多个配置,如果不使用默认配置二使用其他配置,只要将节点名作为参数传入即可 74 ComboPooledDataSource dataSource=new ComboPooledDataSource("oracle-config"); 75 76 Connection conn=dataSource.getConnection(); 77 System.out.println(conn.getClass().getName()); 78 79 conn.close(); 80 } 81 }数据库连接池的使用
②使用Apache Commons dbUtils包进行处理
③使用Apache Commons dbUtils包将结果集与java中的对象,集合等结构进行操作
对Apache Commons dbUtils包的说明参见
http://www.jb51.net/article/61886.htm
http://lavasoft.blog.51cto.com/62575/222771/
javaweb三、JDBC访问数据库
标签: