java连接数据库的jdbc技术之preparestatement的相关操作

以mysql数据库为基础,用junit做jdbc技术之preparestatement的相关测试,以及探讨statement和preparestatement在获取自动增长列的值时和executeBatch操作的区别。

该测试所需的表book和stud,建表语句如下:

CREATE TABLE `book` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `name` varchar(30) DEFAULT NULL,  
  `price` double DEFAULT NULL,  
  `birth` datetime NOT NULL,  
  PRIMARY KEY (`id`)  
);  
CREATE TABLE `stud` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `name` varchar(30) DEFAULT NULL,  
  `age` int DEFAULT NULL,  
  PRIMARY KEY (`id`)  
);  

该测试创建了一个数据库对象,用来操作数据库,附代码:

package com.cw.cw.mysql;  
  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.sql.Statement;  
  
  
public class Mysql {  
    private static final String URL = "jdbc:mysql://localhost:3306/dbgirl";  
    private static final String DRIVER = "com.mysql.jdbc.Driver";  
    private static final String USER = "root";  
    private static final String PWD = "123456";  
      
    public Connection conn = null;  
    public Statement stmt = null;  
    public PreparedStatement pstmt = null;  
    public ResultSet rs = null;  
      
    public Mysql() throws SQLException{  
        try {  
            Class.forName(DRIVER);  
            conn = DriverManager.getConnection(URL,USER,PWD);  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
    }  
    public void getStatement() throws SQLException, ClassNotFoundException{  
        stmt = conn.createStatement();  
    }  
    public void getPsStatement(String sql) throws SQLException, ClassNotFoundException{  
        pstmt = conn.prepareStatement(sql);  
    }  
      
    public void close(){  
        if(conn!=null){  
            try {  
                conn.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
        if(stmt!=null){  
            try {  
                stmt.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
        if(pstmt!=null){  
            try {  
                pstmt.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
        if(rs!=null){  
            try {  
                rs.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
该测试创建的测试类,附代码:
package com.cw.cw;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

import org.junit.Test;

import com.cw.cw.mysql.Mysql;

public class JdbcPrepareStatementTest {
	
	Mysql mysql = null;
	
	public JdbcPrepareStatementTest(){
		try {
			mysql = new Mysql();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * PrepareStatement的executeQuery
	 * 不会被黑:如输入name值为: a' or '1'='1
	 */
	@SuppressWarnings("resource")
	@Test 
	public void test1() throws Exception{
		System.out.println("test1");
		Scanner sc = new Scanner(System.in);
		String id = sc.nextLine();
		String name = sc.nextLine();
		
		//创建预处理语句对象
		String sql = "select count(*) from stud where id=? and name=?  ";//凡是用户输入的地方,用“?”号(称占位符)填入
		mysql.getPsStatement(sql); 
		//给占位设置值---设置参数
		mysql.pstmt.setString(1, id); //给第1个参数设置
		mysql.pstmt.setString(2, name); //给第2个参数设置
		
		mysql.rs = mysql.pstmt.executeQuery();//这里不能传参数sql
		//取一条数据
		mysql.rs.next();
		int n = mysql.rs.getInt(1);
		if(n<=0){
			System.out.println("登录失败...");
		}else{
			System.out.println("登录成功....");
		}
		
		mysql.close();
		System.err.println("=================================================");
	}
	
	/**
	 * PrepareStatement的executeUpdate
	 * 能够防护bug:如输入name值为: aa,b'c
	 */
	@SuppressWarnings("resource")
	@Test 
	public void test2() throws Exception{ 
		System.out.println("test2");
		Scanner sc = new Scanner(System.in);
		String id = sc.nextLine();
		String name = sc.nextLine();
		int age = Integer.parseInt(sc.nextLine());
		//String sql = "insert into stud values('P2001','kobe',25) ";
		String sql = "insert into stud values(?,?,?)  ";
		mysql.getPsStatement(sql); 
		mysql.pstmt.setString(1, id);
		mysql.pstmt.setString(2, name);
		mysql.pstmt.setInt(3, age);
		
		mysql.pstmt.executeUpdate();
		
		mysql.close();
		System.err.println("=================================================");
	}

	/**
	 * Statement的executeUpdate
	 * 获取自动增长列的值,报错
	 */
	@Test 
	public void test3() throws Exception{ 
		System.out.println("test3");
		String sql = "insert into book(name,price,birth) values('三国演义',45.66,'2012-10-18 12:00:05' )";
		mysql.stmt.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
		mysql.rs = mysql.stmt.getGeneratedKeys();
		if(mysql.rs.next()){
			int id = mysql.rs.getInt(1);
			System.out.println("自动生成的字段值:"+id);
		}
		mysql.close();
		System.err.println("=================================================");
	}

	/**
	 * PrepareStatement的executeUpdate
	 * 获取自动增长列的值
	 */
	@Test //获取自动增长列的值--PreparedStatement
	public void test4() throws Exception{ 
		System.out.println("test4");
		String sql = "insert into book(name,price,birth) values(?,?,'2012-10-18 12:00:05' )";
		mysql.pstmt = mysql.conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
		mysql.pstmt.setString(1, "水流利");
		mysql.pstmt.setDouble(2, 123.23);
		mysql.pstmt.executeUpdate();
		mysql.rs = mysql.pstmt.getGeneratedKeys();
		if(mysql.rs.next()){
			int id = mysql.rs.getInt(1);
			System.out.println("自动生成的字段值:"+id);
		}
		mysql.close();
		System.err.println("=================================================");
	}
	
	/**
	 * Statement的executeBatch
	 * executeBatch返回影响的行数
	 * 执行批处理---自己本身不带事务,如果其中某条sql挂,则后续的sql执行失败,前面的还是有效的。
	 * 如果要事务,另外再采用:con.setAutoCommit(false)+try-cacth+ rollback/commit
	 */
	@Test 
	public void test5() throws Exception{ 
		System.out.println("test5");
		String sql = "insert into book(name,price,birth) values('aaa',11.11,'2013-11-28 19:00:15' )";
		mysql.getStatement();
		for(int i=0;i<5;i++){
			if(i==2){
				//去掉注释,执行错误,但前面2条sql还是插进去了,后面三条都没有插入进去
//				sql = "insert into book(name,price,birth) values('aaa','aa','2013-11-28 19:00:15' )";
			}
			mysql.stmt.addBatch(sql);
		}
		sql = "update book set price =price*1.1 where price<30";
		mysql.stmt.addBatch(sql);
		int a[] = mysql.stmt.executeBatch();
		for(int x:a){
			System.out.println(x);
		}
		mysql.close();
		System.err.println("=================================================");
	}
	
	/**
	 * prepareStatement的executeBatch
	 * executeBatch返回影响的行数
	 * 执行批处理---自己本身不带事务,如果其中某条sql挂,则后续的sql执行失败,前面的还是有效的。
	 * 如果要事务,另外再采用:con.setAutoCommit(false)+try-cacth+ rollback/commit
	 */
	@Test //执行批处理---
	public void test6() throws Exception{ 
		System.out.println("test6");
		String sql = "insert into book(name,price,birth) values(?,?,'2013-11-28 19:00:15' )";
		mysql.getPsStatement(sql);
		//插入5条,数组a返回两次addBatch后executeBatch所影响的行数
		for(int i=0;i<5;i++){
			mysql.pstmt.setString(1, "bb"+i);
			mysql.pstmt.setDouble(2, 25+i);
			mysql.pstmt.addBatch();
		}
		//去掉注释,执行错误,只有第三条数据没有插入进去,其他4条sql都插进去了,update操作也执行了,但是执行完executeBatch,没有执行数组a的输出,不知为啥???
		/*for(int i=0;i<5;i++){
			if(i==2){
				mysql.pstmt.setString(1, "bb"+i);
				mysql.pstmt.setString(2, "bb"+i);
				mysql.pstmt.addBatch();
			}else{
				mysql.pstmt.setString(1, "bb"+i);
				mysql.pstmt.setDouble(2, 25+i);
				mysql.pstmt.addBatch();
			}
		}*/
		sql = "update book set price =price*1.1 where price<30";
		mysql.pstmt.addBatch(sql);
		int a[] = mysql.pstmt.executeBatch();
		for(int x:a){
			System.out.println(x);
		}
		mysql.close();
		System.err.println("=================================================");
		System.out.println("junit测试方法执行完毕");
	}


}
参考:http://m.blog.csdn.net/jrdgogo/article/details/52212553


你可能感兴趣的:(数据库)