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出來了 程式就不繼續往下運作了