自从出来后,就很少用到了JDBC,大部分时间都是用框架的东西,对jdbc的知识也有些遗忘了。最近,换了项目组,接手了一个财务结算的子系统平台,因为这些对于数据的查询效率相对来说要严格点,底层的东西还相对于hibernate框架中封装好的机制来说还是是比较快的。正好有时间可以对jdbc的知识温习下。
一、JDBC的基本概念
数据库驱动也就是数据库厂商提供的jar包。sun公司为了降低学习数据库开发的成本,提供了JDBC这一套接口规范。
二、JDBC的基本使用
A.使用jdbc开发的步骤是固定的:
首先,要导入数据库驱动的jar包,然后按照下面的步骤
1.注册数据库驱动:
Class.forName("com.mysql.jdbc.Driver");
2.获取数据库连接:
Connection conn = DriverManager.getConnection(url,userName,passWord);
3.获取传输器:
Statement stat = conn.createStatement();//statement接口
创建向数据库发送sql的statement对象
OR
PrepareStatement ps = conn.perpareStatement(sql);//preparestatement接口
创建向数据库发送预编译sql的PrepareStatement对象
4.利用传输器执行sql语句获取结果集:
ResultSet rs = stat.executeQuery(sql);
用于向数据库发送查询语句
OR
int count = stat.executeUpdate(sql);
用于向数据库发送insert,update或delete语句
OR
stat.execute(sql);
用于向数据库发送任意sql语句
5.遍历结果集:
ResultSet:以表的样式在内存中保存了查询结果,其中还维护了一个游标,最开始的时候游标在第一行之前,每次调用因此next()方法就试图下移行,
如果移动成功返回true.
ResultSet提供了很多Get方法,用来获取查询结果中的不同类型的数据。
6.释放连接:
Connection是一个有限的资源,用完之后要立即释放掉
Statement/PrepareStatement占用内存,所以使用完后也要释放
ResultSet占用内存,所以使用之后也要释放掉
B.实例参考:
1.java工程的结构:
2.数据库配置文件:
driver=com.mysql.jdbc.Driver userName=root passWord=1234 url=jdbc:mysql://localhost:3306/jdbc dao=com.jjyy.jdbc.dao.UserDao
3.Jdbc的简单的工具类
package com.jjyy.jdbc.utils; import java.io.FileReader; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * * @author JiangYu * */ public class JDBCUtil { private static Properties prop = null; private static Connection conn= null; static{ prop = new Properties(); try { prop.load(new FileReader(JDBCUtil.class.getClassLoader().getResource("").getPath())); } catch (Exception e) { e.printStackTrace(); } } private JDBCUtil(){} public static Connection getConnection() throws Exception{ Class.forName(prop.getProperty("driver")); if(null==conn){ conn = DriverManager.getConnection(prop.getProperty("url"),prop.getProperty("userName"),prop.getProperty("passWord")); } return conn; } public static void close(Connection conn,Statement stat,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } if(stat!=null){ try { stat.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ stat = null; } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } } }
4.DaoFactory
package com.jjyy.jdbc.factory; import java.io.FileReader; import java.util.Properties; import com.jjyy.jdbc.dao.UserDao; /** * * @author JiangYu * 2015年3月28日 * */ public class DaoFactory { private static Properties prop = null; // private static DaoFactory factory = new DaoFactory(); // // private DaoFactory(){}; // // public static DaoFactory getInstance(){ // return factory; // } private DaoFactory(){} private static class DaoFactoryHolder{ private static final DaoFactory ENCE = new DaoFactory(); } public static final DaoFactory getInstance(){ return DaoFactoryHolder.ENCE; } static{ prop = new Properties(); try { prop.load(new FileReader(DaoFactory.class.getClassLoader().getResource("config.properties").getPath())); } catch (Exception e) { e.printStackTrace(); } } public UserDao getDao(){ Class clazz; try { clazz = Class.forName(prop.getProperty("dao")); return (UserDao) clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
5.UserDao接口的实现类
package com.jjyy.jdbc.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import com.jjyy.jdbc.dao.UserDao; import com.jjyy.jdbc.entity.User; import com.jjyy.jdbc.utils.JDBCUtil; /** * * @author JiangYu * 2015年3月28日 * */ public class UserDaoImpl implements UserDao { @Override public void add(User user) { // TODO Auto-generated method stub } @Override public User findByName(String userName) { User user = new User(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); ps = conn.prepareStatement("select * from user where userName=?"); ps.setString(1, "jjyy"); rs = ps.executeQuery(); while(rs.next()){ user.setName(rs.getString("userName")); user.setPassWord(rs.getString("passWord")); user.setAge(rs.getInt("age")); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.close(conn, ps, rs); } return user; } }
三、PrepareStatement和Statement的区别:
1.问题的引入:
Sql注入:用于jdbc程序在执行的过程中sql语句在拼装时,使用了有页面传入的参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生改变,
这种攻击方式就是sql注入。
解决方式:由于PrepareStatement使用预编译机制,在创建PrepareStatement对象的时候就需要将sql语句传入,传入的过程中参数要用?替代,这个过程会导
致传入的sql被预编译,然后在调用PrepareStatement的setXXX将参数设置上去,由于sql语句已经经过了预编译,在传入的特殊值也只会当做特定位置的值传入
了,所以也就可以解决sql注入的问题。
2.PrepareStatement使用了预编译机制,相对于Statement来说,sql语句在执行的过程中效率要高,下面以执行批处理做实例:
【Statement】
package com.jjyy.jdbc.dao.impl; import java.sql.Connection; import java.sql.Statement; import com.jjyy.jdbc.dao.StatBatchDao; import com.jjyy.jdbc.utils.JDBCUtil; /** * statement 执行批处理时,可以执行任意类型的sql语句,但是它没有使用预编译,效率比较低 * @author JiangYu * */ public class StatBatchDaoImpl implements StatBatchDao { @Override public void create() { Connection conn = null; Statement stat = null; try { conn = JDBCUtil.getConnection(); stat = conn.createStatement(); stat.addBatch("create database jjyy"); stat.addBatch("user jjyy"); stat.addBatch("create table user(" + " id int(11) auto_increatement," + " name varchar(20)," + " password varchar(30)," + " age int(11)" + ")"); stat.addBatch("insert into user values(1,jjyy,123,23)"); stat.executeBatch(); } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.close(conn, stat, null); } } }
【PrepareStatement】
<pre class="java" name="code">package com.jjyy.jdbc.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import com.jjyy.jdbc.dao.PsBatchDao; import com.jjyy.jdbc.utils.JDBCUtil; /** * preparestatement 的批处理: * 优点:有预编译机制,效率比较高,执行多条结构相同,参数不同的sql时,不需要重复写sql的主干 * 缺点:只能执行主干相同的参数不同的sql,没有办法在一个批处理中加入结构不同的sql * @author JiangYu * */ public class PsBatchDaoImpl implements PsBatchDao{ @Override public void create() { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConnection(); ps = conn.prepareStatement("insert into user values(null,?,?,?)"); for(int i=0;i<=1000000;i++){ ps.setString(1, "name"+i); ps.setString(2, "jjyy"+i); ps.setInt(3, i); ps.addBatch(); if(i%1000==0){ ps.executeBatch(); ps.clearBatch(); } } ps.executeBatch(); } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.close(conn, ps, null); } } }