JDBC(其实是一种jar包)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。即可以实现客户端与服务器端通信,执行数据库操作的一种技术
Java连接数据库的过程
应用程序---加载驱动---访问数据库----将数据返回给应用程序
什么是驱动?
驱动:连接数据库的工具
Jdbc驱动类型:
1. JDBC-ODBC桥
运行原理:把所有 JDBC的调用传递给ODBC ,再由ODBC调用本地数据库驱动代码
要求:客户端必须安装odbc驱动,不适合使用
结论:所以,执行效率比较低,对于那些大数据量存取的应用是不适合的
2. 本地API驱动
运行原理:本地API驱动直接把JDBC调用转变为数据库的标准调用再去访问数据库
要求:在客户端加载数据库厂商提供的代码库
结论:执行速率比第一种高,但是也不是很高
3. 网络协议驱动
运行原理:JDBC先把对数局库的访问请求传递给网络上的中间件服务器.中间件服务器再把请求翻译为符合数据库规范的调用,再把这种调用传给数据库服务器(即网络协议驱动---------中间件服务器------------数据库Server)
要求:在中间件层仍然需要有配置其它数据库驱动程序
结论:由于多了一个中间层传递数据,它的执行效率还不是最好
4. 本地协议驱动
运行原理:把JDBC调用转换为符合相关数据库系统规范的请求,可以直接和数据库服务器通讯
要求:对于不同的数据库需要下载不同的驱动程序
结论:不需要先把JDBC的调用传给ODBC或本地数据库接口或者是中间层服务器.所以它的执行效率是非常高的
JDBC连接数据库的步骤:
1. 加载JDBC驱动程序(在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM)
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
Class.forName(“com.mysql.jdbc.driver”);
2. 创建数据库连接对象Connection
协议:子协议:数据源标识
协议:在JDBC中总是以jdbc开始 子协议:是连接的驱动程序或是数据库管理系统名称。
数据源标识:标记找到数据库来源的地址与连接端口。
jdbc:mysql://localhost:3306/sys?user=root&password=zyt123
jdbc:mysql://localhost:3306/sys
Connection conn = (Connection)DriverManager.getConnection(url, 用户名, 密码);
3. 创建一个可向数据库发送SQL命令并返回结果的传送对象Statement
Statement st = (Statement)conn.createStatement();
4. 执行SQL命令并处理返回结果
ResultSet rs =st.executeQuery("select * from mytable");
5. 处理后,如果有返回结果集,关闭结果集对象ResultSet
while (rs.next()) {
System.out.println(rs.getString(1) + "\t" + rs.getString(2))
}
6. 关闭对应的 Statement 对象
conn.close();
7. 关闭连接对象Connection
package study1115;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class JDBC {
//创建一个本地协议驱动的常量
public static final String DBURL = "jdbc:mysql://localhost:3306/booklending" ;
//创建一个用户名常量
public static final String DBUSER = "root" ;
//创建一个密码的常量
public static final String DBPASSWORD = "1111" ;
public static void main(String[] args) throws SQLException {
Connection connection = null ;
Statement statement = null ;
try {
//三种加载JDBC驱动程序,通用(在连接数据库之前先要将驱动程序加载到JVM)
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//System.setProperty("jdbc.drive","com.mysql.jdbc.Driver");
Class.forName("com.mysql.jdbc.Driver");
//创建连接数据库的对象connection
connection = (Connection)DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);
//创建一个可像数据库发送SQL命令并返回结果的传送对象statement
statement = (Statement)connection.createStatement();
//执行SQL命令并返回处理结果储存到Resultset对象中
ResultSet resultSet = statement.executeQuery("select * from readerinfo");
//通过循环的方式取出所有内容
while (resultSet.next()) {
String reader_id = resultSet.getString(1);
String person_name = resultSet.getString(2);
String birthday = resultSet.getString(3);
String person_id = resultSet.getString(4);
String person_info = resultSet.getString(5);
String person_number = resultSet.getString(6);
String address = resultSet.getString(7);
System.out.println(reader_id+"\t"+person_name+"\t"+birthday+"\t"+person_id+"\t"+person_info+"\t"+person_number+"\t"+address);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关闭对应的statement对象,立即释放此对象的数据库和jdbc资源。关闭statement对象时同时关闭当前ResultSet对象
statement.close();
//关闭数据库连接
connection.close();
}
}
}
PreparedStatement接口
PreparedStatement接口是Statement的子接口,属于预处理操作
开发中一般不会使用Statement接口,因为其采用的是拼接式的SQL语句形式,这样就有可能造成SQL注入漏洞。而且PrepareStatement接口因为其预处理的方式在处理大量数据时效率更高
操作过程与Statement接口相似
package study1115;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ConnectionDeme2 {
public static void main(String[] args) throws SQLException {
//创建SQL语句
String sql = "select * from readerinfo where address like ? and person_info in (?)" ;
//设置第一个用于模糊查找的参数
String stringTemp = "%王者%" ;
//设置第二个参数值
int intTemp = 1 ;
//创建数据库连接(此处将加载驱动和取得connection对象封装成了方法直接调用)
java.sql.Connection connection = myutil.booklending.JDBC.getConnection() ;
//取得PreparedStatement对象(此处将取得PreparedStatement对象封装成了方法直接调用)
java.sql.PreparedStatement preparedStatement = myutil.booklending.JDBC.getPrepare(connection, sql) ;
try {
//将参数1设置进PreparedStatement对象中
preparedStatement.setString(1, stringTemp);
//将参数2设置进PreparedStatement对象中
preparedStatement.setInt(2, intTemp);
//返回结果集对象ResultSet
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {//循环的方式输出内容
System.out.println(resultSet.getString(1)+"\t"+resultSet.getString(2)+"\t"+resultSet.getString(3)+"\t"+resultSet.getString(4)+"\t"+resultSet.getString(5)
+"\t"+resultSet.getString(6)+"\t"+resultSet.getString(7)+"\t"+resultSet.getString(8));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//关闭对应的PreparedStatement对象,立即释放此对象的数据库和jdbc资源。关闭PreparedStatement对象时同时关闭当前ResultSet对象
preparedStatement.close();
//关闭数据库连接
connection.close();
}
}
}
关于PreparedStatement接口,需要重点记住的是:
1. PreparedStatement可以写参数化查询,比Statement能获得更好的性能。
2. 对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,这种预处理语句查询比普通的查询运行速度更快。
3. PreparedStatement可以阻止常见的SQL注入式攻击。
4. PreparedStatement可以写动态查询语句
5. PreparedStatement与java.sql.Connection对象是关联的,一旦你关闭了connection,PreparedStatement也没法使用了。
6. “?” 叫做占位符。
7. PreparedStatement查询默认返回FORWARD_ONLY的ResultSet,你只能往一个方向移动结果集的游标。当然你还可以设定为其他类型的值如:”CONCUR_READ_ONLY”。
8. 不支持预编译SQL查询的JDBC驱动,在调用connection.prepareStatement(sql)的时候,它不会把SQL查询语句发送给数据库做预处理,而是等到执行查询动作的时候(调用executeQuery()方法时)才把查询语句发送个数据库,这种情况和使用Statement是一样的。
9. 占位符的索引位置从1开始而不是0,如果填入0会导致*java.sql.SQLException invalid column index*异常。所以如果PreparedStatement有两个占位符,那么第一个参数的索引时1,第二个参数的索引是2.
以上就是为什么要使用PreparedStatement的全部理由,不过你仍然可以使用Statement对象用来做做测试。但是在生产环境下你一定要考虑使用 PreparedStatement 。