日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

jdbc mysql分页_JDBC【数据库连接池、DbUtils框架、分页】

發布時間:2025/3/8 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jdbc mysql分页_JDBC【数据库连接池、DbUtils框架、分页】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.數據庫連接池

什么是數據庫連接池

簡單來說:數據庫連接池就是提供連接的。。。

為什么我們要使用數據庫連接池

數據庫的連接的建立和關閉是非常消耗資源的

頻繁地打開、關閉連接造成系統性能低下

編寫連接池

編寫連接池需實現java.sql.DataSource接口

創建批量的Connection用LinkedList保存【既然是個池,當然用集合保存、、LinkedList底層是鏈表,對增刪性能較好】

實現getConnetion(),讓getConnection()每次調用,都是在LinkedList中取一個Connection返回給用戶

調用Connection.close()方法,Connction返回給LinkedList

private static LinkedList list = new LinkedList<>();

//獲取連接只需要一次就夠了,所以用static代碼塊

static {

//讀取文件配置

InputStream inputStream = Demo1.class.getClassLoader().getResourceAsStream("db.properties");

Properties properties = new Properties();

try {

properties.load(inputStream);

String url = properties.getProperty("url");

String username = properties.getProperty("username");

String driver = properties.getProperty("driver");

String password = properties.getProperty("password");

//加載驅動

Class.forName(driver);

//獲取多個連接,保存在LinkedList集合中

for (int i = 0; i < 10; i++) {

Connection connection = DriverManager.getConnection(url, username, password);

list.add(connection);

}

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

//重寫Connection方法,用戶獲取連接應該從LinkedList中給他

@Override

public Connection getConnection() throws SQLException {

System.out.println(list.size());

System.out.println(list);

//先判斷LinkedList是否存在連接

return list.size() > 0 ? list.removeFirst() : null;

}

我們已經完成前三步了,現在問題來了。我們調用Conncetion.close()方法,是把數據庫的物理連接關掉,而不是返回給LinkedList的

解決思路:

寫一個Connection子類,覆蓋close()方法

寫一個Connection包裝類,增強close()方法

用動態代理,返回一個代理對象出去,攔截close()方法的調用,對close()增強

分析第一個思路:

Connection是通過數據庫驅動加載的,保存了數據的信息。寫一個子類Connection,new出對象,子類的Connction無法直接繼承父類的數據信息,也就是說子類的Connection是無法連接數據庫的,更別談覆蓋close()方法了。

分析第二個思路:

寫一個Connection包裝類。

寫一個類,實現與被增強對象的相同接口【Connection接口】

定義一個變量,指向被增強的對象

定義構造方法,接收被增強對象

覆蓋想增強的方法

對于不想增強的方法,直接調用被增強對象的方法

這個思路本身是沒什么毛病的,就是實現接口時,方法太多了!,所以我們也不使用此方法

分析第三個思路代碼實現:

@Override

public Connection getConnection() throws SQLException {

if (list.size() > 0) {

final Connection connection = list.removeFirst();

//看看池的大小

System.out.println(list.size());

//返回一個動態代理對象

return (Connection) Proxy.newProxyInstance(Demo1.class.getClassLoader(), connection.getClass().getInterfaces(), new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//如果不是調用close方法,就按照正常的來調用

if (!method.getName().equals("close")) {

return method.invoke(connection, args);

} else {

//進到這里來,說明調用的是close方法

list.add(connection);

//再看看池的大小

System.out.println(list.size());

}

return null;

}

});

}

return null;

}

我們上面已經能夠簡單編寫一個線程池了。下面我們來使用一下開源數據庫連接池

DBCP

使用DBCP數據源的步驟:

導入兩個jar包【Commons-dbcp.jar和Commons-pool.jar】

讀取配置文件

獲取BasicDataSourceFactory對象

創建DataSource對象

private static DataSource dataSource = null;

static {

try {

//讀取配置文件

InputStream inputStream = Demo3.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

Properties properties = new Properties();

properties.load(inputStream);

//獲取工廠對象

BasicDataSourceFactory basicDataSourceFactory = new BasicDataSourceFactory();

dataSource = basicDataSourceFactory.createDataSource(properties);

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

}

public static Connection getConnection() throws SQLException {

return dataSource.getConnection();

}

//這里釋放資源不是把數據庫的物理連接釋放了,是把連接歸還給連接池【連接池的Connection內部自己做好了】

public static void release(Connection conn, Statement st, ResultSet rs) {

if (rs != null) {

try {

rs.close();

} catch (Exception e) {

e.printStackTrace();

}

rs = null;

}

if (st != null) {

try {

st.close();

} catch (Exception e) {

e.printStackTrace();

}

}

if (conn != null) {

try {

conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

C3P0

C3P0數據源的性能更勝一籌,并且它可以使用XML配置文件配置信息!

步驟:

導入開發包【c3p0-0.9.2-pre1.jar】和【mchange-commons-0.2.jar】

導入XML配置文件【可以在程序中自己一個一個配,C3P0的doc中的Configuration有XML文件的事例】

new出ComboPooledDataSource對象

private static ComboPooledDataSource comboPooledDataSource = null;

static {

//如果我什么都不指定,就是使用XML默認的配置,這里我指定的是oracle的

comboPooledDataSource = new ComboPooledDataSource("oracle");

}

public static Connection getConnection() throws SQLException {

return comboPooledDataSource.getConnection();

}

Tomcat數據源

Tomcat服務器也給我們提供了連接池,內部其實就是DBCP

步驟:

在META-INF目錄下配置context.xml文件【文件內容可以在tomcat默認頁面的 JNDI Resources下Configure Tomcat's Resource Factory找到】

導入Mysql或oracle開發包到tomcat的lib目錄下

初始化JNDI->獲取JNDI容器->檢索以XXX為名字在JNDI容器存放的連接池

context.xml文件的配置:

auth="Container"

type="javax.sql.DataSource"

username="root"

password="root"

driverClassName="com.mysql.jdbc.Driver"

url="jdbc:mysql://localhost:3306/zhongfucheng"

maxActive="8"

maxIdle="4"/>

try {

//初始化JNDI容器

Context initCtx = new InitialContext();

//獲取到JNDI容器

Context envCtx = (Context) initCtx.lookup("java:comp/env");

//掃描以jdbc/EmployeeDB名字綁定在JNDI容器下的連接池

DataSource ds = (DataSource)

envCtx.lookup("jdbc/EmployeeDB");

Connection conn = ds.getConnection();

System.out.println(conn);

}

使用dbutils框架

dbutils它是對JDBC的簡單封裝,極大簡化jdbc編碼的工作量

DbUtils類

提供了關閉連接,裝載JDBC驅動,回滾提交事務等方法的工具類【比較少使用,因為我們學了連接池,就應該使用連接池連接數據庫】

QueryRunner類

該類簡化了SQL查詢,配合ResultSetHandler使用,可以完成大部分的數據庫操作,重載了許多的查詢,更新,批處理方法。大大減少了代碼量

ResultSetHandler接口

該接口規范了對ResultSet的操作,要對結果集進行什么操作,傳入ResultSetHandler接口的實現類即可。

ArrayHandler:把結果集中的第一行數據轉成對象數組。

ArrayListHandler:把結果集中的每一行數據都轉成一個數組,再存放到List中。

BeanHandler:將結果集中的第一行數據封裝到一個對應的JavaBean實例中。

BeanListHandler:將結果集中的每一行數據都封裝到一個對應的JavaBean實例中,存放到List里。

ColumnListHandler:將結果集中某一列的數據存放到List中。

KeyedHandler(name):將結果集中的每一行數據都封裝到一個Map里,再把這些map再存到一個map里,其key為指定的key。

MapHandler:將結果集中的第一行數據封裝到一個Map里,key是列名,value就是對應的值。

MapListHandler:將結果集中的每一行數據都封裝到一個Map里,然后再存放到List

ScalarHandler 將ResultSet的一個列到一個對象中。

使用DbUtils框架對數據庫的CRUD

/*

* 使用DbUtils框架對數據庫的CRUD

* 批處理

*

* */

public class Test {

@org.junit.Test

public void add() throws SQLException {

//創建出QueryRunner對象

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "INSERT INTO student (id,name) VALUES(?,?)";

//我們發現query()方法有的需要傳入Connection對象,有的不需要傳入

//區別:你傳入Connection對象是需要你來銷毀該Connection,你不傳入,由程序幫你把Connection放回到連接池中

queryRunner.update(sql, new Object[]{"100", "zhongfucheng"});

}

@org.junit.Test

public void query()throws SQLException {

//創建出QueryRunner對象

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "SELECT * FROM student";

List list = (List) queryRunner.query(sql, new BeanListHandler(Student.class));

System.out.println(list.size());

}

@org.junit.Test

public void delete() throws SQLException {

//創建出QueryRunner對象

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "DELETE FROM student WHERE id='100'";

queryRunner.update(sql);

}

@org.junit.Test

public void update() throws SQLException {

//創建出QueryRunner對象

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "UPDATE student SET name=? WHERE id=?";

queryRunner.update(sql, new Object[]{"zhongfuchengaaa", 1});

}

@org.junit.Test

public void batch() throws SQLException {

//創建出QueryRunner對象

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "INSERT INTO student (name,id) VALUES(?,?)";

Object[][] objects = new Object[10][];

for (int i = 0; i < 10; i++) {

objects[i] = new Object[]{"aaa", i + 300};

}

queryRunner.batch(sql, objects);

}

}

分頁

分頁技術是非常常見的,在搜索引擎下搜索頁面,不可能把全部數據都顯示在一個頁面里邊。所以我們用到了分頁技術。

Oracle實現分頁

/*

Oracle分頁語法:

@lineSize---每頁顯示數據行數

@currentPage----當前所在頁

*/

SELECT *FROM (

SELECT 列名,列名,ROWNUM rn

FROM 表名

WHERE ROWNUM<=(currentPage*lineSize)) temp

WHERE temp.rn>(currentPage-1)*lineSize;

Oracle分頁原理簡單解釋:

/*

Oracle分頁:

Oracle的分頁依賴于ROWNUM這個偽列,ROWNUM主要作用就是產生行號。

分頁原理:

1:子查詢查出前n行數據,ROWNUM產生前N行的行號

2:使用子查詢產生ROWNUM的行號,通過外部的篩選出想要的數據

例子:

我現在規定每頁顯示5行數據【lineSize=5】,我要查詢第2頁的數據【currentPage=2】

注:【對照著語法來看】

實現:

1:子查詢查出前10條數據【ROWNUM<=10】

2:外部篩選出后面5條數據【ROWNUM>5】

3:這樣我們就取到了后面5條的數據

*/

Mysql實現分頁

/*

Mysql分頁語法:

@start---偏移量,不設置就是從0開始【也就是(currentPage-1)*lineSize】

@length---長度,取多少行數據

*/

SELECT *

FROM 表名

LIMIT [START], length;

/*

例子:

我現在規定每頁顯示5行數據,我要查詢第2頁的數據

分析:

1:第2頁的數據其實就是從第6條數據開始,取5條

實現:

1:start為5【偏移量從0開始】

2:length為5

*/

總結:

Mysql從(currentPage-1)*lineSize開始取數據,取lineSize條數據

Oracle先獲取currentPagelineSize條數據,從(currentPage-1)lineSize開始取數據

使用JDBC連接數據庫實現分頁

下面是常見的分頁圖片

配合圖片,看下我們的需求是什么:

算出有多少頁的數據,顯示在頁面上

根據頁碼,從數據庫顯示相對應的數據。

分析:

算出有多少頁數據這是非常簡單的【在數據庫中查詢有多少條記錄,你每頁顯示多少條記錄,就可以算出有多少頁數據了】

使用Mysql或Oracle的分頁語法即可

通過上面分析,我們會發現需要用到4個變量

currentPage--當前頁【由用戶決定的】

totalRecord--總數據數【查詢表可知】

lineSize--每頁顯示數據的數量【由我們開發人員決定】

pageCount--頁數【totalRecord和lineSize決定】

//每頁顯示3條數據

int lineSize = 3;

//總記錄數

int totalRecord = getTotalRecord();

//假設用戶指定的是第2頁

int currentPage = 2;

//一共有多少頁

int pageCount = getPageCount(totalRecord, lineSize);

//使用什么數據庫進行分頁,記得要在JdbcUtils中改配置

List list = getPageData2(currentPage, lineSize);

for (Person person : list) {

System.out.println(person);

}

}

//使用JDBC連接Mysql數據庫實現分頁

public static List getPageData(int currentPage, int lineSize) throws SQLException {

//從哪個位置開始取數據

int start = (currentPage - 1) * lineSize;

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "SELECT name,address FROM person LIMIT ?,?";

List persons = (List) queryRunner.query(sql, new BeanListHandler(Person.class), new Object[]{start, lineSize});

return persons;

}

//使用JDBC連接Oracle數據庫實現分頁

public static List getPageData2(int currentPage, int lineSize) throws SQLException {

//從哪個位置開始取數據

int start = (currentPage - 1) * lineSize;

//讀取前N條數據

int end = currentPage * lineSize;

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "SELECT " +

" name, " +

" address " +

"FROM ( " +

" SELECT " +

" name, " +

" address , " +

" ROWNUM rn " +

" FROM person " +

" WHERE ROWNUM <= ? " +

")temp WHERE temp.rn>?";

List persons = (List) queryRunner.query(sql, new BeanListHandler(Person.class), new Object[]{end, start});

return persons;

}

public static int getPageCount(int totalRecord, int lineSize) {

//簡單算法

//return (totalRecord - 1) / lineSize + 1;

//此算法比較好理解,把數據代代進去就知道了。

return totalRecord % lineSize == 0 ? (totalRecord / lineSize) : (totalRecord / lineSize) + 1;

}

public static int getTotalRecord() throws SQLException {

//使用DbUtils框架查詢數據庫表中有多少條數據

QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());

String sql = "SELECT COUNT(*) FROM person";

Object o = queryRunner.query(sql, new ScalarHandler());

String ss = o.toString();

int s = Integer.parseInt(ss);

return s;

}

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章的同學,可以關注微信公眾號:Java3y。

總結

以上是生活随笔為你收集整理的jdbc mysql分页_JDBC【数据库连接池、DbUtils框架、分页】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。