J2EE学习篇之--JDBC详解(五)

2014-11-23 21:26:05 · 作者: · 浏览: 42
tion(Exception e){ super(e); } public DaoException(String msg){ super(msg); } public DaoException(String msg,Exception e){ super(msg,e); } }
同时,我们这里面采用工厂模式进行实例化UserDao对象:

package com.weijia.domain;

import java.io.FileInputStream;
import java.util.Properties;

public class DaoFactory {
	/**
	 * 单例模式
	 */
	private static UserDao userDao = null;
	private static DaoFactory instance = new DaoFactory();
	
	private DaoFactory(){
		/**
		 * 通过读取属性文件来动态的加载Dao层类
		 */
		Properties prop = new Properties();
		try{
			FileInputStream fis = new FileInputStream("src/com/weijia/domain/daoconfig.properties");
			prop.load(fis);
			String className = prop.getProperty("userDaoClass");
			Class
   clazz = Class.forName(className);
			userDao = (UserDao)clazz.newInstance();
			fis.close();
		}catch(Throwable e){
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static DaoFactory getInstance(){
		return instance;
	}
	
	public UserDao createUserDao(){
		return userDao;
	}

}
这里面是读取properties文件,然后去读取类名进行加载,这种方式是很灵活的


测试:

package com.weijia.domain;

import java.util.Date;

public class TestDemo {
	
	public static void main(String[] args) throws Exception{
		UserService userService = new UserService();
		System.out.println("添加用户:");
		userService.regist(new User(1,"jiangwei",new Date(System.currentTimeMillis()),300));
	}

}

这里我们看到其实这些操作真的很简单,就是按照那样的几个步骤来操作即可,同时我们还需要将结构进行分层,以便管理,我们这里面测试的时候,撇开了创建数据库的一个环节,至于那个环节,也是不难的,可以从网上搜索一下即可。


接着来看一下关于我们上面的例子中使用了Statement进行操作的,其实这里面是存在一个问题的,就是会有sql注入的问题,我们先来看一下这个问题:

查询学生信息:

	/**
	 * 使用Statement读取数据
	 * @param name
	 * @throws SQLException
	 */
	static void read(String name) throws SQLException{
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getConnection();
			//创建语句
			st = conn.createStatement();
			//执行语句(不建议使用*)
			String sql = "select id,name from user where name='"+name+"'";
			rs = st.executeQuery(sql);
			//根据列名取数据
			while(rs.next()){
				System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t");
			}
		}catch(SQLException e){
			e.printStackTrace();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JdbcUtils.free(rs, st, conn);
		}
	}

我们使用代码测试一下:

read("'or 1 or'");
我们运行会发现,将查询出所有的学生的记录,这个是什么原因呢?我们不妨将sql打印一下会发现:

select id,name from user where name=''or 1 or''
擦,因为sql语句中把1认为是true,又因为是或的关系,所以将所有的学生的信息查询出来了,这个就是sql注入,因为Statement会把传递进来的参数进行一下转化操作,用引号包含一下,所以会出现这个问题,那么我们该怎么解决呢?有的同学说我们可以添加一句过滤的代码,将传递的参数取出单引号,这个方法是可行的的,但是这个只能解决那些使用单引号的数据库,可能有的数据库使用的是双引号包含内容,那就不行了,所以应该想一个全套的方法,那么这里我们就是用一个叫做:PreparedStatement类,这个类是Statement类的子类,关于这两个类的区别可以查看我的另外一片文章:

http://blog.csdn.net/jiangwei0910410003/article/details/26143977

我们这里只看这个sql注入的问题:

我们将上面读取用户信息的代码改写成PreparedStatement:

	/**
	 * 使用PreparedStatement
	 * @param name
	 * @throws SQLException
	 */
	static void readPrepared(String name) throws SQLException{
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			//执行语句(不建议使用*)
			String sql = "select id,name from user where name= ";
			//创建语句
			st = conn.prepareStatement(sql);
			st.setString(1, name);
			rs = st.execut