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. ...
随机推荐
- poj 1144 Network
Network 题意:输入n(n < 100)个点,不一定是连通图,问有多少个割点? 割点:删除某个点之后,图的联通分量增加. 思路:dfs利用时间戳dfs_clock的特性,点u的low函数l ...
- zzuli oj 1165 实数的小数部分(指针专题)
Description 读入一个实数,输出该实数的小数部分,小数部分若多余的末尾0,请去掉.如输入111111.12345678912345678900 则输出0.12345678912345678 ...
- POJ 1860 Currency Exchange 毫无优化的bellman_ford跑了16Ms,spfa老是WA。。
题目链接: http://poj.org/problem?id=1860 找正环,找最长路,水题,WA了两天了.. #include <stdio.h> #include <stri ...
- C# RichTextBox 获取当前显示部分的文字
int start = richTextBox1.GetCharIndexFromPosition(new Point(0, 0)); int end = richTextBox1.GetCharIn ...
- 《无懈可击的Web设计》_灵活的文字
常见的方法 body{ font-size:12px; } 使用像素单位的优点: 不管使用哪种浏览器或者设备来查看,文字看起来都大小一致. 为什么这么做不是无懈可击的? 以像素为单位设定文字大小之后, ...
- mysql 时间字段的函数 timestamp
Mysql 里格式 时间字段的函数 DATE_FORMAT unix_timestamp - 墨墨修行的日志 - 网易博客http://jjuanxi.blog.163.com/blog/static ...
- 形形色色Node工程Angular2
最近项目要用的 一些无关紧要的文件夹, demo是一些示例, dist是webpack打包后发布的代码,server是用node启动服务,typings和tsconfig是一些ts配置. npm in ...
- linux下使用NFS挂载文件系统
转自linux如何使用NFS挂载文件系统 设备:一台服务器和一台客户端,这里我们把装在PC机上的RedHat作为服务器,而客户端则是嵌入式linux开发板. 环境:开发板已启动,连接好串口和网线,串口 ...
- Java文件备份类
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import ...
- 最简单的CRC32源码---逐BIT法
CRC其实也就那么回事,却在网上被传得神乎其神.单纯从使用角度来说,只需要搞明白模二除法,再理解一些偷懒优化的技巧,就能写出自己的CRC校验程序. 下面的代码完全是模拟手算过程的,效率是最低的,发出来 ...