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. ...
随机推荐
- eclipse 启动 出现Failed to create the Java Virtual Machine" 解决方案
方法如下: 找到eclipse目录下的eclipse.ini,可以看到如下内容:-startupplugins/org.eclipse.equinox.launcher_1.1.0.v20100507 ...
- Djang DJANGO_SETTINGS_MODULE
在 site-packages\django 新建一个文件 ’settings.py‘ 内容如下: DEBUG = TrueDEFAULT_FROM_EMAIL = 'alangwansui@qq.c ...
- Python 函数式编程学习
描述:通过将函数作为参数,使得功能类似的函数实现可以整合到同一个函数. Before def getAdd(lst): result = 0 for item in lst: result += it ...
- Apache配置允许文件索引
这两天在看bootstrap的文档,所以在本地搭建了一个web server. 这里记下Apache的一个小配置: LISTEN *:8000 <VirtualHost *:8000> A ...
- 多个div独立控制其显示/隐藏
今天要说一个神奇的html标签op,静态页下可以配合jquery分别控制每个层的显示/隐藏切换. 如果用动态中使用,用文章id做区分就可以了. <html> <head> &l ...
- Aircrack-ng官方文档翻译[中英对照]---Aireplay-ng
Aircrack-ng官方文档翻译---Aireplay-ng[90%] Description[简介] Aireplay-ng is used to inject frames. Aireplay- ...
- sublime 编译程序出错控制台打印PATH的解决办法
找到sublime的安装目录 搜索 exec.py 打开找到这几句话193行左右或者搜索关键词path if "PATH" in merged_env: self.debug_te ...
- 四校训练 warm up 14
A:Pythagoras's Revenge 代码: #include<cstdio> #define ll long long using namespace std; int main ...
- Android 常用权限
添加WiFi以及访问网络的权限: <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" ...
- 李洪强iOS开发之-环信02.3_具体接口讲解 - Apple Docs
http://www.easemob.com/apidoc/ios/chat3.0/annotated.html Apple Docs.