JDBC-02
jdbc
前言
在jdbc-01当中,我们简单地学习了有关jdbc的一些基本操作,现在我们再一次进行深入的学习。
正文
事务
首先,我们来学习的是jdbc中事务的运用,那么让我们再次了解一下事务的概念。
事务的概念
事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全部成功,要么全部失败。
关于事务的api
commit()
rollback()
异常案例:
package com.charles.jdbc.high; import org.junit.test; import java.sql.connection; import java.sql.preparedstatement; import java.sql.sqlexception; /** * 有关事务的案例 * 转账案例 * @author charles */ public class demo01 { @test public void demo(){ connection conn = null; preparedstatement pste = null; try { // 加载驱动 + 获取连接 conn = org.charl.demo.getconnection(); // 编写sql string sql = "update account set money = money + ? where name = ?"; // 预编译 pste = conn.preparestatement(sql); // 转账过程 pste.setint(1,-1000); pste.setstring(2,"aaa"); pste.executeupdate(); pste.setint(1,1000); pste.setstring(2,"bbb"); pste.executeupdate(); // 因为这个错误,导致异常的发生 int i = 1 / 0; } catch (sqlexception e){ e.printstacktrace(); } finally { // 资源释放 org.charl.demo.release(pste,conn); } } }
修改后的案例
package com.charles.jdbc.high; import org.junit.test; import java.sql.connection; import java.sql.preparedstatement; import java.sql.sqlexception; /** * 有关事务的案例 * 转账案例 * @author charles */ public class demo01 { @test public void demo(){ connection conn = null; preparedstatement pste = null; try { // 加载驱动 + 获取连接 conn = org.charl.demo.getconnection(); // 开启事务 conn.setautocommit(false); // 编写sql string sql = "update account set money = money + ? where name = ?"; // 预编译 pste = conn.preparestatement(sql); // 转账过程 pste.setint(1,-1000); pste.setstring(2,"aaa"); pste.executeupdate(); pste.setint(1,1000); pste.setstring(2,"bbb"); pste.executeupdate(); // 因为这个错误,导致异常的发生 // int i = 1 / 0; conn.commit(); } catch (sqlexception e){ // 回滚事务 try { conn.rollback(); } catch (sqlexception ex) { ex.printstacktrace(); } e.printstacktrace(); } finally { // 资源释放 org.charl.demo.release(pste,conn); } } }
这样,数据就会进行回滚,保证了数据的安全性。
连接池
概念:连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
好处(作用):
- 减少连接创建时间
- 简化的编程模式
- 受控的资源使用
- 提高连接的效率
连接池原理:
自定义连接池:
我们可以利用datasource接口来实现一个自定义连接池
具体步骤:
-
-
重写一个getconnection方法
-
初始化多个连接在内存中
-
/** * 自定义连接池 * @author charles */ public class mydatasource implements datasource { // 在初始化的时候提供一些连接 private list<connection> connectionlist = new arraylist<connection>(); public mydatasource(){ // 初始化连接 for (int i = 1; i <= 4; i++){ // 向集合中存入连接 connectionlist.add(org.charl.demo.getconnection()); } } // 获得连接的方法 @override public connection getconnection(string username, string password) throws sqlexception { connection conn = connectionlist.remove(0); return conn; } // 归还连接的方法 public void addback(connection conn){ connectionlist.add(conn); }
代码案例:
package jdbc.datasources; import org.junit.test; import javax.management.relation.relation; import java.sql.connection; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; /** * 利用连接池的案例 */ public class demo01 { @test public void demo(){ connection conn = null; preparedstatement preparedstatement = null; resultset rs = null; mydatasource md = null; try{ // 利用自定义的连接池注册驱动 + 获得连接 md = new mydatasource(); conn = md.getconnection(); // 编写sql语句 string sql = "select * from account"; preparedstatement = conn.preparestatement(sql); rs = preparedstatement.executequery(); // 遍历结果 while (rs.next()){ system.out.println(rs.getint("id") + " " + rs.getstring("name") + " " + rs.getstring("money")); } }catch (exception e){ e.printstacktrace(); }finally { // 释放资源 if (preparedstatement != null){ try{ preparedstatement.close(); } catch (sqlexception e){ e.printstacktrace(); } preparedstatement = null; } if (rs != null){ try { rs.close(); }catch (sqlexception e){ e.printstacktrace(); } rs = null; } // 归还连接 md.addback(conn); } } }
druid 是阿里旗下的开源连接池产品,使用非常简单,可以与spring 框架进行快速整合。
maven导包
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupid>com.alibaba</groupid> <artifactid>druid</artifactid> <version>1.1.21</version> </dependency>
基本代码实现
package com.charles.datasource.demo1; import com.alibaba.druid.pool.druiddatasource; import org.junit.test; import java.sql.connection; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; public class druiddemo1 { @test public void demo01(){ connection connection = null; preparedstatement preparedstatement = null; resultset resultset = null; try { // 使用连接池 druiddatasource druiddatasource = new druiddatasource(); druiddatasource.setdriverclassname("com.mysql.jdbc.driver"); druiddatasource.seturl("jdbc:mysql:///web_test3"); druiddatasource.setusername("root"); druiddatasource.setpassword("1234"); // 获得连接 connection = druiddatasource.getconnection(); // 编写sql string sql = "select * from user"; // 预编译sql preparedstatement = connection.preparestatement(sql); resultset = preparedstatement.executequery(); while (resultset.next()){ system.out.println(resultset.getint("id") + " " + resultset.getstring("username") + " " + resultset.getstring("password")); } } catch (sqlexception e) { e.printstacktrace(); } finally { try { connection.close(); } catch (sqlexception e) { e.printstacktrace(); } try { resultset.close(); } catch (sqlexception e) { e.printstacktrace(); } try { preparedstatement.close(); } catch (sqlexception e) { e.printstacktrace(); } } } }
当然也可以将这些数据库信息向外面引入,即创建一个db.properties
代码实现:
单元测试类
@test public void demo02(){ connection connection = null; preparedstatement preparedstatement = null; resultset resultset = null; try { // 使用连接池 properties properties = new properties(); properties.load(new fileinputstream("src/main/resources/db.properties")); datasource datasource = druiddatasourcefactory.createdatasource(properties); // 获得连接 connection = datasource.getconnection(); // 编写sql string sql = "select * from user"; // 预编译sql preparedstatement = connection.preparestatement(sql); resultset = preparedstatement.executequery(); while (resultset.next()){ system.out.println(resultset.getint("id") + " " + resultset.getstring("username") + " " + resultset.getstring("password")); } } catch (sqlexception | filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } catch (exception e) { e.printstacktrace(); } finally { try { connection.close(); } catch (sqlexception e) { e.printstacktrace(); } try { resultset.close(); } catch (sqlexception e) { e.printstacktrace(); } try { preparedstatement.close(); } catch (sqlexception e) { e.printstacktrace(); } } }
db.properties
# 连接设置 driverclassname=com.mysql.jdbc.driver url=jdbc:mysql:///web_test3 username=root password=1234 # 初始化连接 initialsize=10 # 最大连接数量 maxactive=50 # 最大空闲连接 maxidle=20 # 最小空闲连接 minidle=5 # 超时等待时间(以毫秒为单位) maxwait=60000
c3p0连接池
c3p0是一个开源的jdbc连接池,它实现了数据源和jndi绑定,支持jdbc3规范和jdbc2的标准扩展。
使用方法与druid相类似
maven导包
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> <dependency> <groupid>com.mchange</groupid> <artifactid>c3p0</artifactid> <version>0.9.5.2</version> </dependency>
基本代码实现
package com.charles.datasource.demo1; import com.mchange.v2.c3p0.combopooleddatasource; import org.junit.test; import java.beans.propertyvetoexception; import java.sql.connection; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; public class c3p0 { @test public void demo01() { connection connection = null; preparedstatement preparedstatement = null; resultset resultset = null; try { // 使用连接池 combopooleddatasource datasource = new combopooleddatasource(); datasource.setdriverclass("com.mysql.jdbc.driver"); datasource.setjdbcurl("jdbc:mysql:///web_test3"); datasource.setuser("root"); datasource.setpassword("1234"); // 获得连接 connection = datasource.getconnection(); // 编写sql string sql = "select * from user"; // 预编译sql preparedstatement = connection.preparestatement(sql); resultset = preparedstatement.executequery(); while (resultset.next()) { system.out.println(resultset.getint("id") + " " + resultset.getstring("username") + " " + resultset.getstring("password")); } } catch (sqlexception e) { e.printstacktrace(); } catch (propertyvetoexception e) { e.printstacktrace(); } finally { try { connection.close(); } catch (sqlexception e) { e.printstacktrace(); } try { resultset.close(); } catch (sqlexception e) { e.printstacktrace(); } try { preparedstatement.close(); } catch (sqlexception e) { e.printstacktrace(); } } } }
当然,c3p0连接池也可以通过外部配置文件引用
具体代码实现:
c3p0-config.xml配置文件
<?xml version="1.0" encoding="utf-8"?> <c3p0-config> <default-config> <property name="driverclass">com.mysql.jdbc.driver</property> <property name="jdbcurl">jdbc:mysql:///web_test3</property> <property name="user">root</property> <property name="password">1234</property> <property name="initialpoolsize">5</property> <property name="maxpoolsize">20</property> <property name="minpoolsize">5</property> </default-config> </c3p0-config>
单元测试类
@test public void demo02(){ connection connection = null; preparedstatement preparedstatement = null; resultset resultset = null; try { // 使用连接池 combopooleddatasource datasource = new combopooleddatasource(); datasource.setdriverclass("com.mysql.jdbc.driver"); datasource.setjdbcurl("jdbc:mysql:///web_test3"); datasource.setuser("root"); datasource.setpassword("1234"); // 获得连接 connection = datasource.getconnection(); // 编写sql string sql = "select * from user"; // 预编译sql preparedstatement = connection.preparestatement(sql); resultset = preparedstatement.executequery(); while (resultset.next()) { system.out.println(resultset.getint("id") + " " + resultset.getstring("username") + " " + resultset.getstring("password")); } } catch (sqlexception e) { e.printstacktrace(); } catch (propertyvetoexception e) { e.printstacktrace(); } finally { try { connection.close(); } catch (sqlexception e) { e.printstacktrace(); } try { resultset.close(); } catch (sqlexception e) { e.printstacktrace(); } try { preparedstatement.close(); } catch (sqlexception e) { e.printstacktrace(); } } }
这里注意,只要将配置文件放在默认路径下,它就会自动查找,不需要手动导入。
commons dbutils一个对jdbc进行简单封装的工具类库,它能够简化jdbc应用程序的开发,同时也不会影响程序的性能。
两个字:方便 -----> 一个字:懒
arrayhandler 和 arraylisthandler:
小结
以上便是jdbc的内容了,多练,练到烦了就会了。当然为了更偷懒,我们后期将会学到mybatis,这个框架比jdbc更方便。
加油!
时间:2020-04-06 01:41:37