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. eclipse 启动 出现Failed to create the Java Virtual Machine" 解决方案

    方法如下: 找到eclipse目录下的eclipse.ini,可以看到如下内容:-startupplugins/org.eclipse.equinox.launcher_1.1.0.v20100507 ...

  2. Djang DJANGO_SETTINGS_MODULE

    在 site-packages\django 新建一个文件 ’settings.py‘ 内容如下: DEBUG = TrueDEFAULT_FROM_EMAIL = 'alangwansui@qq.c ...

  3. Python 函数式编程学习

    描述:通过将函数作为参数,使得功能类似的函数实现可以整合到同一个函数. Before def getAdd(lst): result = 0 for item in lst: result += it ...

  4. Apache配置允许文件索引

    这两天在看bootstrap的文档,所以在本地搭建了一个web server. 这里记下Apache的一个小配置: LISTEN *:8000 <VirtualHost *:8000> A ...

  5. 多个div独立控制其显示/隐藏

    今天要说一个神奇的html标签op,静态页下可以配合jquery分别控制每个层的显示/隐藏切换. 如果用动态中使用,用文章id做区分就可以了. <html> <head> &l ...

  6. Aircrack-ng官方文档翻译[中英对照]---Aireplay-ng

    Aircrack-ng官方文档翻译---Aireplay-ng[90%] Description[简介] Aireplay-ng is used to inject frames. Aireplay- ...

  7. sublime 编译程序出错控制台打印PATH的解决办法

    找到sublime的安装目录 搜索 exec.py 打开找到这几句话193行左右或者搜索关键词path if "PATH" in merged_env: self.debug_te ...

  8. 四校训练 warm up 14

    A:Pythagoras's Revenge 代码: #include<cstdio> #define ll long long using namespace std; int main ...

  9. Android 常用权限

    添加WiFi以及访问网络的权限: <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" ...

  10. 李洪强iOS开发之-环信02.3_具体接口讲解 - Apple Docs

    http://www.easemob.com/apidoc/ios/chat3.0/annotated.html Apple Docs.