java程序员从笨鸟到菜鸟之(七)一—java数据库操作

本文来自:曹胜欢博客专栏。转载请注明出处: http://blog.csdn.net/csh624366188

数据库访问几乎每一个稍微成型的程序都要用到的知识,怎么高效的访问数据库也是我们学习的一个重点,今天的任务就是总结java访问数据库的方法和有关APIjava访问数据库主要用的方法是JDBC,是java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法,下面我们就具体来总结一下JDBC

一:Java访问数据库的具体步骤:

1 加载(注册)数据库

 驱动加载就是把各个数据库提供的访问数据库的API加载到我们程序进来,加载JDBC驱动,并将其注册到DriverManager中,每一种数据库提供的数据库驱动不一样,加载驱动时要把jar包添加到lib文件夹下,下面看一下一些主流数据库的JDBC驱动加裁注册的代码:

//Oracle8/8i/9iO数据库(thin模式)

Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();

//Sql Server7.0/2000数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

//Sql Server2005/2008数据库 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

//DB2数据库

Class.froName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();

//MySQL数据库 Class.forName("com.mysql.jdbc.Driver").newInstance();

2 建立链接   

建立数据库之间的连接是访问数据库的必要条件,就像南水北调调水一样,要想调水首先由把沟通的河流打通。建立连接对于不同数据库也是不一样的,下面看一下一些主流数据库建立数据库连接,取得Connection对象的不同方式:

//Oracle8/8i/9i数据库(thin模式)

String url="jdbc:oracle:thin:@localhost:1521:orcl";

String user="scott";

String password="tiger";

Connection conn=DriverManager.getConnection(url,user,password);

//Sql Server7.0/2000/2005/2008数据库

String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs";

String user="sa";

String password="";

Connection conn=DriverManager.getConnection(url,user,password);

//DB2数据库

String url="jdbc:db2://localhost:5000/sample";

String user="amdin"

String password=-"";

Connection conn=DriverManager.getConnection(url,user,password);

//MySQL数据库

String url="jdbc:mysql://localhost:3306/testDB?user=root&password=root&useUnicode=true&characterEncoding=gb2312";

Connection conn=DriverManager.getConnection(url);

3. 执行SQL语句  

数据库连接建立好之后,接下来就是一些准备工作和执行sql语句了,准备工作要做的就是建立Statement对象PreparedStatement对象,例如:

//建立Statement对象

Statement stmt=conn.createStatement();

//建立PreparedStatement对象

String sql="select * from user where userName=? and password=?";

PreparedStatement pstmt=Conn.prepareStatement(sql);

pstmt.setString(1,"admin");

pstmt.setString(2,"liubin");

做好准备工作之后就可以执行sql语句了,执行sql语句:

String sql="select * from users";

ResultSet rs=stmt.executeQuery(sql);

//执行动态SQL查询

ResultSet rs=pstmt.executeQuery();

//执行insert update delete等语句,先定义sql

stmt.executeUpdate(sql);

4 处理结果集  

 访问结果记录集ResultSet对象。例如:

while(rs.next)

{

out.println("你的第一个字段内容为:"+rs.getString("Name"));

out.println("你的第二个字段内容为:"+rs.getString(2));

}

5 关闭数据库

依次将ResultSetStatementPreparedStatementConnection对象关 闭,释放所占用的资源.例如:

rs.close();

stmt.clost();

pstmt.close();

con.close();

二:JDBC事务

什么是事务:

首先,说说什么事务。我认为事务,就是一组操作数据库的动作集合。

事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操 作一样被完整地执行,我们称该事务被提交。由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。

事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性 (isolation)和持久性(durability)的缩写。事务的原子性表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。一致性表示 当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态。隔离性表示在事务执行过程中对数据的修改,在事务提交之前对其他事务不可见。持 久性表示当系统或介质发生故障时,确保已提交事务的更新不能丢失。持久性通过数据库备份和恢复来保证。

JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:
public void setAutoCommit(boolean)
public boolean getAutoCommit()
public void commit()
public void rollback()
使用
JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。

三:java操作数据库连接池

在总结java操作数据库连接池发现一篇很好的文章,所以就不做具体总结了,直接上地址:

http://www.blogjava.net/chunkyo/archive/2007/01/16/94266.html

最后附一段比较经典的代码吧:

  1. import java.sql.Connection;
  2. import java.sql.DatabaseMetaData;
  3. import java.sql.Driver;
  4. import java.sql.DriverManager;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7. import java.util.Enumeration;
  8. import java.util.Vector;
  9. public class ConnectionPool {
  10. private String jdbcDriver = ""; // 数据库驱动
  11. private String dbUrl = ""; // 数据 URL
  12. private String dbUsername = ""; // 数据库用户名
  13. private String dbPassword = ""; // 数据库用户密码
  14. private String testTable = ""; // 测试连接是否可用的测试表名,默认没有测试表
  15. private int initialConnections = 10; // 连接池的初始大小
  16. private int incrementalConnections = 5;// 连接池自动增加的大小
  17. private int maxConnections = 50; // 连接池最大的大小
  18. private Vector connections = null; // 存放连接池中数据库连接的向量 , 初始时为 null
  19. // 它中存放的对象为 PooledConnection 型
  20. /**
  21. * 构造函数
  22. *
  23. * @param jdbcDriver String JDBC 驱动类串
  24. * @param dbUrl String 数据库 URL
  25. * @param dbUsername String 连接数据库用户名
  26. * @param dbPassword String 连接数据库用户的密码
  27. *
  28. */
  29. public ConnectionPool(String jdbcDriver,String dbUrl,String dbUsername,String dbPassword) {
  30. this.jdbcDriver = jdbcDriver;
  31. this.dbUrl = dbUrl;
  32. this.dbUsername = dbUsername;
  33. this.dbPassword = dbPassword;
  34. }
  35. /**
  36. * 返回连接池的初始大小
  37. *
  38. * @return 初始连接池中可获得的连接数量
  39. */
  40. public int getInitialConnections() {
  41. return this.initialConnections;
  42. }
  43. /**
  44. * 设置连接池的初始大小
  45. *
  46. * @param 用于设置初始连接池中连接的数量
  47. */
  48. public void setInitialConnections(int initialConnections) {
  49. this.initialConnections = initialConnections;
  50. }
  51. /**
  52. * 返回连接池自动增加的大小 、
  53. *
  54. * @return 连接池自动增加的大小
  55. */
  56. public int getIncrementalConnections() {
  57. return this.incrementalConnections;
  58. }
  59. /**
  60. * 设置连接池自动增加的大小
  61. * @param 连接池自动增加的大小
  62. */
  63. public void setIncrementalConnections(int incrementalConnections) {
  64. this.incrementalConnections = incrementalConnections;
  65. }
  66. /**
  67. * 返回连接池中最大的可用连接数量
  68. * @return 连接池中最大的可用连接数量
  69. */
  70. public int getMaxConnections() {
  71. return this.maxConnections;
  72. }
  73. /**
  74. * 设置连接池中最大可用的连接数量
  75. *
  76. * @param 设置连接池中最大可用的连接数量值
  77. */
  78. public void setMaxConnections(int maxConnections) {
  79. this.maxConnections = maxConnections;
  80. }
  81. /**
  82. * 获取测试数据库表的名字
  83. *
  84. * @return 测试数据库表的名字
  85. */
  86. public String getTestTable() {
  87. return this.testTable;
  88. }
  89. /**
  90. * 设置测试表的名字
  91. * @param testTable String 测试表的名字
  92. */
  93. public void setTestTable(String testTable) {
  94. this.testTable = testTable;
  95. }
  96. /**
  97. *
  98. * 创建一个数据库连接池,连接池中的可用连接的数量采用类成员
  99. * initialConnections 中设置的值
  100. */
  101. public synchronized void createPool() throws Exception {
  102. // 确保连接池没有创建
  103. // 如果连接池己经创建了,保存连接的向量 connections 不会为空
  104. if (connections != null) {
  105. return; // 如果己经创建,则返回
  106. }
  107. // 实例化 JDBC Driver 中指定的驱动类实例
  108. Driver driver = (Driver) (Class.forName(this.jdbcDriver).newInstance());
  109. DriverManager.registerDriver(driver); // 注册 JDBC 驱动程序
  110. // 创建保存连接的向量 , 初始时有 0 个元素
  111. connections = new Vector();
  112. // 根据 initialConnections 中设置的值,创建连接。
  113. createConnections(this.initialConnections);
  114. System.out.println(" 数据库连接池创建成功! ");
  115. }
  116. /**
  117. * 创建由 numConnections 指定数目的数据库连接 , 并把这些连接
  118. * 放入 connections 向量中
  119. *
  120. * @param numConnections 要创建的数据库连接的数目
  121. */
  122. @SuppressWarnings("unchecked")
  123. private void createConnections(int numConnections) throws SQLException {
  124. // 循环创建指定数目的数据库连接
  125. for (int x = 0; x < numConnections; x++) {
  126. // 是否连接池中的数据库连接的数量己经达到最大?最大值由类成员 maxConnections
  127. // 指出,如果 maxConnections 为 0 或负数,表示连接数量没有限制。
  128. // 如果连接数己经达到最大,即退出。
  129. if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) {
  130. break;
  131. }
  132. //add a new PooledConnection object to connections vector
  133. // 增加一个连接到连接池中(向量 connections 中)
  134. try{
  135. connections.addElement(new PooledConnection(newConnection()));
  136. }catch(SQLException e){
  137. System.out.println(" 创建数据库连接失败! "+e.getMessage());
  138. throw new SQLException();
  139. }
  140. System.out.println(" 数据库连接己创建 ......");
  141. }
  142. }
  143. /**
  144. * 创建一个新的数据库连接并返回它
  145. *
  146. * @return 返回一个新创建的数据库连接
  147. */
  148. private Connection newConnection() throws SQLException {
  149. // 创建一个数据库连接
  150. Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
  151. // 如果这是第一次创建数据库连接,即检查数据库,获得此数据库允许支持的
  152. // 最大客户连接数目
  153. //connections.size()==0 表示目前没有连接己被创建
  154. if (connections.size() == 0) {
  155. DatabaseMetaData metaData = conn.getMetaData();
  156. int driverMaxConnections = metaData.getMaxConnections();
  157. // 数据库返回的 driverMaxConnections 若为 0 ,表示此数据库没有最大
  158. // 连接限制,或数据库的最大连接限制不知道
  159. //driverMaxConnections 为返回的一个整数,表示此数据库允许客户连接的数目
  160. // 如果连接池中设置的最大连接数量大于数据库允许的连接数目 , 则置连接池的最大
  161. // 连接数目为数据库允许的最大数目
  162. if (driverMaxConnections > 0 && this.maxConnections > driverMaxConnections) {
  163. this.maxConnections = driverMaxConnections;
  164. }
  165. }
  166. return conn; // 返回创建的新的数据库连接
  167. }
  168. /**
  169. * 通过调用 getFreeConnection() 函数返回一个可用的数据库连接 ,
  170. * 如果当前没有可用的数据库连接,并且更多的数据库连接不能创
  171. * 建(如连接池大小的限制),此函数等待一会再尝试获取。
  172. *
  173. * @return 返回一个可用的数据库连接对象
  174. */
  175. public synchronized Connection getConnection() throws SQLException {
  176. // 确保连接池己被创建
  177. if (connections == null) {
  178. return null; // 连接池还没创建,则返回 null
  179. }
  180. Connection conn = getFreeConnection(); // 获得一个可用的数据库连接
  181. // 如果目前没有可以使用的连接,即所有的连接都在使用中
  182. while (conn == null){
  183. // 等一会再试
  184. wait(250);
  185. conn = getFreeConnection(); // 重新再试,直到获得可用的连接,如果
  186. //getFreeConnection() 返回的为 null
  187. // 则表明创建一批连接后也不可获得可用连接
  188. }
  189. return conn;// 返回获得的可用的连接
  190. }
  191. /**
  192. * 本函数从连接池向量 connections 中返回一个可用的的数据库连接,如果
  193. * 当前没有可用的数据库连接,本函数则根据 incrementalConnections 设置
  194. * 的值创建几个数据库连接,并放入连接池中。
  195. * 如果创建后,所有的连接仍都在使用中,则返回 null
  196. * @return 返回一个可用的数据库连接
  197. */
  198. private Connection getFreeConnection() throws SQLException {
  199. // 从连接池中获得一个可用的数据库连接
  200. Connection conn = findFreeConnection();
  201. if (conn == null) {
  202. // 如果目前连接池中没有可用的连接
  203. // 创建一些连接
  204. createConnections(incrementalConnections);
  205. // 重新从池中查找是否有可用连接
  206. conn = findFreeConnection();
  207. if (conn == null) {
  208. // 如果创建连接后仍获得不到可用的连接,则返回 null
  209. return null;
  210. }
  211. }
  212. return conn;
  213. }
  214. /**
  215. * 查找连接池中所有的连接,查找一个可用的数据库连接,
  216. * 如果没有可用的连接,返回 null
  217. *
  218. * @return 返回一个可用的数据库连接
  219. */
  220. private Connection findFreeConnection() throws SQLException {
  221. Connection conn = null;
  222. PooledConnection pConn = null;
  223. // 获得连接池向量中所有的对象
  224. Enumeration enumerate = connections.elements();
  225. // 遍历所有的对象,看是否有可用的连接
  226. while (enumerate.hasMoreElements()) {
  227. pConn = (PooledConnection) enumerate.nextElement();
  228. if (!pConn.isBusy()) {
  229. // 如果此对象不忙,则获得它的数据库连接并把它设为忙
  230. conn = pConn.getConnection();
  231. pConn.setBusy(true);
  232. // 测试此连接是否可用
  233. if (!testConnection(conn)) {
  234. // 如果此连接不可再用了,则创建一个新的连接,
  235. // 并替换此不可用的连接对象,如果创建失败,返回 null
  236. try{
  237. conn = newConnection();
  238. }catch(SQLException e){
  239. System.out.println(" 创建数据库连接失败! "+e.getMessage());
  240. return null;
  241. }
  242. pConn.setConnection(conn);
  243. }
  244. break; // 己经找到一个可用的连接,退出
  245. }
  246. }
  247. return conn;// 返回找到到的可用连接
  248. }
  249. /**
  250. * 测试一个连接是否可用,如果不可用,关掉它并返回 false
  251. * 否则可用返回 true
  252. *
  253. * @param conn 需要测试的数据库连接
  254. * @return 返回 true 表示此连接可用, false 表示不可用
  255. */
  256. private boolean testConnection(Connection conn) {
  257. try {
  258. // 判断测试表是否存在
  259. if (testTable.equals("")) {
  260. // 如果测试表为空,试着使用此连接的 setAutoCommit() 方法
  261. // 来判断连接否可用(此方法只在部分数据库可用,如果不可用 ,
  262. // 抛出异常)。注意:使用测试表的方法更可靠
  263. conn.setAutoCommit(true);
  264. } else {// 有测试表的时候使用测试表测试
  265. //check if this connection is valid
  266. Statement stmt = conn.createStatement();
  267. stmt.execute("select count(*) from " + testTable);
  268. }
  269. } catch (SQLException e) {
  270. // 上面抛出异常,此连接己不可用,关闭它,并返回 false;
  271. closeConnection(conn);
  272. return false;
  273. }
  274. // 连接可用,返回 true
  275. return true;
  276. }
  277. /**
  278. * 此函数返回一个数据库连接到连接池中,并把此连接置为空闲。
  279. * 所有使用连接池获得的数据库连接均应在不使用此连接时返回它。
  280. *
  281. * @param 需返回到连接池中的连接对象
  282. */
  283. public void returnConnection(Connection conn) {
  284. // 确保连接池存在,如果连接没有创建(不存在),直接返回
  285. if (connections == null) {
  286. System.out.println(" 连接池不存在,无法返回此连接到连接池中 !");
  287. return;
  288. }
  289. PooledConnection pConn = null;
  290. Enumeration enumerate = connections.elements();
  291. // 遍历连接池中的所有连接,找到这个要返回的连接对象
  292. while (enumerate.hasMoreElements()) {
  293. pConn = (PooledConnection) enumerate.nextElement();
  294. // 先找到连接池中的要返回的连接对象
  295. if (conn == pConn.getConnection()) {
  296. // 找到了 , 设置此连接为空闲状态
  297. pConn.setBusy(false);
  298. break;
  299. }
  300. }
  301. }
  302. /**
  303. * 刷新连接池中所有的连接对象
  304. *
  305. */
  306. public synchronized void refreshConnections() throws SQLException {
  307. // 确保连接池己创新存在
  308. if (connections == null) {
  309. System.out.println(" 连接池不存在,无法刷新 !");
  310. return;
  311. }
  312. PooledConnection pConn = null;
  313. Enumeration enumerate = connections.elements();
  314. while (enumerate.hasMoreElements()) {
  315. // 获得一个连接对象
  316. pConn = (PooledConnection) enumerate.nextElement();
  317. // 如果对象忙则等 5 秒 ,5 秒后直接刷新
  318. if (pConn.isBusy()) {
  319. wait(5000); // 等 5 秒
  320. }
  321. // 关闭此连接,用一个新的连接代替它。
  322. closeConnection(pConn.getConnection());
  323. pConn.setConnection(newConnection());
  324. pConn.setBusy(false);
  325. }
  326. }
  327. /**
  328. * 关闭连接池中所有的连接,并清空连接池。
  329. */
  330. public synchronized void closeConnectionPool() throws SQLException {
  331. // 确保连接池存在,如果不存在,返回
  332. if (connections == null) {
  333. System.out.println(" 连接池不存在,无法关闭 !");
  334. return;
  335. }
  336. PooledConnection pConn = null;
  337. Enumeration enumerate = connections.elements();
  338. while (enumerate.hasMoreElements()) {
  339. pConn = (PooledConnection) enumerate.nextElement();
  340. // 如果忙,等 5 秒
  341. if (pConn.isBusy()) {
  342. wait(5000); // 等 5 秒
  343. }
  344. //5 秒后直接关闭它
  345. closeConnection(pConn.getConnection());
  346. // 从连接池向量中删除它
  347. connections.removeElement(pConn);
  348. }
  349. // 置连接池为空
  350. connections = null;
  351. }
  352. /**
  353. * 关闭一个数据库连接
  354. *
  355. * @param 需要关闭的数据库连接
  356. */
  357. private void closeConnection(Connection conn) {
  358. try {
  359. conn.close();
  360. }catch (SQLException e) {
  361. System.out.println(" 关闭数据库连接出错: "+e.getMessage());
  362. }
  363. }
  364. /**
  365. * 使程序等待给定的毫秒数
  366. *
  367. * @param 给定的毫秒数
  368. */
  369. private void wait(int mSeconds) {
  370. try {
  371. Thread.sleep(mSeconds);
  372. } catch (InterruptedException e) {
  373. }
  374. }
  375. /**
  376. *
  377. * 内部使用的用于保存连接池中连接对象的类
  378. * 此类中有两个成员,一个是数据库的连接,另一个是指示此连接是否
  379. * 正在使用的标志。
  380. */
  381. class PooledConnection {
  382. Connection connection = null;// 数据库连接
  383. boolean busy = false; // 此连接是否正在使用的标志,默认没有正在使用
  384. // 构造函数,根据一个 Connection 构告一个 PooledConnection 对象
  385. public PooledConnection(Connection connection) {
  386. this.connection = connection;
  387. }
  388. // 返回此对象中的连接
  389. public Connection getConnection() {
  390. return connection;
  391. }
  392. // 设置此对象的,连接
  393. public void setConnection(Connection connection) {
  394. this.connection = connection;
  395. }
  396. // 获得对象连接是否忙
  397. public boolean isBusy() {
  398. return busy;
  399. }
  400. // 设置对象的连接正在忙
  401. public void setBusy(boolean busy) {
  402. this.busy = busy;
  403. }
  404. }
  405. }
  406. =======================================
  407. 这个例子是根据POSTGRESQL数据库写的,
  408. 请用的时候根据实际的数据库调整。
  409. 调用方法如下:
  410. ① ConnectionPool connPool
  411. = new ConnectionPool("org.postgresql.Driver"
  412. ,"jdbc:postgresql://dbURI:5432/DBName"
  413. ,"postgre"
  414. ,"postgre");
  415. ② connPool .createPool();
  416.   Connection conn = connPool .getConnection();
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Vector;
public class ConnectionPool {
private String jdbcDriver = ""; // 数据库驱动
private String dbUrl = ""; // 数据 URL
private String dbUsername = ""; // 数据库用户名
private String dbPassword = ""; // 数据库用户密码
private String testTable = ""; // 测试连接是否可用的测试表名,默认没有测试表
private int initialConnections = 10; // 连接池的初始大小
private int incrementalConnections = 5;// 连接池自动增加的大小
private int maxConnections = 50; // 连接池最大的大小
private Vector connections = null; // 存放连接池中数据库连接的向量 , 初始时为 null

// 它中存放的对象为 PooledConnection 型

/**
* 构造函数
*
* @param jdbcDriver String JDBC 驱动类串
* @param dbUrl String 数据库 URL
* @param dbUsername String 连接数据库用户名
* @param dbPassword String 连接数据库用户的密码
*
*/

public ConnectionPool(String jdbcDriver,String dbUrl,String dbUsername,String dbPassword) {
         this.jdbcDriver = jdbcDriver;
         this.dbUrl = dbUrl;
         this.dbUsername = dbUsername; 
         this.dbPassword = dbPassword;
}

/**

* 返回连接池的初始大小
*
* @return 初始连接池中可获得的连接数量
*/
public int getInitialConnections() {

         return this.initialConnections;
}

/**

* 设置连接池的初始大小

*

* @param 用于设置初始连接池中连接的数量

*/

public void setInitialConnections(int initialConnections) {
         this.initialConnections = initialConnections;
}

/**

* 返回连接池自动增加的大小 、
*
* @return 连接池自动增加的大小
*/
public int getIncrementalConnections() {

         return this.incrementalConnections;

}

/**
* 设置连接池自动增加的大小
* @param 连接池自动增加的大小
*/

public void setIncrementalConnections(int incrementalConnections) {

         this.incrementalConnections = incrementalConnections;

}

/**
* 返回连接池中最大的可用连接数量
* @return 连接池中最大的可用连接数量
*/

public int getMaxConnections() {
         return this.maxConnections;
}

/**

* 设置连接池中最大可用的连接数量

*

* @param 设置连接池中最大可用的连接数量值

*/

public void setMaxConnections(int maxConnections) {

         this.maxConnections = maxConnections;

}

/**

* 获取测试数据库表的名字
*
* @return 测试数据库表的名字
*/
public String getTestTable() {

         return this.testTable;

}

/**
* 设置测试表的名字
* @param testTable String 测试表的名字
*/
public void setTestTable(String testTable) {
         this.testTable = testTable;
}

/**

*
* 创建一个数据库连接池,连接池中的可用连接的数量采用类成员
* initialConnections 中设置的值
*/
public synchronized void createPool() throws Exception {

         // 确保连接池没有创建
  
         // 如果连接池己经创建了,保存连接的向量 connections 不会为空
  
         if (connections != null) {
  
          return; // 如果己经创建,则返回
  
         }
  
         // 实例化 JDBC Driver 中指定的驱动类实例
  
         Driver driver = (Driver) (Class.forName(this.jdbcDriver).newInstance());
  
         DriverManager.registerDriver(driver); // 注册 JDBC 驱动程序
  
         // 创建保存连接的向量 , 初始时有 0 个元素
  
         connections = new Vector();
  
         // 根据 initialConnections 中设置的值,创建连接。
  
         createConnections(this.initialConnections);
  
         System.out.println(" 数据库连接池创建成功! ");

}

/**

* 创建由 numConnections 指定数目的数据库连接 , 并把这些连接

* 放入 connections 向量中
*
* @param numConnections 要创建的数据库连接的数目
*/
@SuppressWarnings("unchecked")
private void createConnections(int numConnections) throws SQLException {

         // 循环创建指定数目的数据库连接
  
         for (int x = 0; x < numConnections; x++) {
  
          // 是否连接池中的数据库连接的数量己经达到最大?最大值由类成员 maxConnections
   
          // 指出,如果 maxConnections 为 0 或负数,表示连接数量没有限制。
   
          // 如果连接数己经达到最大,即退出。
   
          if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) {
   
           break;
   
          }
  
          //add a new PooledConnection object to connections vector
   
          // 增加一个连接到连接池中(向量 connections 中)
   
          try{
   
           connections.addElement(new PooledConnection(newConnection()));
   
          }catch(SQLException e){
   
           System.out.println(" 创建数据库连接失败! "+e.getMessage());
   
          throw new SQLException();
   
          }
   
          System.out.println(" 数据库连接己创建 ......");
   
         }
}

/**

* 创建一个新的数据库连接并返回它
*
* @return 返回一个新创建的数据库连接
*/
private Connection newConnection() throws SQLException {

         // 创建一个数据库连接
  
         Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
  
         // 如果这是第一次创建数据库连接,即检查数据库,获得此数据库允许支持的
  
         // 最大客户连接数目
  
         //connections.size()==0 表示目前没有连接己被创建
  
         if (connections.size() == 0) {
  
          DatabaseMetaData metaData = conn.getMetaData();
   
          int driverMaxConnections = metaData.getMaxConnections();
   
          // 数据库返回的 driverMaxConnections 若为 0 ,表示此数据库没有最大
   
          // 连接限制,或数据库的最大连接限制不知道
   
          //driverMaxConnections 为返回的一个整数,表示此数据库允许客户连接的数目
   
          // 如果连接池中设置的最大连接数量大于数据库允许的连接数目 , 则置连接池的最大
   
          // 连接数目为数据库允许的最大数目
   
          if (driverMaxConnections > 0 && this.maxConnections > driverMaxConnections) {
   
           this.maxConnections = driverMaxConnections;
   
          }
         } 
         return conn; // 返回创建的新的数据库连接

}

/**

* 通过调用 getFreeConnection() 函数返回一个可用的数据库连接 ,

* 如果当前没有可用的数据库连接,并且更多的数据库连接不能创

* 建(如连接池大小的限制),此函数等待一会再尝试获取。

*

* @return 返回一个可用的数据库连接对象

*/

public synchronized Connection getConnection() throws SQLException {

         // 确保连接池己被创建
  
         if (connections == null) {
  
          return null; // 连接池还没创建,则返回 null
  
         }
  
         Connection conn = getFreeConnection(); // 获得一个可用的数据库连接
  
         // 如果目前没有可以使用的连接,即所有的连接都在使用中
  
         while (conn == null){
  
          // 等一会再试
   
          wait(250);
   
          conn = getFreeConnection(); // 重新再试,直到获得可用的连接,如果
   
          //getFreeConnection() 返回的为 null
   
          // 则表明创建一批连接后也不可获得可用连接
  
         }
  
         return conn;// 返回获得的可用的连接
}

/**

* 本函数从连接池向量 connections 中返回一个可用的的数据库连接,如果

* 当前没有可用的数据库连接,本函数则根据 incrementalConnections 设置

* 的值创建几个数据库连接,并放入连接池中。

* 如果创建后,所有的连接仍都在使用中,则返回 null

* @return 返回一个可用的数据库连接

*/

private Connection getFreeConnection() throws SQLException {

         // 从连接池中获得一个可用的数据库连接
  
         Connection conn = findFreeConnection();
  
         if (conn == null) {
  
          // 如果目前连接池中没有可用的连接
   
          // 创建一些连接
   
          createConnections(incrementalConnections);
   
          // 重新从池中查找是否有可用连接
   
          conn = findFreeConnection();
   
          if (conn == null) {
   
           // 如果创建连接后仍获得不到可用的连接,则返回 null
    
           return null;
   
          }
  
         }
  
         return conn;

}

/**

* 查找连接池中所有的连接,查找一个可用的数据库连接,

* 如果没有可用的连接,返回 null

*

* @return 返回一个可用的数据库连接

*/

private Connection findFreeConnection() throws SQLException {

         Connection conn = null;
  
         PooledConnection pConn = null;
  
         // 获得连接池向量中所有的对象
  
         Enumeration enumerate = connections.elements();
  
         // 遍历所有的对象,看是否有可用的连接
  
         while (enumerate.hasMoreElements()) {
  
          pConn = (PooledConnection) enumerate.nextElement();
   
          if (!pConn.isBusy()) {
   
           // 如果此对象不忙,则获得它的数据库连接并把它设为忙
    
           conn = pConn.getConnection();
    
           pConn.setBusy(true);
    
           // 测试此连接是否可用
    
           if (!testConnection(conn)) {
    
            // 如果此连接不可再用了,则创建一个新的连接,
     
            // 并替换此不可用的连接对象,如果创建失败,返回 null
     
            try{
     
             conn = newConnection();
     
            }catch(SQLException e){
     
             System.out.println(" 创建数据库连接失败! "+e.getMessage());
     
             return null;
     
            }
    
            pConn.setConnection(conn);
    
           }
    
           break; // 己经找到一个可用的连接,退出
   
          }
  
         }
  
         return conn;// 返回找到到的可用连接

}

/**

* 测试一个连接是否可用,如果不可用,关掉它并返回 false

* 否则可用返回 true

*

* @param conn 需要测试的数据库连接

* @return 返回 true 表示此连接可用, false 表示不可用

*/

private boolean testConnection(Connection conn) {

         try {
  
          // 判断测试表是否存在
   
          if (testTable.equals("")) {
   
           // 如果测试表为空,试着使用此连接的 setAutoCommit() 方法
    
           // 来判断连接否可用(此方法只在部分数据库可用,如果不可用 ,
    
           // 抛出异常)。注意:使用测试表的方法更可靠
    
           conn.setAutoCommit(true);
   
          } else {// 有测试表的时候使用测试表测试
   
           //check if this connection is valid
    
           Statement stmt = conn.createStatement();
    
           stmt.execute("select count(*) from " + testTable);
   
          }
  
         } catch (SQLException e) {
  
          // 上面抛出异常,此连接己不可用,关闭它,并返回 false;
  
          closeConnection(conn);
  
          return false;
  
         }
  
         // 连接可用,返回 true
  
         return true;

}

/**

* 此函数返回一个数据库连接到连接池中,并把此连接置为空闲。

* 所有使用连接池获得的数据库连接均应在不使用此连接时返回它。

*

* @param 需返回到连接池中的连接对象

*/

public void returnConnection(Connection conn) {

         // 确保连接池存在,如果连接没有创建(不存在),直接返回
  
         if (connections == null) {
  
          System.out.println(" 连接池不存在,无法返回此连接到连接池中 !");
   
          return;
  
         }

         PooledConnection pConn = null;
  
         Enumeration enumerate = connections.elements();
  
         // 遍历连接池中的所有连接,找到这个要返回的连接对象
  
         while (enumerate.hasMoreElements()) {

          pConn = (PooledConnection) enumerate.nextElement();
   
          // 先找到连接池中的要返回的连接对象
   
          if (conn == pConn.getConnection()) {
   
           // 找到了 , 设置此连接为空闲状态
    
           pConn.setBusy(false);
    
           break;
   
          }

         }

}

/**

* 刷新连接池中所有的连接对象

*

*/

public synchronized void refreshConnections() throws SQLException {

         // 确保连接池己创新存在
  
         if (connections == null) {
  
          System.out.println(" 连接池不存在,无法刷新 !");
  
          return;
  
         }
  
         PooledConnection pConn = null;
  
         Enumeration enumerate = connections.elements();
  
         while (enumerate.hasMoreElements()) {

          // 获得一个连接对象
   
          pConn = (PooledConnection) enumerate.nextElement();
   
          // 如果对象忙则等 5 秒 ,5 秒后直接刷新
   
          if (pConn.isBusy()) {
   
           wait(5000); // 等 5 秒
   
          }
   
          // 关闭此连接,用一个新的连接代替它。
   
          closeConnection(pConn.getConnection());
   
          pConn.setConnection(newConnection());
   
          pConn.setBusy(false);
   
         }

}

/**

* 关闭连接池中所有的连接,并清空连接池。

*/

public synchronized void closeConnectionPool() throws SQLException {

         // 确保连接池存在,如果不存在,返回
  
         if (connections == null) {
  
          System.out.println(" 连接池不存在,无法关闭 !");
  
          return;
  
         }
  
         PooledConnection pConn = null;
  
         Enumeration enumerate = connections.elements();
  
         while (enumerate.hasMoreElements()) {
  
          pConn = (PooledConnection) enumerate.nextElement();
  
          // 如果忙,等 5 秒
  
          if (pConn.isBusy()) {
  
           wait(5000); // 等 5 秒
  
          }
  
         //5 秒后直接关闭它
  
         closeConnection(pConn.getConnection());
  
         // 从连接池向量中删除它
  
         connections.removeElement(pConn);
  
         }
  
         // 置连接池为空
  
         connections = null;

}

/**

* 关闭一个数据库连接

*

* @param 需要关闭的数据库连接

*/

private void closeConnection(Connection conn) {

         try {
  
          conn.close();
  
         }catch (SQLException e) {
  
          System.out.println(" 关闭数据库连接出错: "+e.getMessage());
  
         }

}

/**

* 使程序等待给定的毫秒数

*

* @param 给定的毫秒数

*/

private void wait(int mSeconds) {

         try {
  
          Thread.sleep(mSeconds);
  
         } catch (InterruptedException e) {
  
         }

}

/**

*

* 内部使用的用于保存连接池中连接对象的类

* 此类中有两个成员,一个是数据库的连接,另一个是指示此连接是否

* 正在使用的标志。

*/

class PooledConnection {

         Connection connection = null;// 数据库连接
  
         boolean busy = false; // 此连接是否正在使用的标志,默认没有正在使用
  
         // 构造函数,根据一个 Connection 构告一个 PooledConnection 对象
  
         public PooledConnection(Connection connection) {
  
          this.connection = connection;
  
         }
  
         // 返回此对象中的连接
  
         public Connection getConnection() {
  
          return connection;

         }

         // 设置此对象的,连接
  
         public void setConnection(Connection connection) {
  
          this.connection = connection;
   
         }
   
         // 获得对象连接是否忙
   
         public boolean isBusy() {
   
          return busy;
   
         }
   
         // 设置对象的连接正在忙
   
         public void setBusy(boolean busy) {
   
          this.busy = busy;
   
         }

}

}

=======================================

这个例子是根据POSTGRESQL数据库写的,
请用的时候根据实际的数据库调整。

调用方法如下:

① ConnectionPool connPool
                                     = new ConnectionPool("org.postgresql.Driver"
                                                                         ,"jdbc:postgresql://dbURI:5432/DBName"
                                                                         ,"postgre"
                                                                         ,"postgre");

② connPool .createPool();
  Connection conn = connPool .getConnection();

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值