天天看點

傳智播客李勇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出來了 程式就不繼續往下運作了