jdbc總結
1. 連接數據庫的步驟:
1) 注冊驅動
2) 建立連接
3) 創建語句
4) 執行語句
5) 處理結果
6) 釋放資源(注意關閉的順序)
實例//1.注冊驅動
DriverManager.registerDriver(newcom.mysql.jdbc.Driver());
System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
Class.forName("com.mysql.jdbc.Driver");//推薦方式
//2.建立連接
String url = "jdbc:mysql:localhost:3306/jdbc";
String user = "root";
String password = "mysql";
Connection conn = DriverManager.getConnection(url,user,password);
//3.創建語句
Statement st = conn.createStatement();
//4.執行語句
ResultSet rs = st.executeQuery("select * from user");
//5.處理結果
while(rs.next()){//按行來遍歷
System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t" +rs.getObject(3) + "\t" + rs.getObject(4));
}
//6.釋放資源(注意關閉的順序)
rs.close();
st.close();
conn.close();2. 注意在jdbc中的sql注入問題,解決的辦法是使用PreparedStatement :PreparedStatement ps = null;// 利用PreparedStatement而不用Statement是因為PreparedStatement能夠對輸入的內容進行過濾,除去sql的關鍵字,防止此問題。
3. 數據庫中對大文本的寫入和讀取:clob類的處理
public class ClobTest {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//create();
read();
}
//數據庫的讀取操作
static void read() throws SQLException, Exception {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 3.創建語句
st = conn.createStatement();
// 4.執行語句
rs = st.executeQuery("select big_text from clob_test");
// 5.處理結果
while (rs.next()) {// 按行來遍歷
Reader reader = rs.getCharacterStream(1);
Filefile = newFile("CRUD_bak.java");
Writerwriter = new BufferedWriter(new FileWriter(file));
char[] buff = new char[1024];
for(int i = 0; (i = reader.read(buff))>0;){
writer.write(buff,0, i);
}
writer.close();
reader.close();
}
} finally {
JdbcUtils.free(rs, st, conn);
}
}
//數據庫的創建操作
static void create() throws SQLException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 3.創建語句
String sql = "insertinto clob_test(big_text) values(?)";
ps = conn.prepareStatement(sql);
File file = new File("src/com/lcq/jdbc/CRUD.java");
Reader reader = newBufferedReader(newFileReader(file));
//傳遞大塊的文本文檔
ps.setCharacterStream(1,reader, file.length());
int i = ps.executeUpdate();
reader.close();
System.out.println("i = " + i);
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
}4. 問題blob類型讀取二進制文件
數據庫編譯時異常的處理,編寫自己的異常類
package com.lcq.jdbc.impl;
public class DaoException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public DaoException() {
// TODO Auto-generatedconstructor stub
}
public DaoException(String message) {
super(message);
// TODO Auto-generatedconstructor stub
}
public DaoException(Throwablecause) {
super(cause);
// TODO Auto-generatedconstructor stub
}
public DaoException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generatedconstructor stub
}
}
在使用時
catch(SQLException e){
//異常的處理,轉化為運行時異常
throw new DaoException(e.getMessage(),e);
}在sql中SQLException是編譯時異常,所以要拋出,但是如果只是向上拋出的話,會導致業務層和數據訪問層的關系復雜,后期維護不便;因此最好的解決方法是在數據訪問層中將異常catch住,編寫異常類進行處理,在運行時如果上層能夠處理就處理。從而使業務層和數據訪問層耦合度減少。
5. 一個類的實例化的過程中首先執行的是靜態代碼塊,然后是構造函數。
6.
事務的處理問題:
/**
* 事務處理范例
* 從賬戶1轉賬到賬戶2十元
*
*/
static void test() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
Savepoint sp = null;
try {
conn = JdbcUtils.getConnection();
// 3.創建語句
Conn.setAutoCommit(false);//設置自動提交無效
st = conn.createStatement();
// 4.執行語句
String sql = "updateuser set money=money-10 where id=1";
st.executeUpdate(sql);
//設置回滾點
sp =conn.setSavepoint();
sql = "update userset money=money+10 where id=3";
st.executeUpdate(sql);
sql = "selectmoney from user where id=2";
rs = st.executeQuery(sql);
float money = 0.0f;
// 5.處理結果
if (rs.next()) {// 按行來遍歷
money = rs.getFloat("money");
}
if(money > 300){
throw new RuntimeException("已經達到最大值!");
}
sql = "update userset money=money+10 where id=2";
st.executeUpdate(sql);
conn.commit();
} catch(RuntimeException e){
if(conn != null && sp != null)
//回滾到設置的點
conn.rollback(sp);
//遞交,使以上操作有效
conn.commit();
throw e;
}catch(SQLException e){
if(conn != null)
conn.rollback();
throwe;
}finally {
JdbcUtils.free(rs, st, conn);
}
}7. 跨越多個數據源的事務(JTA)實現分布式的數據處理,事務處理步驟:
1) 打開事務
2) 提交事務
3) 回滾事務
8. 在數據庫中編寫組件(函數),通過ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//能夠得到數據庫中的組件。這樣通過組件可以在用戶向數據庫中添加數據時,在返回時可以用組件對結果進行標識,說明數據已經在數據庫中得到更新。
9. 批處理,對sql語句的打包。
10.
根據用戶的查詢需求進行查詢,并將結果封裝為Map返回
public classResultSetMetaDataTest {
/**
* @param args
* @throws SQLException
*/
public static void main(String[] args) throws SQLException {
List<Map<String, Object>> datas = read("select * from user");
System.out.println(datas);
}
static List<Map<String, Object>> read(String sql) throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaDatarsmd = rs.getMetaData();
//得到結果集的列數
intcount = rsmd.getColumnCount();
String[] colNames = new String[count];
for(int i = 1; i < colNames.length;i++){
colNames[i-1] = rsmd.getColumnName(i);
}
List<Map<String, Object>> datas = newArrayList<Map<String, Object>>();
// 5.處理結果
while (rs.next()) {// 按行來遍歷,將每一行添加到map中,list中最后存放的是表
Map<String,Object> data = new HashMap<String, Object>();
for(inti = 1;i<= colNames.length;i++){
data.put(colNames[i-1],rs.getObject(i));
}
datas.add(data);
}
return datas;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
}11. 對象與關系的映射(利用反射)
public class ORMTest {
/**
* @param args
* @throwsInvocationTargetException
* @throwsIllegalAccessException
* @throws SQLException
* @throwsIllegalArgumentException
* @throws InstantiationException
*/
public static void main(String[] args) throws IllegalArgumentException,
SQLException, IllegalAccessException,InvocationTargetException,
InstantiationException {
User user = (User) getObject(
"select idas Id ,name as Name, birthday as Birthday,money as Money from user whereid=2",
User.class);
System.out.println(user);
}
static ObjectgetObject(String sql, Class clazz) throws SQLException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException, InstantiationException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
// 得到結果集的列數
int count = rsmd.getColumnCount();
String[] colNames = new String[count];
for (int i = 1; i <= colNames.length; i++) {
colNames[i - 1] = rsmd.getColumnLabel(i);
}
Object object = null;
Method[] ms = clazz.getMethods();
// 5.處理結果
if (rs.next()) {// 按行來遍歷,將每一行添加到map中,list中最后存放的是表
object = clazz.newInstance();
for (int i = 0; i < colNames.length; i++) {
String colName = colNames[i];
String methodName = "set" + colName;
// System.out.println(methodName);
for (Method m : ms) {
if (methodName.equals(m.getName())) {
m.invoke(object, rs.getObject(colName));
}
}
}
}
return object;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
}12. 創建數據庫連接池,先創建多個連接,將連接一次放在List的尾部,用的時候從List的頭部取出連接,使用連接;用完釋放連接的時候是將連接返回到連接池的尾部,供后邊的用戶使用。達到連接重復使用的目地。
/**
*
* 創建數據庫連接池
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
public class MyDataSource {
private static String url = "jdbc:mysql://localhost:3306/jdbc";
private static String user = "root";
private static String password = "mysql";
private LinkedList<Connection>connectionsPoll = new LinkedList<Connection>();
public MyDataSource(){
for(int i = 0; i<5;i++){
try {
this.connectionsPoll.addLast(this.createConnection());
} catch (SQLException e) {
throw newExceptionInInitializerError(e);
}
}
}
public Connection getConnection(){
return this.connectionsPoll.removeFirst();
}
private Connection createConnection() throws SQLException{
return DriverManager.getConnection(url, user, password);
}
public void free(Connection conn){
this.connectionsPoll.addLast(conn);
}
}13. 對創建連接的優化,利用dbcp作為數據源,從數據源中取出連接。編寫自己的數據源。對代碼的優化是從“變與不變”入手的。
14. 通過模板模式對增刪改查進行優化,利用抽象和繼承實現。
15. 利用工廠模式和sping對數據庫的封裝進行最終版本的實現。