天天看点

传智播客李勇Jdbc视频笔记(7-17)

7、PerparedStatement的应用:

在上面的例子中,我们看到了在构造sql语句的时候使用拼串的方式会有sql注入的问题,这个时候我们可以用

PreparedStatement 来解决这个问题

public void read(String name) {
		......
		PreparedStatement ps = null;
		String sql = "select * from xxx where name = ?";
		ps = conn.prepareStatement(sql);
		ps.setString(1, name);
		rs = ps.executeQuery();
		......
		..
	}
           

如果我们采用上面的方式来构造sql语句就不会有sql注入问题了,因为PerparedSatatement会对传递给他的sql

语句进行一系列的处理。然后再执行。

注意:rs = ps.executeQuery()如果你写成了rs = ps.executeQuery(sql)编译器也是不会报错的,因为PerparedSatement

是从Satement继承来的,所以如果你调用的是ps.executeQuery(String sql)这个带有参数的方法的时候,其实是调用的

Statement接口的方法,因为你上面sql语句是用PerparedStatement的方式进行构造的 用?代替了参数部分,这个时候会包

错误说 ? 是非法字符,因为调用的是Statement的方法他不会对?进行处理直接传递给数据库执行,而数据库是不能解析

这个字符的。

总结:

在SQL中包含特殊字符或SQL的关键字(如:' or 1 or ')时Statement将出现不可预料的结果(出现异常或查询的结果不正确),可用PreparedStatement来解决。

PreperedStatement(从Statement扩展而来)相对Statement的优点:

1.没有SQL注入的问题。

2.Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。

3.数据库和驱动可以对PreperedStatement进行优化(只有在相关联的数据库连接没有关闭的情况下有效)。

9、Eclipse的使用问题

10、jdbc中的数据类型与日期问题

public class DateTest {
		public static void main(String[] args) throws SQLException {
			// create("name2", new Date(), 500.0f);
			Date d = read(7);
			System.out.println(d);
		}

		static Date read(int id) throws SQLException {
			Connection conn = null;
			Statement st = null;
			ResultSet rs = null;
			Date birthday = null;
			try {
				// 2.建立连接
				conn = JdbcUtils.getConnection();
				// conn = JdbcUtilsSing.getInstance().getConnection();
				// 3.创建语句
				st = conn.createStatement();

				// 4.执行语句
				rs = st.executeQuery("select birthday  from user where id=" + id);

				// 5.处理结果
				while (rs.next()) {
					//birthday = new Date(rs.getDate("birthday").getTime());
					//取值的时候是java.sql.Date赋值给一个父类类型java.util.Date是没有问题的
					birthday = rs.getDate("birthday");
				}
			} finally {
				JdbcUtils.free(rs, st, conn);
			}
			return birthday;
		}

		static void create(String name, Date birthday, float money)
				throws SQLException {
			Connection conn = null;
			PreparedStatement ps = null;
			ResultSet rs = null;
			try {
				// 2.建立连接
				conn = JdbcUtils.getConnection();
				// conn = JdbcUtilsSing.getInstance().getConnection();
				// 3.创建语句
				String sql = "insert into user(name,birthday, money) values (?, ?, ?) ";
				ps = conn.prepareStatement(sql);
				ps.setString(1, name);
				//插入的时候传递的是java.util.Date而方法要求的是java.sql.Date,所以要进行一下转化
				ps.setDate(2, new java.sql.Date(birthday.getTime()));
				ps.setFloat(3, money);

				// 4.执行语句
				int i = ps.executeUpdate();

				System.out.println("i=" + i);
			} finally {
				JdbcUtils.free(rs, ps, conn);
			}
		}
	}
           

11、jdbc访问大段文本数据:数据库产品不一样,字段可能不同:mysql:Text Oracle:可能是Clob

//存储大段文本数据
	public static void clobTest() throws SQLException, IOException {
		Connection conn = JdbcUtils.getConnection();
		String sql = "insert into clob(content) values (?)";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		//把一个文件的内容读进来存储到数据库中
		File file = new File("src/org/guo/jdbc/JdbcUtils.java");
		//如果你把reader转换为数组,然后再转换成String,在这个地方可以直接pstmt.setString()
		//前提是你的数据库的那个字段规定的是Clob(Text)类型,那么在下面取数据的时候
		//可以直接getString()进行读取操作。
		Reader reader = new BufferedReader(new FileReader(file));
		//以字符流的方法设置参数
		pstmt.setCharacterStream(1,reader, file.length());
		pstmt.executeUpdate();
	}

	//读取大段文本数据
	public static void readTest() throws SQLException, IOException {
		Connection conn = JdbcUtils.getConnection();
		String sql = "select content from clob";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		while(rs.next()) {
			//字符大对象
			Clob clob = rs.getClob(1);
			//下面两种方式都可以
			//Reader reader = clob.getCharacterStream();
			Reader reader = rs.getCharacterStream(1);
			File fileBak = new File("jdbcUtils.bak.java");

			Writer writer = new BufferedWriter(new FileWriter(fileBak));
			char[] data = new char[1024];
			//reader.read(data):把读取到的一个字符放到data字符数组中
			for(int i=0; (i=reader.read(data)) >0;) {
				//把字符数组中的内容写到文件中
				writer.write(data, 0, i);
			}
			writer.close();
			reader.close();
		}
	}
           

12、jdbc访问二进制类型的数据

//存储二进制数据(图片为例)
	public static void blobTest() throws SQLException, IOException {
		Connection conn = JdbcUtils.getConnection();
		String sql = "insert into t_blob(big_bit) values (?)";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		File file = new File("baby.gif");
		InputStream in = new BufferedInputStream(new FileInputStream(file));
		pstmt.setBinaryStream(1, in, file.length());
		pstmt.executeUpdate();
	}

	//读取二进制数据
	public static void readTest() throws SQLException, IOException {
		Connection conn = JdbcUtils.getConnection();
		String sql = "select big_bit from t_blob";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		while(rs.next()) {
			//二进制大对象
			Blob blob = rs.getBlob(1);
			//下面两种方式都可以
			//Reader reader = clob.getCharacterStream();
			InputStream in = blob.getBinaryStream();
			//下面这种方式也可以,和读取大段文本数据的原理是一样的
			//InputStream in = rs.getBinaryStream(1);
			File imgBit = new File("baby2.gif");

			OutputStream out = new BufferedOutputStream(new FileOutputStream(imgBit));
			byte[] data = new byte[1024];
			for(int i=0; (i=in.read(data)) >0;) {
				out.write(data, 0, i);
			}
			out.close();
			in.close();
		}
	}
           

13、JDBC_jdbc访问其他各种数据类型:解释数据库中的类型与java中的数据类型的相互的对应关系--------->查看mysql的参考文档

14、传智播客JDBC_答疑学员的索引号问题

15、分析在实际项目中该如何应用

[img]http://dl.iteye.com/upload/attachment/229131/d85facce-6862-33ab-b00c-6d1e4a988668.jpg[/img]

我们上面的例子程序都是简单的在控制台打印一下,但是在真实的开发中不可能这样,那么我们能不能返回ResultSet对象呢?

这个其实是不可以的当Connection关闭之后,ResultSet中的数据你就拿不到了。如果我们要进行传值需要定义个domain对象。

16、DAO设计思想与搭建骨架

17、结合Service层讲解DAO层的异常处理

在处理异常的时候,不能catch住异常之后什么都不做,最起码要打印一下堆栈,最好的方式是将这个异常转化为RuntimeException抛出

如果出现了异常,你catch住了,程序会继续往下执行。如果你throw出来了 程序就不继续往下运行了