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

2014-11-23 21:26:05 · 作者: · 浏览: 43
eQuery(); //根据列名取数据 while(rs.next()){ System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t"); } }catch(Exception e){ } }之后我们在执行:

readPrepared("'or 1 or'");
就不会全部查出来了,只会查询空结果,因为表中没有一个学生的名字叫做 'or 1 or'。


下面再来看一下JDBC中特殊数据类型的操作问题

第一个是日期问题:

我们在操作日期问题的时候会发现,使用PreparedStatement进行参数赋值的时候,有一个方法是:setDate(...),但是这个方法接收的参数是sql中的Date类,而不是我们平常使用的util中的Date类,所以我们要做一次转化,通常我们是这样做的,就是在定义实体类的时候将其日期型的属性定义成util中的Date类型,在进行数据库操作的时候.

进行一次转换:setDate(x,new Date(birthday.getTime());,这里birthday就是一个util.Date类型的一个属性,而new Date是sql.Date类型的,这样转化就可以了,同样我们在读取数据的时候将转化操作反过来即可。


第二个问题就是大文本数据的问题,因为有时候我们会存入一些文本内容,因为varchar的大小在mysql中也是有上线的,所以我们这里要使用blob类型了,我们这里来看一下实例:

	/**
	 * 插入大文本
	 */
	static void insert(){
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			String sql = "insert into clob_test(bit_text) values( )";
			ps = conn.prepareStatement(sql);
			File file = new File("src/com/weijia/type/ClubDemo.java");
			Reader reader = new BufferedReader(new FileReader(file));
			//ps.setAsciiStream(1, new FileInputStream(file), (int)file.length());//英文的文档
			ps.setCharacterStream(1, reader, (int)file.length());
			ps.executeUpdate();
			reader.close();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			JdbcUtils.free(rs,ps,conn);
		}
	}
我们将一个Java代码文件插入到数据库

我们查询一下clob_test表:

\

我们看到文件内容存入到库中了。同样我们也可以从表中读取一段文本出来,使用

Clob clob = rs.getClob(1);
InputStream is = clob.getAsciiStream();
或者读取一个Reader也是可以的,这里的InputStream和Reader是针对不同流,一个字节流,这个不需要关心编码问题的,Reader是字符流需要关心编码问题。


下面再来看一下JDBC中事务的概念:

我们当初在学习数据库的时候就了解事务的概念了,事务在数据库中的地位是很重要的。在JDBC中默认情况事务是自动提交的,所以我们在进行CRUD操作的时候不需要关心开启事务,提交事务,事务回滚的一些操作,那么下面我们就来看一下怎么手动的操作一些事务:

下载我们假定这样的一个场景:

有来两个用户1和2,现在

将用户1中的账户的钱减少10
查询用户2中的账户的钱,如果钱少于300,就增加10,否则抛出异常

看一下代码:

static void test() throws Exception{
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			/**************事务START********************/
			conn.setAutoCommit(false);
			st = conn.createStatement();
			
			String sql = "update user set money=money-10 where id=1";
			st.executeUpdate(sql);
			
			sql = "select money from user where id=2";
			rs = st.executeQuery(sql);
			float money = 0.0f;
			if(rs.next()){
				money = rs.getFloat("money");
			}
			if(money>300){
				throw new RuntimeException("已经超过最大值");
			}
			sql = "update user set money=money+10 where id=2";
			st.executeUpdate(sql);
			conn.commit();
			/*******************事务END*********************/
		}catch(RuntimeException e){
			
		}finally{
			JdbcUtils.free(rs, st, conn);
		}
	}
我们运行测试一下,因为我们这里想让它抛出异常,所以我们将用户2中的钱改成大于300的,运行一下,结果抛出异常了,但是我们发现了用户1中的钱少了10,但是由于抛出异常,所以后面的代码不执行了,用户2中的钱没有变化,那么这样的操作明显不对的,所以我们这时候要解决这个问题,使用事务的回滚操作,在捕获到异常的时候需要做回滚操作:

if(conn != null){
   conn.rollback();
}
这样即使抛出了异常,这些操作也会进行回滚的,那么用户1中的钱就不会少10了。

同时上面我们看到,我们是在开始的时候手动的关闭事务的自动提交,然后再手动的提交事务,下面再来看一下事务的保存点的问题。

场景:在上面的基础上,我们添加一个用户3,同时对用户1和用户3中的钱进行减少10,用户2的操作不变,但是当抛出异常的时候,我们希望用户1的操作还是有效的,用户3的操作还原,这时候我们需要将事务回滚到用户3的那个点就可以了,这就是事务的保存点的概念,看一下代码:

static void test() throws Exception{
		Connection conn = null;
		State