我们知道Java中的jdbc是用来连接应用程序和数据系统的。本篇文章主要就来看看关于JDBC的实现和使用细节。主要包括以下几点内容:
- JDBC的基本知识(数据驱动程序)
- JDBC的连接配置
- 使用JDBC增删改查
- JDBC的一些使用细节
一、JDBC的基本知识
我们用Java写的程序。不管是桌面应用程序还是web应用程序都是不能直接訪问我们本机上的数据库系统的,这就须要使用驱动程序去构成两者之间的连接。
像这样,我们的应用程序须要针对不同的数据库系统调用不同的驱动程序来连接操作数据库系统,可是对于不同的数据库系统,我们就须要学习他们各自提供的驱动程序接口的使用,还是比較麻烦的。而且程序一旦数据迁移。将导致关于数据操作的代码模块须要重写。
于是sun公司为了简化Java对数据库的连接操作,定义了一套Java操作数据库的规范,JDBC(Java Database Connectivity)。
从此程序猿就能够使用纯Java代码连接和操作数据库了。
JDBC向上提供了一系列的使用接口,包括连接数据库,增删改查操作等。向下会去调用相相应了驱动程序。然后这些驱动程序又会去直接的操作数据库。运行sql语句,返回结果。
对于我们程序猿,仅仅须要学习怎么使用JDBC,不用再去关心各个驱动程序怎么使用。
二、JDBC的连接配置
想要成功的使用jdbc连接我们的本地数据库主要须要以下几个步骤:
- 下载相应的数据库系统提供的驱动程序
- 将驱动程序包加入到jdk包中
- 调用 DriverManager 类的 getConnection()获取数据库连接对象
以下一步步演示并解释。首先下载相应的DBMS(数据库管理系统提供驱动程序),你能够使用IBM的DB2,或者微软的Sql Server,或者mysql。本篇文章使用的是sql server。下载地址:https://www.microsoft.com/en-us/download/details.aspx?
displaylang=en&id=11774 。运行sqljdbc_6.0.8112.100_chs.exe解压文件,或者直接解压sqljdbc_6.0.8112.100_chs.tar.gz,然后进入解压出来的目录,找到jre目录,(应该有两个版本号7,8),找到相应自己的jdk版本号,复制里面的sqljdbc42.jar包,到本机的jdk目录。
默认应该在:C:Program FilesJava中。进入jdk目录中(不要进错了),然后jrelibext,将刚刚的jdbc包粘贴到当中就可以。
以下打开IDE创建一个project,main函数中粘贴以下代码,详细什么意思,后文会说。
public static void main(String[] args){
String driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver";
String dbURL="jdbc:sqlserver://localhost:1433;DatabaseName=你的某个数据库的名字";
String userName="你的数据库登录名";
String userPwd="你的数据库登录password";
try{
//载入驱动程序
Class.forName(driverName);
//获取连接对象
Connection dbConn= DriverManager.getConnection(dbURL, userName, userPwd);
System.out.println("数据库连接成功");
}
catch(Exception e)
{
e.printStackTrace();
}
}
运行以上代码假设打印连接成功,就继续下文。否则。能够评论留言或者自行百度解决。
以下開始解释每一条语句:
首先,全部的操作的前提都是告诉jvm我们的程序将要使用的数据驱动是什么。是mysql,sqlserver,还是oracle。
Class.forName(driverName);这条语句就是这个作用。我们看driverName字符串。
装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");
装载Oracle驱动:Class.forName("oracle.jdbc.driver.OracleDriver");
装载SqlServer驱动:Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
我们上述代码中使用的driverName的值是第三种中的參数值。主流的数据库管理系统是这三者,这三句代码是不变的。读者能够依据自己电脑上的数据库自行选择。
第二步就是获取连接对象,假设没有抛异常就说明连接是成功的。我们首先从三个參数说起。第一个參数是一个URL,他的格式是:jdbc:<子协议>:<子名称>。这样的格式基本上也是被每一个数据库提供商定死了,你仅仅须要选择他们并添加自己的參数就可以。常见的三个URL格式:
对于 Oracle 数据库连接。採用例如以下形式:
jdbc:oracle:thin:@localhost:1521:sid
对于 SQLServer 数据库连接。採用例如以下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
对于 MYSQL 数据库连接,採用例如以下形式:
jdbc:mysql://localhost:3306/sid
sid就是本地数据库中某个详细数据库的名字。以下说第二个參数。从命名上读者也是能够轻松的推断出这是在判别身份,第三个參数是password。相信这三个參数还是能够非常轻松理解的。以下看看DriverManager类和他的一些方法。
DriverManager能够叫它驱动程序管理接口。主要实现的是对驱动程序的管理的功能。比如:初始化驱动程序,启动驱动程序建立jdbc连接对象。另一些获取日志信息的操作。我们主要用它来创建数据库连接对象。然后通过这个对象操作数据库的增删改查。
此间假设数据库连接失败将会抛出异常。
以下我们介绍这个连接对象,并通过它完毕增删改查。
三、使用JDBC增删改查
实现增删改查的操作的前提是须要获取数据库连接对象。
以下是这个Connection接口的主要方法:
Statement createStatement()
PreparedStatement prepareStatement(String sql)
CallableStatement prepareCall(String sql)
先看第一个方法。这种方法返回一个Statement对象,这个对象是用来向数据库发送静态sql语句的,第二个方法返回了一个PreparedStatement对象。这是一个预编译的Statement对象,主要用来发送动态的sql语句的。详细的差别下文说。
第三个方法返回的对象是用来运行存储过程的相关操作的。
以下我们看能够操作一般sql语句的对象Statement。
他有例如以下经常用法:
ResultSet executeQuery(String sql)
int executeUpdate(String sql)
boolean execute(String sql)
int[] executeBatch()
void addBatch( String sql )
測试方法executeQuery
public static void main(String[] args){
try{
//载入驱动程序
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
//获取连接对象
Connection dbConn= DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=FitWeb", "sa", "123456");
Statement statement = dbConn.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM users");
while(rs.next()){
System.out.println(rs.getString("name"));
}
rs.close();
dbConn.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//程序的输出结果是我的表FitWeb中users表中字段名为name的全部的值
对于上代码中的ResultSet结果集的相关操作,临时能够先过。仅仅须要知道我们向executeQuery方法中传入可运行的sql语句。他会返回运行之后的结果。对于方法executeUpdate主要是完毕对数据表的增删改。
int x = statement.executeUpdate("UPDATE users SET NAME = '华为' WHERE NAME ='李斯'");
能够像这样改动表中数据。还能够insert,delete等操作。对于execute方法,它不区分是查询还是改动操作。你能够向他传入随意的sql语句,仅仅是对于查询不会返回结果集,假设成功的改动了表中内容返回true,否则false。以下看看批处理sql操作:
Statement statement = dbConn.createStatement();
statement.addBatch("UPDATE users SET NAME ='Walker' WHERE NAME = '华为'");
statement.addBatch("UPDATE users SET NAME ='华为' WHERE NAME = 'Walker'");
int[] count = statement.executeBatch();
for(int c : count){
System.out.print(c);
System.out.print(",");
}
statement.close();
dbConn.close();
//输出结果:1,1
之前的方法都仅仅能一次操作一条sql语句,而我们的executeBatch是用来一次运行多条sql语句的。返回值是int数组。它表示了每一次操作数据库之后影响的行数。第一次sql运行之后影响的行数保存在索引为0中,后面以此类推。关于预编译Statement的操作。我们放在下一个小节说。
四、JDBC的一些使用细节
SQL注入的大名想必大家都是知道的,而在我们之前介绍的方法中。好像都没有关于怎样防止这样的黑客行为。
SQL注入就是指在带有參数的sql语句中注入的sql语法。相似这样:
select * from users where name = userName
假设我们的应用程序中须要查询某个人的信息,而查询的条件是须要用户输入自己的username,然后我们依据username进行查询,向上面一样假设用户输入的是以下内容:
userName = "'张三' or '李四'";
select * from users where name = userName
等价:
select * from users where name = '张三' or '李四'
这样岂不是将张三和李四的信息都查询出来了,假设此人通过大数据列举,非常可能数据表中的全部数据都会被查询出来。
我们能够使用。预编译Statement对象来避免这件事情。先看代码:
PreparedStatement statement = dbConn.prepareStatement("insert into user(id,Name) values (?,?
)"
);
statement.setInt(1,1);
statement.setString(2,"walker");
statement.executeUpdate();
statement.close();
dbConn.close();
程序运行的结果是,插入一条数据到了我的user表中。
接下来我们看看每条语句是什么含义。
首先。?表示占位符的意思,就是说此处会有參数传入,仅仅是详细的值是什么临时不知道。以下的两条setXXX就是在为占位符赋值。然后运行更改操作。完毕数据库更新。我们说为什么它能够防止Sql注入呢?由于全部用户的输入參数都是用?占位,也就是说不管你传入的是什么,我都仅仅把你当做參数。
userName = "'张三' or '李四'";
select * from users where name = ?
等价:
select * from users where name = ''张三' or '李四''
//相当于:'?'。不管?是什么都不会产生不论什么问题
另外,使用这样的预编译Statement,能够非常大程度上提高性能,由于他会缓存sql模板。就是除了參数部分,其余内容会被缓存,等到下次再遇到的时候会直接调用,提高性能。
因此建议使用这样的方式来操作数据库。
最后详细的介绍一下,关于结果集的操作。
本篇刚開始的时候用过,可是那仅仅是非常easy的一部分。
ResultSet(结果集)接口的主要方法例如以下:
boolean next()
String getString(int columnIndex)
boolean getBoolean(int columnIndex)
int getInt(int columnIndex)
String getString(String columnLabel)
java.sql.Date getDate(int columnIndex)
java.sql.Time getTime(int columnIndex)
java.sql.Timestamp getTimestamp(int columnIndex)
void beforeFirst()
void afterLast()
Blob getBlob(int columnIndex)
Clob getClob(int columnIndex)
这个接口有着四千多行的代码,我们仅仅列举了经常使用的方法。
我们能够将整个结果集理解为一张二维的表,每张表都有一个游标用于遍历全部的行。next()方法用于推断是否还有下一行,返回值是boolean。getXXX方法表示获取当前游标指向的行中指定的字段,能够使用索引来定位字段,也能够是通过字段的名字来定位。
假设是索引,1为起始位置。
关于LOB类型数据,这是一类大对象,往往是图片或者是一些其它的数据。二进制大对象称作BLOB,字符型大对象称作CLOB。调用getBlob或者getClob能够获取到相应的对象。
通过他们自己内部的getBytes,或者getInputStream等方法,能够获取当中的内容。此处不细说。
以下看看多结果集的操作,看代码:
Statement statement = dbConn.createStatement();
boolean b = statement.execute("select * from users;select * from sports;");
if(b){
ResultSet rs = statement.getResultSet();
while (rs.next()){
System.out.println(rs.getString("name"));
}
b = statement.getMoreResults();
if (b){
ResultSet rs2 = statement.getResultSet();
while (rs2.next()){
System.out.println(rs2.getString("sportsName"));
}
}
}
statement.close();
dbConn.close();
我们调用execute方法运行sql语句,而须要运行的是两条sql语句,假设成功的获取了结果集则返回true。通过getResultSet方法获取第一个结果集,输出全部字段名为name的信息,调用getMoreResults方法推断是否有别的结果集。假设有返回true。
然后通过getResultSet获取当前结果集,也就是第二个结果集,输出信息。
为了不使文章篇幅过长。还剩下一个知识点放在下篇。