JDBC基础知识(备忘)

来源:互联网 发布:排序算法总结 编辑:程序博客网 时间:2024/04/30 23:00
          自从出来后,就很少用到了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.DriveruserName=rootpassWord=1234url=jdbc:mysql://localhost:3306/jdbcdao=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 {@Overridepublic void add(User user) {// TODO Auto-generated method stub}@Overridepublic 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 {@Overridepublic 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{@Overridepublic 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);}}}

 

0 0
原创粉丝点击