`
Before_Morning
  • 浏览: 35872 次
文章分类
社区版块
存档分类
最新评论

JDBC基础知识(备忘)

 
阅读更多
 自从出来后,就很少用到了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);
		}
		
	}
	
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics