@(Java)代碼片段
數(shù)據(jù)庫是經(jīng)常會涉及到的,對于JDBC來說,已經(jīng)是對數(shù)據(jù)庫連接提供了非常好的支持,但對于每次連接數(shù)據(jù)庫都要寫一大堆代碼實現(xiàn),這顯然不符合一個好的程序員的習(xí)慣,而且由于每次連接數(shù)據(jù)庫都是比較耗費(fèi)資源的,所以為了對代碼的重用和對系統(tǒng)性能的提高,對JDBC數(shù)據(jù)庫的連接進(jìn)行封裝,是在所難免的,下面是封裝的數(shù)據(jù)庫,有不足的請指出改正,謝謝交流!
DataPage
涉及的是從數(shù)據(jù)庫獲取分頁數(shù)據(jù)庫時,所包含的信息,包括當(dāng)前頁碼、每頁記錄數(shù)、總頁數(shù)、總記錄數(shù)、當(dāng)前頁數(shù)據(jù)等
package com.nlte.common.utils;
import java.sql.ResultSet;
import java.util.List;
/**
* Created by hp on 2016/11/11.
*/
public class DataPage {
private int curPage = 0;//當(dāng)前頁碼
private int pageSizes = 20;//每頁記錄數(shù)
private int pages;//總頁數(shù)
private int totalRows; //總記錄數(shù)
private ResultSet data;//當(dāng)前頁數(shù)據(jù)
public int getTotalRows() {
return totalRows;
}
public void setTotalRows(int totalRows) {
this.totalRows = totalRows;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public int getPageSizes() {
return pageSizes;
}
public void setPageSizes(int pageSizes) {
this.pageSizes = pageSizes;
}
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public ResultSet getData() {
return data;
}
public void setData(ResultSet data) {
this.data = data;
}
}
DaoException
自定義異常,方便對所遇到異常的描述
package com.nlte.common.exception;
/**
* Created by hp on 2016/11/11.
*/
public class DaoException extends Exception {
public DaoException() {
super();
}
public DaoException(String msg) {
super(msg);
}
public DaoException(Throwable arg) {
super(arg);
}
}
DBUtil
封裝類,把對數(shù)據(jù)的操作進(jìn)行封裝,方便操作
package com.nlte.common.utils;
import com.nlte.common.exception.DaoException;
import oracle.jdbc.OracleTypes;
import java.sql.*;
/**
* 對Oracle數(shù)據(jù)庫連接的封裝工具類
* Created by hp on 2016/11/11.
*/
public class DBUtil {
//Oracle驅(qū)動包
private static final String driver = "oracle.jdbc.driver.OracleDriver";
//連接Oracle數(shù)據(jù)庫的URL
// TODO: 2016/11/11 對于數(shù)據(jù)庫URL、用戶名、密碼可以動態(tài)輸入
private static String url = "jdbc:oracle:thin:localhost:1521:orcl";
//數(shù)據(jù)庫用戶名
private static String username = "scott";
//數(shù)據(jù)庫密碼
private static String pwd = "tiger";
//連接對象
private static Connection conn;
//參數(shù)語句對象
private static PreparedStatement ps;
/**
* 獲取連接對象
*
* @return 連接對象
* @throws DaoException 創(chuàng)建對象時拋出的異常
*/
public static Connection getConnection() throws DaoException {
try {
//加載驅(qū)動Oracle的jdbc驅(qū)動包
Class.forName(driver);
//建立連接 :制定連接到哪里去jdbc:oracle:thin: ip地址 : 端口號 : 服務(wù)
conn = DriverManager.getConnection(url, username, pwd);
if (conn != null) {
System.out.println("連接成功");
}
} catch (ClassNotFoundException e) {
throw new DaoException("驅(qū)動加載失敗,請檢查驅(qū)動包");
} catch (SQLException e) {
throw new DaoException("連接數(shù)據(jù)庫服務(wù)器失敗,請檢查網(wǎng)絡(luò)或相關(guān)參數(shù)");
}
return conn;
}
/**
* 只關(guān)閉連接
*/
public static void close() {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 關(guān)閉傳入的連接
*
* @param conn 連接對象
*/
public static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 關(guān)閉指定的連接和參數(shù)語句對象
*
* @param conn 連接對象
* @param ps 參數(shù)語句對象
*/
public static void close(Connection conn, PreparedStatement ps) {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 關(guān)閉連接和參數(shù)語句對象及結(jié)果集
*
* @param conn 連接對象
* @param ps 參數(shù)語句對象
* @param resultSet 結(jié)果集
*/
public static void close(Connection conn, PreparedStatement ps, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 關(guān)閉最近獲得的連接和參數(shù)語句對象
*
* @param ps 參數(shù)語句對象
*/
public static void close(PreparedStatement ps) {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 關(guān)閉最近獲得的連接和參數(shù)語句對象及結(jié)果集
*
* @param ps 參數(shù)語句對象
* @param resultSet 結(jié)果集
*/
public static void close(PreparedStatement ps, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 關(guān)閉最近獲得的連接和最近參數(shù)語句對象及結(jié)果集
*
* @param resultSet 結(jié)果集
*/
public static void close(ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 關(guān)閉最近獲取的連接和CallableStatement和結(jié)果集
* @param prepareCall
* @param resultSet 結(jié)果集
*/
public static void Close(CallableStatement prepareCall,ResultSet resultSet){
try {
if (resultSet != null) {
resultSet.close();
}
if (prepareCall != null) {
prepareCall.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 支持參數(shù)查詢并返回結(jié)果集
*
* @param sql sql語句
* @param objects 動態(tài)參數(shù)列表
* @return 結(jié)果集
* @throws DaoException 創(chuàng)建SQL語句對象拋出的異常
*/
// TODO: 2016/11/11 可以將sql語句拆分,通過輸入?yún)?shù)合成SQL語句
public static ResultSet search(String sql, Object... objects) throws DaoException {
Connection conn = getConnection();
ResultSet resultSet;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
ps.setObject(i + 1, objects[i]);
}
resultSet = ps.executeQuery();
} catch (SQLException e) {
throw new DaoException("創(chuàng)建SQL語句對象失敗");
}
return resultSet;
}
/**
* 支持參數(shù)查詢并返回一個對象
* 類似select count(*) from emp;
*
* @param sql sql語句
* @param objects 動態(tài)參數(shù)列表
* @return 查詢到的對象
* @throws DaoException 創(chuàng)建SQL語句對象拋出的異常
*/
public static Object searchObjects(String sql, Object... objects) throws DaoException {
Connection conn = getConnection();
ResultSet resultSet;
Object object = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
ps.setObject(i + 1, objects[i]);
}
resultSet = ps.executeQuery();
resultSet.next();
object = resultSet.getObject(1);
close(ps, resultSet);
} catch (SQLException e) {
throw new DaoException("創(chuàng)建SQL語句對象失敗");
}
return object;
}
/**
* 執(zhí)行插入、刪除、修改等更新數(shù)據(jù)庫的操作
*
* @param sql SQL語句
* @param objects 參數(shù)化對象
* @return 影響的行數(shù)
* @throws DaoException 創(chuàng)建SQL語句對象拋出的異常
*/
// TODO: 2016/11/11 可以將增、刪、改等操作分開成獨立的方法,并將sql語句拆分,通過輸入?yún)?shù)合成SQL語句
public static int update(String sql, Object... objects) throws DaoException {
conn = DBUtil.getConnection();
int rows;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
ps.setObject(i + 1, objects[i]);
}
rows = ps.executeUpdate();
close(ps);
} catch (SQLException e) {
throw new DaoException("創(chuàng)建SQL語句對象失敗");
}
return rows;
}
/**
* 開啟事務(wù)(多用于批量數(shù)據(jù))
*
* @param conn 連接對象
* @throws DaoException 開啟食物出錯拋出的異常
*/
public static void beginTransction(Connection conn) throws DaoException {
try {
conn.setAutoCommit(false);//關(guān)閉事務(wù)自動提交機(jī)制
} catch (SQLException e) {
throw new DaoException("開啟食物出錯");
}
}
/**
* 提交事務(wù)
*
* @param conn 連接對象
* @throws DaoException 提交食物出錯拋出的異常
*/
public static void commit(Connection conn) throws DaoException {
try {
conn.commit();
conn.setAutoCommit(true);//恢復(fù)事務(wù)自動提交機(jī)制
} catch (SQLException e) {
throw new DaoException("事務(wù)提交失敗");
}
}
/**
* 回滾事務(wù)
*
* @param conn 連接對象
* @throws DaoException 回滾食物出錯拋出的異常
*/
public static void rollback(Connection conn) throws DaoException {
try {
conn.rollback();
conn.setAutoCommit(true);
} catch (SQLException e) {
throw new DaoException("回滾事務(wù)失敗");
}
}
/**
* @param tableName 表名,或子查詢
* @param fields 字段列表
* @param strWhere 條件表達(dá)式
* @param curPage 每頁的記錄數(shù)
* @param pageSizes 當(dāng)前頁頁碼
* @return 數(shù)據(jù)頁對象
* @throws DaoException 調(diào)用分頁過程出錯拋出的異常
*/
public static DataPage getPage(String tableName,
String fields,
String strWhere,
String orderFiled,
int curPage,
int pageSizes) throws DaoException {
DataPage dataPage = null;
Connection conn = getConnection();
String sql = "call Pagination(" +
"?," +//1、表名,或子查詢
"?," +//2、字段列表
"?," +//3、條件表達(dá)式
"?," +//4、排序表達(dá)式
"?," +//5、當(dāng)前頁頁碼
"?," +//6、每頁的記錄數(shù)
"?," +//7、總記錄數(shù) -- 輸出參數(shù)
"?," +//8、總頁數(shù),或頁數(shù)(存儲過程計算出來)-- 輸出參數(shù)
"?)";// 9、當(dāng)前頁的數(shù)據(jù) --輸出參數(shù)
try {
//創(chuàng)建存儲過程
CallableStatement prepareCall = conn.prepareCall(sql);
int i = 1;
//給存儲過程的參數(shù)設(shè)置值
prepareCall.setString(i++, tableName);
prepareCall.setString(i++, fields);
prepareCall.setString(i++, strWhere);
prepareCall.setString(i++, orderFiled);
prepareCall.setInt(i++, curPage);
prepareCall.setInt(i++, pageSizes);
//注冊輸出參數(shù)
/*All OUT parameters must be registered before a stored procedure is executed.*/
prepareCall.registerOutParameter(i++, Types.INTEGER);//總記錄數(shù)
prepareCall.registerOutParameter(i++, Types.INTEGER);//總頁數(shù)
prepareCall.registerOutParameter(i++, OracleTypes.CURSOR);////當(dāng)前頁的數(shù)據(jù)
prepareCall.execute();//執(zhí)行存儲過程
dataPage = new DataPage();
//執(zhí)行完后,獲取輸出參數(shù)
//獲取總記錄數(shù)
int totalRows = prepareCall.getInt(7);
dataPage.setTotalRows(totalRows);
//獲取總頁數(shù)
int pages = prepareCall.getInt(8);
dataPage.setPages(pages);
//獲取當(dāng)前頁的數(shù)據(jù)
ResultSet resultSet = (ResultSet) prepareCall.getObject(9);
dataPage.setData(resultSet);
//close(prepareCall, resultSet);
} catch (SQLException e) {
throw new DaoException("調(diào)用分頁過程出錯");
}
return dataPage;
}
}
存儲過程
分頁存儲過程
CREATE OR REPLACE PROCEDURE Pagination
(tableName varchar2, --表名
fileds varchar2, --查詢字段
strWhere varchar2, --查詢條件
orderFiled varchar2, --排序的字段
curPage Number, --當(dāng)前頁
sizes Number, --每頁顯示記錄條數(shù)
totalRows out Number, --總記錄數(shù)
pages out Number, --總頁數(shù)
cur_out out sys_refcursor -- 系統(tǒng)預(yù)定義的游標(biāo)類型
)
--優(yōu)點一:sys_refcursor,可以在存儲過程中作為參數(shù)返回一個table格式的結(jié)構(gòu)集
--(我把他認(rèn)為是table類型,容易理解,其實是一個游標(biāo)集), cursor 只能用在存
--儲過程,函數(shù),包等的實現(xiàn)體中,不能做參數(shù)使用。
--優(yōu)點二:sys_refcursor 這東西可以使用在包中做參數(shù),進(jìn)行數(shù)據(jù)庫面向?qū)ο箝_放。
--sys_refcursor 不能用open,close ,fetch 進(jìn)行操作
--支持多表連接查詢,
--多表舉例:
--tableName= "t1,t2"
--strWhere="t1.id=t2.id"
IS
v_sql VARCHAR2(1000) := ''; --sql語句
v_startRecord Number(4); --開始顯示的記錄條數(shù)
v_endRecord Number(4); --結(jié)束顯示的記錄條數(shù)
v_fileds VARCHAR2(1000) := fileds;
BEGIN
--記錄中總記錄條數(shù)
v_sql := 'SELECT TO_NUMBER(COUNT(*)) FROM ' || tableName ;
IF strWhere IS NOT NULL or strWhere <> '' THEN
v_sql := v_sql || ' WHERE ' || strWhere;
END IF;
EXECUTE IMMEDIATE v_sql INTO totalRows; -- EXECUTE IMMEDIATE立即執(zhí)行
--根據(jù)頁大小計算總頁數(shù)
IF MOD(totalRows,sizes) = 0 THEN
pages := totalRows / sizes;
ELSE
pages := totalRows / sizes + 1;
END IF;
--實現(xiàn)分頁查詢
v_startRecord := (curPage - 1) * sizes + 1;
v_endRecord := curPage * sizes;
--處理所有列情況
if fileds='*' then
v_fileds:=tableName||'.'||fileds;
end if;
--生成基本sql
v_sql := 'SELECT '|| v_fileds || ',rownum rn FROM ' || tableName ;
IF strWhere IS NOT NULL or strWhere <> '' THEN
v_sql := v_sql || ' WHERE '||strWhere;
END IF;
v_sql :='select * from ('|| v_sql ||') ';
--指定記錄集
v_sql :=v_sql || ' where rn <= ' || v_endRecord || 'and rn >= ' || v_startRecord;
IF orderFiled IS NOT NULL or orderFiled <> '' THEN
v_sql := v_sql || ' ORDER BY ' || orderFiled;
END IF;
--DBMS_OUTPUT.put_line(v_sql);
open cur_out for v_sql ;--用v_sql創(chuàng)建的游標(biāo)賦值給cur_out游標(biāo)
END Pagination;
/