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. ...
随机推荐
- citrix xen server 虚拟机无法关闭的问题
悲剧的一台windows的虚拟机无法重启无法关机.如下图,一直卡住不动. 首先找到这台机器: [root@xenserver- xen]# xe vm-list name-label=-vss\ se ...
- C/S和B/S两种软件体系结构
目前两种流行的软件体系结构就是C/S和B/S体系结构,下面对两种体系结构进行一下总结: 1.C/S(客户端/服务器模式): 客户端和服务器都是独立的计算机,客户端是面向最终用户的应用程序或一些接口设备 ...
- 第一次写Makefile文件
test.c文件内容 #include <stdio.h> int main(int argc, char const *argv[]) { printf("hahahah\n& ...
- NOI冲刺计划
省选过了,剩下大概是NOI冲刺了吧.中间还有一大堆诸如会考,CTSC,APIO等东西. 最近先不急着天天刷八中了吧,多在不同网站见一些题,然后再着重提高一下代码准确性.重点把DP这个板块多练习一下,八 ...
- [BZOJ 2048] [2009国家集训队]书堆 【调和级数】
题目链接:BZOJ - 2048 题目分析 只有一本书时,这本书的重心落在桌子边缘上,伸出桌面的长度就是 1/2. 有两本书时,第一本书的重心就落在第二本书的边缘上,两本书的重心落在桌子边缘上,两本书 ...
- InvalidIndexNameException[Invalid index name [2Shard], must be lowercase]
[2016-10-11 14:16:42,191][DEBUG][action.admin.indices.create] [Feron] [2Shard] f ailed to create [2S ...
- 【踩坑记】从HybridApp到ReactNative
前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...
- strncpy 用法
strncpy 用法 原型:extern char *strncpy(char *dest, char *src, int n); 用法:#include <string.h> 功能: ...
- Selenium WebDriver + Grid2 + RSpec之旅(六) ----多浏览器的并行执行
Selenium WebDriver + Grid2 + RSpec之旅(六) ----多浏览器的并行执行 由于浏览器的发展,浏览器种类繁多.为了保证系统能在各种浏览器上叱咤风云,减少测试人员的测试工 ...
- MVC 依赖注入/控制反转
http://www.cnblogs.com/cnmaxu/archive/2010/10/12/1848735.html http://www.cnblogs.com/artech/archive/ ...