JDBC操作数据库以及statement、preparedStatement和callableStatement区别

利用JDBC API可以通过java简便的操作数据库。在java8以及以后的版本中jdbc-odbc桥连接已经舍弃。对于不同的数据库要到对应的官网中下载驱动。

下面给出三种常用数据库驱动名,驱动类和对应的连接字符串名(x代表版本)

数据库 驱动 jar 具体驱动类名 连接字符串
Oracle ojdbc-x.jar oracle.jdbc.OracleDriver jdbc:oracle:thin:@localhost:1521:ORCL
MySQL mysql-connector-java-x.jar com.mysql.jdbc.Driver jdbc:mysql://localhost:33006/数据库实例名
SQLServer sqljdbc-x.jar com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc:microsoft:sqlserver:localhost:1433:databasename=数据库实例名

JDBC操作数据库的四个步骤

  1. 倒入驱动,加载具体的驱动类
  2. 与数据库建立连接
  3. 执行SQL
  4. 处理结果集(针对查询结果集)

通过JDBC API 不同的数据库操作起来都差不多,这里以SQLServer为例,不同数据库差别就在驱动与连接字符串。


import java.sql.*;

/**
 * JDBC操作数据库的四个步骤
 * a.倒入驱动,加载具体的驱动类
 * b.与数据库建立连接
 * c.执行SQL
 * d.处理结果集
 * @author 1
 *
 */
public class JDBCDemo{
	
	private static String URL = "jdbc:sqlserver://127.0.0.1:1433;databaseName=学生数据库";
	private static String user = "sa";
	private static String pwd = "123";
	
	public static void update(String sql){ //增删改
		Statement stmt = null;
		Connection  con = null;
		try {
			//a.倒入驱动,加载具体的驱动类
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			//b.与数据库建立连接
			con = DriverManager.getConnection(URL, user, pwd);
			//c.执行SQL
			stmt = con.createStatement();
			int count = stmt.executeUpdate(sql);  //返回影响的结果集数
			//d.处理结果集
			if(count>0) {
				System.out.println("操作成功,影响了"+count+"行");
			}
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("无法加载驱动");
		}catch(SQLException e) {
			e.printStackTrace();
			System.out.println("执行SQL失败");
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(stmt!=null) stmt.close();
				if(con!=null) con.close();
			}catch(SQLException e) {
				e.printStackTrace();
				System.out.println("关闭失败");
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	
	public static void query(){ //查
		Statement stmt = null;
		Connection  con = null;
		ResultSet rs = null;
		try {
			//a.倒入驱动,加载具体的驱动类
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			//b.与数据库建立连接
			con = DriverManager.getConnection(URL, user, pwd);
			//c.执行SQL
			String sql = "select * from Course";
			stmt = con.createStatement();
			rs = stmt.executeQuery(sql);
			//d.处理结果集
			while(rs.next()) {
				System.out.print(rs.getString("Cno")+" ");
				System.out.print(rs.getString("Cname")+" ");
				System.out.print(rs.getInt("Credit")+" ");
				System.out.println(rs.getInt("Semester"));
			}
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("无法加载驱动");
		}catch(SQLException e) {
			e.printStackTrace();
			System.out.println("执行SQL失败");
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs!=null) rs.close();
				if(stmt!=null) stmt.close();
				if(con!=null) con.close();
			}catch(SQLException e) {
				e.printStackTrace();
				System.out.println("关闭失败");
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	public static void main(String[] args) {
		String sql = "update Course set Credit = 4 where Cno='C001'";
		JDBCDemo.update(sql);
		query();
	}
}

Statement 和 preparedStatement

Statement 和 preparedStatement都可以用来进行增删改查。

Statement

statement 对象可以通过connection对象的createStatement()方法产生。
createStatement()方法原型 Statement java.sql.Connection.createStatement() throws SQLException

常用方法:

  • executeUpdate(sql);
    用于进行数据库更新(增删改)
    函数原型:int java.sql.Statement.executeUpdate(String sql) throws SQLException
    返回值为int,即进行更新影响到的几条记录。
  • executeQuery(sql) ;
    用于数据库查询
    函数原型:ResultSet java.sql.Statement.executeQuery(String sql) throws SQLException
    返回值为ResultSet类型。用于保存数据库结果集的数据表,ResultSet对象指向当前数据行的光标,最初光标被置于第一行之前(类似于迭代器)。
    通过next()方法可将光标移动到下一行,没有下一行时返回false,否则返回true。
    通过getXXX(“属性名”)的方法获得属性值
			rs = stmt.executeQuery(sql);
			//d.处理结果集
			while(rs.next()) {
				System.out.print(rs.getString("Cno")+" ");
				System.out.print(rs.getString("Cname")+" ");
				System.out.print(rs.getInt("Credit")+" ");
				System.out.println(rs.getInt("Semester"));
			}

preparedStatement

preparedStatement拓展了Statement
原型:public abstract interface java.sql.PreparedStatement extends java.sql.Statement

所以Statement的所有方法preparedStatement都可使用,除此之外preparedStatement还多了很多set方法:
在这里插入图片描述
由connection对象的prepareStatement(String sql)方法产生。
函数原型:PreparedStatement java.sql.Connection.prepareStatement(String sql) throws SQLException
(注:构建Statement对象的createStatement()不许参数sql,SQL语句是最后执行execute的时候传入的。)
接口preparedStatement用于表示预编译的SQL语句对象。这里的SQL语句通常含有占位符?。SQL语句被预编译并存储在preparedStatement对象中,这样可以提高执行该SQL语句的效率。

//这里省略了try、catch,模板与上面的大致相同
			//a.倒入驱动,加载具体的驱动类
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			//b.与数据库建立连接
			con = DriverManager.getConnection(URL, user, pwd);
			//c.执行SQL
			String sql = "select Sno,Sname from Student where Sname like ?";  
			pstmt = con.prepareStatement(sql); //预编译
			pstmt.setString(1,"张%");  //查询姓李的学生
			rs = pstmt.executeQuery();
			//d.处理结果集
			while(rs.next()) {
				System.out.print(rs.getString("Sno")+" ");
				System.out.print(rs.getString("Sname")+" ");
				System.out.println();
			}

set方法用于设置占位符的值,第一个参数为对应占位符在SQL语句出现的顺序(从1开始),第二个参数为值。

preparedStatement较Statement的优点

1)编写代码更简便(避免字符串拼接的麻烦–采用占位符)
2)提高性能(采用预编译)
3)更安全(有效防止SQL注入)
例如:对于一个登陆操作(使用statement)
用户输入用户名:XXX ’ or 1=1 –
密码:XXX
这样查询语句就由

select count(*from login where uname='name' and upwd ='pwd'

变成了

select count(*from login where uname='XXX' or 1=1 --' and upwd ='XXX'

–后的被注释
or 1=1 永真所以能登陆成功。
但是使用preparedStatement时,用户输入会被当成一个整体,危险输入会被转义,所以更安全。

CallableStatement

CallableStatement用于调用储蓄过程或者储蓄函数
通过connection对象的prepareCall(String sql)方法产生CallableStatement对象。

注:这里的sql有格式要求
对于储蓄过程:sql={call 储蓄过程名(参数列表)}
对于存储函数:sql={?= call 存储函数名(参数列表)}
有几个参数就用几个占位符?代替

通过setXXX(index,value)设置参数值
通过registerOutParameter(index,SQLType)设置输出参数类型
调用execute()后
通过getXXX()接收输出参数。

例:储蓄过程p3用于统计学校某系的男生人数,输入参数为系,输出参数为该系男生人数

ALTER PROCEDURE p3 @dept VARCHAR(10),@number INT OUTPUT
AS
SELECT @number = COUNT(Sno) FROM Student WHERE Sdept = @dept AND Ssex = '男'
//a.倒入驱动,加载具体的驱动类
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			//b.与数据库建立连接
			con = DriverManager.getConnection(URL, user, pwd);
			//获取CallableStatement对象
			cstmt = con.prepareCall("{call p3(?,?)}");
			
			//为参数赋值
			cstmt.setString(1, "计算机系");
			
			//设置输出结果的数据类型
			cstmt.registerOutParameter(2, Types.INTEGER);
			//执行
			cstmt.execute();
			//获取输出结果
			int result = cstmt.getInt(2);
			System.out.println(result);
发布了12 篇原创文章 · 获赞 0 · 访问量 155

猜你喜欢

转载自blog.csdn.net/qq_43635212/article/details/104211315