sun公司设计一套java语言操作不同的数据库提供的是接口,二具体的实现类是由各大数据库厂商实现的。

        private static final String driver=
			"com.microsoft.sqlserver.jdbc.SQLServerDriver";
	private static final String url=
			"jdbc:sqlserver://localhost:1433;DataBaseName=test";

	private static final String user="sa";			//用户名
	private static final String password="123456";		//密码
	private static Connection con=null;

        //加载驱动
	Class.forName(driver);
	con=DriverManager.getConnection(url,user,password);

  

JDBC不管是sql server还是mysql大致的原理是一样的,这里只找到了mysql的jdbc部分源码,在Driver的类中,我们找到了如下代码

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
	// ~ Static fields/initializers
	// ---------------------------------------------

	//
	// Register ourselves with the DriverManager
	//
	static {
		try {
			/**
			 * DriverManager 管理一组 JDBC 驱动程序的基本服务
			 * 注册了自己,自身实例化了
			 */
			java.sql.DriverManager.registerDriver(new Driver());
		} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
		}
	}

	// ~ Constructors
	// -----------------------------------------------------------

	/**
	 * Construct a new driver and register it with DriverManager
	 *
	 * @throws SQLException
	 *             if a database error occurs.
	 */
	public Driver() throws SQLException {
		// Required for Class.forName().newInstance()
	}
}

  

 所以通过

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

 就可以将上面jdbc的driver包下面的静态的代码块直接加载过来,完成驱动的注册,所以在后面就可以有如下代码去连接数据库

con=DriverManager.getConnection(url,user,password);

  


JDBC接口核心的API

在java.sql.*   和  javax.sql.*包中

|- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。

|- connect(url, properties):  连接数据库的方法。

url: 连接数据库的URL

URL语法: jdbc协议:数据库子协议://主机:端口/数据库

user: 数据库的用户名

password: 数据库用户密码

|- DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序

|-registerDriver(driver)  : 注册驱动类对象

|-Connection getConnection(url,user,password);  获取连接对象

|- Connection接口: 表示java程序和数据库的连接对象。

|- Statement createStatement() : 创建Statement对象

|- PreparedStatement prepareStatement(String sql)  创建PreparedStatement对象

|- CallableStatement prepareCall(String sql) 创建CallableStatement对象

|- Statement接口: 用于执行静态的sql语句

|- int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)

|- ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)

  

            |-PreparedStatement接口:用于执行预编译sql语句(是Statement的子类)

|- int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)

|-ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)

                

                  |-CallableStatement接口:用于执行存储过程的sql语句(call xxx)(是PreparedStatement的子类)

|-ResultSet executeQuery()  : 调用存储过程的方法

|- ResultSet接口:用于封装查询出来的数据

|- boolean next() : 将光标移动到下一行

|-getXX() : 获取列的值


statement

package com.gqx.api.statement;

import static org.junit.Assert.*;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

import com.jdbc.util.JDBCUtil;

public class Demo1 {
	@Test
	public void test() {
		/**
		 * 发送DDL命令
		 */
		Statement  stmt=null;
		Connection con=null;
			try {
				con=JDBCUtil.getConnection();
				//准备statement
				stmt=con.createStatement();
				//创建sql语句
				String sql="create table tt(id int primary key IDENTITY(1,1),name varchar(20),password varchar(20))";
				//发送sql语句,同时执行结果返回
				int count=stmt.executeUpdate(sql);

				System.out.println("影响了"+count+"行!");
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				//关闭动作
				//顺序:后打开的先关闭
			JDBCUtil.close(con, stmt);

	}

	@Test
	public void testDML(){
		/**
		 * 发送DML语句
		 */

		Statement statement=null;
		Connection connection=null;
		try {

			connection=JDBCUtil.getConnection();
			statement=connection.createStatement();
			String sql="insert into tt(name,password) values('gqx','1222')";
			int count=statement.executeUpdate(sql);
			System.out.println("影响了"+count+"行!");
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}
		JDBCUtil.close(connection, statement);
	}

	/*
	 * DQL
	 */
	@Test
	public void test3(){
		Statement  stmt=null;
		Connection con=null;

		//加载驱动
			try {
				con=JDBCUtil.getConnection();
				//准备statement
				stmt=con.createStatement();
				//创建sql语句
				/*
				 * ResultSet  API
				 * 1、ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。
				 * next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,
				 * 所以可以在 while 循环中使用它来迭代结果集。
				 * 2、ResultSet 接口提供用于从当前行获取列值的获取 方法(getBoolean、getLong 等)。
				 * 可以使用列的索引编号或列的名称获取值。一般情况下,使用列索引较为高效。列从 1 开始编号。
				 * 为了获得最大的可移植性,应该按从左到右的顺序读取每行中的结果集列,每列只能读取一次。
				 *3、用作获取方法的输入的列名称不区分大小写。
				 */
				String sql="select * from tt";
				//发送sql语句,同时执行结果返回
				ResultSet result=stmt.executeQuery(sql);
				//移动光标
				while(result.next()){
					int id=result.getInt("id");
					String name=result.getString("name");
					String password=result.getString("password");
					System.out.println("id:"+id+",name:"+name+",password:"+password);
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
				//关闭动作
				//顺序:后打开的先关闭
			JDBCUtil.close(con, stmt);

	}
}

 但他有一个很大的问题,如下,很容易被一些人给玩坏

package com.gqx.api.preparedStatement;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.jdbc.util.JDBCUtil;

/**
 * 模拟用户登录效果
 */
public class Demo2 {
	//模拟用户输入
	/*
	 * 更有情节严重的是使用" delete from tt where id=1 or 1=1--" 去删掉你的用户,甚至是表
	 * 所以一般建议使用preparedStatement
	 */
	private static String name = "'我是来玩的' OR 1=1 -- ";
	private static String password = "123456dfdfddfdf";
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Statement  stmt=null;
		Connection con=null;
		ResultSet result=null;
		try {
			con=JDBCUtil.getConnection();

			//准备statement
			stmt=con.createStatement();
			//创建sql语句
			String sql="select * from tt where name="+name+"and password="+password;
			result=stmt.executeQuery(sql);
			if (result.next()) {
				System.out.println("登入成功,你好,"+name);
			}else {
				System.out.println("你登入失败了啊");
			}
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}finally{
			JDBCUtil.close(con, stmt,result);
		}
	}
}

就会发现在该sql语句(select * from tt where name=" '我是来玩的' OR 1=1 --and password="123456dfdfdd" )就会被原封不动的执行,导致错误登入,更有甚者还可能会将数据库的表给破坏掉了,现在可以换一种方法。

PreparedStatement

package com.gqx.api.preparedStatement;

import static org.junit.Assert.*;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

import com.jdbc.util.JDBCUtil;
/**
 *
 * @author Administrator
 * public interface PreparedStatementextends Statement表示预编译的 SQL 语句的对象。
 * SQL 语句被预编译并存储在 PreparedStatement 对象中。
 * 然后可以使用此对象多次高效地执行该语句。
 *
 */
public class Demo {

	@Test
	public void test() {

		PreparedStatement statement=null;
		Connection connection=null;
		try {
			connection=JDBCUtil.getConnection();

			//准备一条预编译的sql语句,用问号代替相应的字符串,预编译的时候,?是一个占位符
			String sql="insert into tt(name,password) values(?,?)";
			statement=connection.prepareStatement(sql);
			//设置参数值,参数一,表示参数的位置,参数二表示值
			statement.setString(1, "哈哈哈");
			statement.setString(2, "222222");
			//发送参数执行
			int count=statement.executeUpdate();
			System.out.println("影响了"+count+"行!");
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}
		JDBCUtil.close(connection, statement);
	}

	@Test
	public void Test2(){
		PreparedStatement statement=null;
		Connection connection=null;
		ResultSet result=null;
		try {
			connection=JDBCUtil.getConnection();

			//准备一条预编译的sql语句,用问号代替相应的字符串,预编译的时候,?是一个占位符
			String sql="select * from tt where id =?";
			statement=connection.prepareStatement(sql);
			statement.setInt(1, 1);

			//发送参数执行
			result=statement.executeQuery();
			while (result.next()) {
				int id=result.getInt("id");
				String name=result.getString("name");
				String password=result.getString("password");
				System.out.println("id:"+id+",name:"+name+",password:"+password);
			}
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}finally{
			JDBCUtil.close(connection, statement,result);
		}

	}

}

 由于它的运行机制如下:

所以不会发生以上用户胡乱登入的情况。

CallableStatement

带有输入输出的存储过程

package com.gqx.api.CallableStatement;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;

import com.jdbc.util.JDBCUtil;

/**
 * 使用CablleStatement调用存储过程
 * @author Administrator
 *
 */
public class Demo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Connection conn = null;
		CallableStatement stmt = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JDBCUtil.getConnection();

			//准备sql
			//第一个?是输入参数,第二个?是输出参数
			String sql = "{call NOD (?,?)}"; //可以执行预编译的sql

			//预编译
			stmt = conn.prepareCall(sql);

			//设置输入参数
			stmt.setString(1, "CS");

			//设置输出参数(注册输出参数)
			/**
			 * 参数一: 参数位置
			 * 参数二: 存储过程中的输出参数的jdbc类型    VARCHAR(20)
			 */
			stmt.registerOutParameter(2, java.sql.Types.INTEGER);

			//发送参数
			stmt.execute(); //结果不是返回到结果集中,而是返回到输出参数中

			//得到输出参数的值
			/**
			 * 索引值: 预编译sql中的输出参数的位置
			 */
			String result = stmt.getString(2); //getXX方法专门用于获取存储过程中的输出参数

			System.out.println(result);

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JDBCUtil.close(conn, stmt ,rs);
		}

	}

}

 程序的util包下的JDBCUtil

package com.jdbc.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.omg.CORBA.portable.InputStream;

public class JDBCUtil {

	static String url=null;
	 static String user=null;			//数据库管理员名
	 static String pass=null;		//密码
	 static String driver=null;		//密码

	/*
	 * 静态代码块只加载一次
	 */
	static{
		//读取db.propties
		try {
			Properties proper =new Properties();
			/**
			 *  . 代表java命令运行的目录
			 *  在java项目下,. java命令的运行目录从项目的根目录开始
			 *  在web项目下,  . java命令的而运行目录从tomcat/bin目录开始
			 *  所以不能使用点.
			 */
			//FileInputStream in =new FileInputStream("./src/db.properties");
			java.io.InputStream in = JDBCUtil.class.getResourceAsStream("/db.properties");
			//加载信息
			proper.load(in);
			url=proper.getProperty("url");
			user=proper.getProperty("user");
			pass=proper.getProperty("pass");
			driver=proper.getProperty("driver");
			//读取信息
				Class.forName(driver);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("驱动程序注册失败");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 获取JDBC连接对象的方法
	 */
	public static Connection getConnection(){
		try {
			Connection connection=DriverManager.getConnection(url,user,pass);
			return connection;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}
	}

	/*
	 * 关闭操作
	 */

	public static void close(Connection con,Statement stmt){
			if (stmt!=null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
			if (con!=null) {
				try {
					con.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
		}

	/**
	 * 这是方法的重载
	 * @param con
	 * @param stmt
	 * @param resultSet
	 */
public static void close(Connection con,Statement stmt,ResultSet resultSet){
	if (resultSet!=null) {
		try {
			resultSet.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
		if (stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if (con!=null) {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
}

  

JDBC——Sql Server的更多相关文章

  1. JDBC连接SQL Server遇到的问题

    需要使用到微软的JDBC sql server的驱动类,去官网下载jar包 使用的URL模式:"jdbc:sqlserver:地址:端口//;databaseName=YourDatabas ...

  2. 使用Apache JMeter对SQL Server、Mysql、Oracle压力测试(二)

    接着第一篇的写: 第三步,测试SQL Server数据库的性能: a.加载JDBC SQL Server驱动.添加线程组和设置线程属性和第二步一样,就不再赘述了: b.设置JDBC Connectio ...

  3. spring boot(二): spring boot+jdbctemplate+sql server

    前言 小项目或者做demo时可以使用jdbc+sql server解决即可,这篇就基于spring boot环境使用jdbc连接sql server数据库,和spring mvc系列保持一致. 在sp ...

  4. 喜大普奔,微软Microsoft JDBC Driver For SQL Server已发布到maven中央仓库

    相信通过java和SQLServer开发应用的同学们都经历过如下类似的问题. 微软提供的JDBC官方驱动没有放置在Maven仓库中,这样如果你的Java应用需要访问SQL Server,你不得不下载s ...

  5. JDBC连接SQL Server代码模板

    *                  JDBC连接SQL Server数据库 代码模板* Connection: 连接数据库并担任传送数据的任务:* Statement :  执行SQL语句:* Re ...

  6. JDBC连接sql server数据库及其它

    JDBC连接sql server数据库的步骤如下: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Class类的 ...

  7. jdbc至sql server的两种常见方法

    Statement和prepareStatement sql server中已建立BookPhone数据库,包含bookPhone表,eclipse中有BookPhone类,三个string类型的值 ...

  8. 【J2EE】Java连接SQL Server 2000问题:“com.microsoft.sqlserver.jdbc.SQLServerException:用户'sa'登录失败。该用户与可信SQL Server连接无关联”

    1.问题现象 E:\JSP\HibernateDemo\HibernateDemoProject\src\sine>java ConnectSQLServerConnect failed!com ...

  9. JDBC与SQL SERVER各个版本的连接方法

    转至:blog.csdn.net/ying5420/article/details/4488246 1.SQL SERVER 2000 JDBC驱动程序:msbase.jar.mssqlserver. ...

随机推荐

  1. vs2012生成的项目,如何在只装有VS2010的电脑上打开

    步骤: 1.用记事本打开Vs2012生成的项目解决方案文件(.sln文件)文件 2.修改前两行 Microsoft Visual Studio Solution File, Format Versio ...

  2. C++有关类的符号总结

    因为我先学习的java,尽管c++与java在类声明与使用上很相似,但是看到c++的源码还是有一些符号不太明白..现在就用一个例子总结一下: #include <iostream> cla ...

  3. 10g和11g,优化器对外连接的处理对比

    我反省,今天面试有个问题没有说清楚.我给出的结论(而且这个结论我验证过)是:不要使用不必要的外连接,举了下面这个例子却没有说清楚.虽然最近感冒,状态不是很好,但最擅长的东西都没有表达清楚,泪流满面啊: ...

  4. JSP页面的五种跳转方法

    ①RequestDispatcher.forward() 是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servlet or JSP到另外一个Se ...

  5. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

  6. hdu 1281

    二分图,简单的模板题,不过题目比较难懂: 其中important chess就是删掉它不能够完美匹配,所以就枚举每一个可能删的棋子: 代码: #include <cstdio> #incl ...

  7. WAF

    http://netsecurity.51cto.com/art/201010/231124.htm http://wenku.baidu.com/link?url=elrFtxPRcwJ5FjlXE ...

  8. 解决wordpress上传的文件尺寸超过 php.ini 中定义的 upload_max_filesize 值。

    上传的文件尺寸超过 php.ini 中定义的 upload_max_filesize 值. 解决方法:修改/etc/php5/apache2/php.ini文件中的 post_max_size = 6 ...

  9. 看了一下安装文件. 是qt4python 下用了 webkit,包装了bootstrap

    Pg9.6 安装包里的pgadmin4 反正软件是开源的,慢慢看源码呗.

  10. bzoj1899

    显然如果只有一个窗口,是一道贪心的题目,直接让吃饭慢的排在前面即可 两个窗口的话,我们还是根据这个原则 先对吃饭时间降序排序,然后这是一个dp 假如设当前处理到第i个人,当在窗口1的打饭时间确定了,窗 ...