一、本文记录一下jdbc的知识点,分享感受,并记录一些注意事项。

二、JDBC连接数据库步骤:参考了文章     

1)     加载JDBC驱动程序:  

在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的静态方法forName(String  className)实现。成功加载后,会将driver类的实例注册到DriverManager类中。  

示例:  

try {
// 加载MySql的驱动类
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("找不到驱动程序类 ,加载驱动失败!");
e.printStackTrace();
}



 

2)     创建数据库的连接  

a)     通过java.sql.DriverManager的getConnectin(String url , String userName , String password )方法获得Connection对象。  

url:连接的数据库的路径

userName:数据库的用户名

password:密码




b)     url说明:

URL定义了连接数据库时的协议(在JDBC中总是以jdbc开始)、子协议(驱动程序名或数据库名称)、数据源标识(数据库来源的地址与连接端口)

格式:协议:子协议:数据源标识

jdbc:mysql: //127.0.0.1:3306/test?useUnicode=true&characterEncoding=gbk;




c)     示例:(连接mysql数据库)  




String url = " jdbc:mysql: //127.0.0.1:3306/test?useUnicode=true&characterEncoding=gbk";

String username = "root";

String password = "root";

try {

Connection con = DriverManager.getConnection(url, username, password);

} catch (SQLException e) {

System.out.println("数据库连接失败!");

e.printStackTrace();

}

        

3)     创建一个Statement并执行SQL语句 

要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:  

a)     执行静态SQL语句。通常通过Statement实例实现。

Statement stmt = con.createStatement();

Statement接口提供了三种执行SQL语句的方法:executeQuery、executeUpdate和execute

1、ResultSet executeQuery(StringsqlString):执行查询数据库的SQL语句,返回一个结果集(ResultSet)对象。  

ResultSet rs = stmt.executeQuery("SELECT * FROM...") ; 

2、 int executeUpdate(StringsqlString):用于执行INSERT、UPDATE或DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等  

int rows = stmt.executeUpdate("INSERT INTO...") ;

3、execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的语句。  

booleanflag = stmt.execute(String sql) ;








b)     执行动态SQL语句。通常通过PreparedStatement实例实现。

PreparedStatement pstmt = con.prepareStatement(sql) ;

示例:

String sql = "insert into test values(?, ?,?)";
try {
PreparedStatement psmt = con.prepareStatement(sql);
psmt.setString(1, "123");
psmt.setString(2, "12");
psmt.setInt(3, 3);
// psmt.setData()该Data变量是java.sql.Data,而不是java.util.Data。
int count = psmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}

c)     执行数据库存储过程。通常通过CallableStatement实例实现。

CallableStatementcstmt = con.prepareCall("{CALL demoSp(? , ?)}") ;







               

4)     处理结果  

 两种情况:  

1、执行更新返回的是本次操作影响到的记录数。  

2、执行查询返回的结果是一个ResultSet对象。ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些行中数据的访问,使用结果集(ResultSet)对象的访问方法获取数据:  

while (rs.next()) {
String name = rs.getString("name");
String pass = rs.getString(1); // 此方法比较高效。列是从左到右编号的,并且从列1开始
}



 

5)     关闭JDBC连接对象   

操作完成以后要把所有使用的JDBC对象关闭,以释放JDBC资源,关闭顺序和声明顺序相反:  

1、关闭记录集  

2、关闭声明  

3、关闭连接对象  




if (rs != null) { // 关闭记录集 

try { 

rs.close(); 

rs = null; 

} catch (SQLException e) { 

e.printStackTrace(); 

} 

} 

if (stmt != null) { // 关闭声明 

try { 

stmt.close(); 

stmt = null; 

} catch (SQLException e) { 

e.printStackTrace(); 

} 

} 

if (conn != null) { // 关闭连接对象 

try { 

conn.close(); 

conn = null; 

} catch (SQLException e) { 

e.printStackTrace(); 

} 

}



三、PreparedStatement和statement区别:



1、语法区别


1)Statement:
Statement stmt = conn.CreateStatement();
resultSet rs = stmt.executeQuery(sql);
2)PreparedStatement:
PreparedStatement ptmt = conn.prepareStatement(sql);
resultSet rs = ptmt.executeQuery();



2、代码的可读性和可维护性方面


stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('" + var1 + "','" + var2 + "'," + var3 + ",'" + var4 + "')");



PreparedStatement ptmt = conn.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
ptmt.setString(1, var1);
ptmt.setString(2, var2);
ptmt.setString(3, var3);
ptmt.setString(4, var4);
ptmt.executeUpdate();




PreparedStatement优于Statement。




3、性能方面,PreparedStatement能提高性能


每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个函数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.如:
            insert into tb_name (col1,col2) values ('11','22');
            insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.
当然并不是所有预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.
statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译的,preparedstatement支持批处理,preparedstatement的性能更好。




4.安全性方面


String sql = "select * from tb_name where name= '" + varname + "' and password='" + password + "'";
如果我们把[' or '1' = '1]作为password传入进来.用户名root,看看会成为什么?
select * from tb_name = 'root' and password = '' or '1' = '1';
因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:把[';drop table tb_name;]作为password传入进来,则:
select * from tb_name = 'root' and password = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.




而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就不用对传入的数据做任何过滤.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过滤.





四、总结


1、在JDBC使用的时候一定要记得关闭连接,释放资源。

2、由于preparedstatement具备很多优点,开发者尽量使用它。只有在一行sql语句中没有变量的时候才使用通常的statement。