JDBC——Sql Server
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的更多相关文章
- JDBC连接SQL Server遇到的问题
需要使用到微软的JDBC sql server的驱动类,去官网下载jar包 使用的URL模式:"jdbc:sqlserver:地址:端口//;databaseName=YourDatabas ...
- 使用Apache JMeter对SQL Server、Mysql、Oracle压力测试(二)
接着第一篇的写: 第三步,测试SQL Server数据库的性能: a.加载JDBC SQL Server驱动.添加线程组和设置线程属性和第二步一样,就不再赘述了: b.设置JDBC Connectio ...
- spring boot(二): spring boot+jdbctemplate+sql server
前言 小项目或者做demo时可以使用jdbc+sql server解决即可,这篇就基于spring boot环境使用jdbc连接sql server数据库,和spring mvc系列保持一致. 在sp ...
- 喜大普奔,微软Microsoft JDBC Driver For SQL Server已发布到maven中央仓库
相信通过java和SQLServer开发应用的同学们都经历过如下类似的问题. 微软提供的JDBC官方驱动没有放置在Maven仓库中,这样如果你的Java应用需要访问SQL Server,你不得不下载s ...
- JDBC连接SQL Server代码模板
* JDBC连接SQL Server数据库 代码模板* Connection: 连接数据库并担任传送数据的任务:* Statement : 执行SQL语句:* Re ...
- JDBC连接sql server数据库及其它
JDBC连接sql server数据库的步骤如下: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Class类的 ...
- jdbc至sql server的两种常见方法
Statement和prepareStatement sql server中已建立BookPhone数据库,包含bookPhone表,eclipse中有BookPhone类,三个string类型的值 ...
- 【J2EE】Java连接SQL Server 2000问题:“com.microsoft.sqlserver.jdbc.SQLServerException:用户'sa'登录失败。该用户与可信SQL Server连接无关联”
1.问题现象 E:\JSP\HibernateDemo\HibernateDemoProject\src\sine>java ConnectSQLServerConnect failed!com ...
- JDBC与SQL SERVER各个版本的连接方法
转至:blog.csdn.net/ying5420/article/details/4488246 1.SQL SERVER 2000 JDBC驱动程序:msbase.jar.mssqlserver. ...
随机推荐
- (转载)delphi实例TDBGrid用右键菜单复制行粘贴行
delphi实例TDBGrid用右键菜单复制行粘贴行 这个从本质上来说就是DBGrid后台数据库的插入 右键复制当前行的相关数据到临时变量点粘贴时,覆盖数据或插入数据! db为数据库: 字段名id,n ...
- 4种方法生成二维码 (js 控制canvas 画出 二维码)
随着网络的迅速发展 发展 发展,二维码的应用将会越来越多.同时很多只是很平凡的二维码,请拿起你的手 把这个二维码 设计起来吧.下面分享了几个非常好的二维码设计. 二维码原理: 二维条码/二维码可以分 ...
- 解决treeview的同一节点单击多次的执行问题
在使用treeview的AfterSelect函数的时候,单击同一节点多次无响应. 解决方法: 将首次单击的节点信息保存到selectTreeNode: 然后使用click函数,判断单击的节点是否和s ...
- c语言的笔记
下面把我这半年来记的一些C语言的笔记贴出来. 1 C语言中函数参数传递是按照“值传递”进行的,即单向传递. 2 函数原型:函数类型 函数名(参数类型,参数类型……),可以不必加参数名,因为操作系统 ...
- iOS - 应用程序国际化
开发的移动应用更希望获取更多用户,走向世界,这就需要应用国际化,国际化其实就是多语言.这篇文章介绍Xcode4.5以后的国际化,包括应用名国际化和应用内容国际化.如果是Xcode4.5之前版本请参考. ...
- requirejs学习博客址分享
1. http://blog.jobbole.com/30046/ 2. http://www.requirejs.cn/ 3. http://www.ruanyifeng.com/blog/2012 ...
- csu 10月 月赛 H 题 A Very Hard Problem
Description CX老湿经常被人黑,被黑得多了,自己也就麻木了.于是经常听到有人黑他,他都会深情地说一句:禽兽啊! 一天CX老湿突发奇想,给大家出了一个难题,并且声称谁能够准确地回答出问题才能 ...
- 深入解析java虚拟机-jvm运行机制
转自oschina 一:JVM基础概念 JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现.编译虚拟机的指令集与编译微处理器的指令集非常类似.Java虚拟机包括一套字 ...
- mysql日志的查看与开启
mysql的日志类型: 错误日志: log-error 查询日志: log 慢查询日志: log-slow-queries 更新日志: log-update 二进制日志: log-bin 开启错误日志 ...
- android视频播放
视频播放我们用到的是MediaPlayer,显示控件使用的surfaceView 我们向SD卡中先添加个视频文件,我的是xajh.3gp,不要用mp4,MP4会出现 should have subti ...