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. ...
随机推荐
- Python学习_IDLE快捷键以及列表相关杂记
IDLE快捷键 Tab完成:键入部分代码,按下TAB键,IDLE将给出列表帮助完成语句 回退代码语句:按下Alt+P(Previous),可以回退到IDLE中之前输入的代码语句, 下一个代码语句:按下 ...
- JS身份证真实性校验(一)
//这个可以验证15位和18位的身份证,并且包含生日和校验位的验证. //如果有兴趣,还可以加上身份证所在地的验证,就是前6位有些数字合法有些数字不合法. function isIdCardNo(nu ...
- simhash--文本排重
转载自 https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/06.12.md http: ...
- bzoj 3144: [Hnoi2013]切糕 最小割
3144: [Hnoi2013]切糕 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 681 Solved: 375[Submit][Status] ...
- [原博客] POJ 2505 A multiplication game 组合游戏
题目链接题意: 有一个数p=1,甲乙两人轮流操作,每次可以把p乘2~9中的一个数,给定一个n,当一个人操作后p>=n,那么这个人赢,问先手是否必胜. 必胜状态:存在一种走法走到一个必败状态. 必 ...
- hdu 1116
欧拉回路,利用并查集来实现: 代码: #include<cstdio> #include<cstring> #include<vector> using names ...
- Codeforces Round #197 (Div. 2) : B
也是水题一个,不过稍微要细心点.... 贴代码: #include<iostream> using namespace std; long long n,m; ; int main() { ...
- phpstorm 强大的活动模板 可以自定义注释,代码段,根据cms订制自动提示
http://jingyan.baidu.com/article/8275fc86badd6346a03cf6aa.html [PHP] phpstorm的使用(1) http://v.youku.c ...
- POJ 1778 All Discs Considered(拓扑排序)
点我看题目 题意 :其实题意我也说不清楚,因为比赛的时候我盯着看了1个小时也没看懂....就是两个磁盘,第一个有n1的安装包,编号为1~n1,第二个有n2个安装包,编号为n1~n2.给你d对关系,(x ...
- 发现一个Doxygen风格的QT帮助
http://cep.xray.aps.anl.gov/software/qt4-x11-4.8.6-browser/classes.html http://cep.xray.aps.anl.gov/ ...