java c3p0获取主键_[数据库连接池二]Java数据库连接池--C3P0和JDNI.

前言:

上一篇文章中讲了DBCP的用法以及实现原理, 这一篇再来说下C3P0和JDNI的用法.

1.1、C3P0数据源

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。

c3p0与dbcp区别dbcp没有自动回收空闲连接的功能

c3p0有自动回收空闲连接功能

1.2、在应用程序中加入C3P0连接池

1.导入相关jar包

c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.2-pre1.jar

2、在类目录下加入C3P0的配置文件:c3p0-config.xml

c3p0-config.xml的配置信息如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png<?xml  version="1.0" encoding="UTF-8"?>

com.mysql.jdbc.Driver

jdbc:mysql://localhost:3306/jdbcstudy

root

XDP

5

10

5

20

com.mysql.jdbc.Driver

jdbc:mysql://localhost:3306/jdbcstudy

root

XDP

5

10

5

20

48304ba5e6f9fe08f3fa1abda7d326ab.png

如下图所示:

C3P0使用实例: C3P0Utils.java

48304ba5e6f9fe08f3fa1abda7d326ab.png1 public class C3P0Utils { 2     private static DataSource dataSource = new ComboPooledDataSource(); 3      4     //从池中获取一个连接 5     public static Connection getConnection() throws SQLException{ 6         return dataSource.getConnection(); 7     } 8      9     public static void closeAll(ResultSet rs,Statement stmt,Connection conn){10         if(rs!=null){11             try {12                 rs.close();13             } catch (SQLException e) {14                 e.printStackTrace();15             }16         }17         18         if(stmt!=null){19             try {20                 stmt.close();21             } catch (SQLException e) {22                 e.printStackTrace();23             }24         }25         26         if(conn!=null){27             try {28                 conn.close();//关闭29             } catch (SQLException e) {30                 e.printStackTrace();31             }32         }33     }34 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

测试类:UserDaoImpl.java

48304ba5e6f9fe08f3fa1abda7d326ab.png1 public class UserDaoImpl { 2     @Test 3     public void testInsert(){ 4         Connection conn = null; 5         PreparedStatement ps = null; 6         try { 7             conn = C3P0Utils.getConnection(); 8             ps = conn.prepareStatement(""); 9             //...10             System.out.println(conn.getClass().getName());11         } catch (SQLException e) {12             e.printStackTrace();13         }finally{14             C3P0Utils.closeAll(null, ps, conn);15             16         }17     }18 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

可以看出只要将配置文件c3p0-config.xml放在classpath中,或classes目录中, 然后通过private static DataSource dataSource = new ComboPooledDataSource();就可以自动读取到,确实很方便易用.

到了这里我们来看一下这里的源码:private static DataSource dataSource = new ComboPooledDataSource();

ComboPooledDataSource.java

48304ba5e6f9fe08f3fa1abda7d326ab.png1  // not reassigned post-ctor; mutable elements protected by their own locks 2     // when (very rarely) necessery, we sync this -> wcpds -> dmds 3  4     // note that serialization of these guys happens via out superclass 5     // we just have to make sure they get properly reset on deserialization 6     transient DriverManagerDataSource         dmds; 7     transient WrapperConnectionPoolDataSource wcpds; 8  9     public ComboPooledDataSource()10     { this( true ); }11 12     public ComboPooledDataSource( boolean autoregister )13     {14         super( autoregister );15 16         // System.err.println("...Initializing ComboPooledDataSource.");17 18         dmds  = new DriverManagerDataSource();19         wcpds = new WrapperConnectionPoolDataSource();20 21         wcpds.setNestedDataSource( dmds );22 23         try24         { this.setConnectionPoolDataSource( wcpds ); }25         catch (PropertyVetoException e)26         {27             logger.log(MLevel.WARNING, "Hunh??? This can't happen. We haven't set up any listeners to veto the property change yet!", e);28             throw new RuntimeException("Hunh??? This can't happen. We haven't set up any listeners to veto the property change yet! " + e);29         }30 31         // set things up in case there are future changes to our ConnectionPoolDataSource32         //33         setUpPropertyEvents();34     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

2.1 , JDNI

JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,

这 套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需 通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。

Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,通过查看Tomcat文档,我们知道使用如下的方式配置tomcat服务器的数据源:1 

2   

3             type="javax.sql.DataSource" username="root" password="123456"

4             driverClassName="com.mysql.jdbc.Driver"

5             url="jdbc:mysql://localhost:3306/datest"

6             maxActive="8" maxIdle="4"/>

服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序。我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:第一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的。第二种就是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可。

对于上面的name="jdbc/datasource"数据源资源,在应用程序中可以用如下的代码去获取1 Context initCtx = new InitialContext();

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

3 dataSource = (DataSource)envCtx.lookup("jdbc/datasource");

此种配置下,数据库的驱动jar文件需放置在tomcat的lib下

2.2、配置Tomcat数据源

1、在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件

如下图所示:

2、在context.xml文件配置tomcat服务器的数据源

48304ba5e6f9fe08f3fa1abda7d326ab.png1  2    

3        name="jdbc/datasource"  4        auth="Container" 5        type="javax.sql.DataSource"  6        username="root"  7        password="XDP" 8        driverClassName="com.mysql.jdbc.Driver"  9        url="jdbc:mysql://localhost:3306/jdbcstudy"10        maxActive="8" 11        maxIdle="4"/>12 

48304ba5e6f9fe08f3fa1abda7d326ab.png

3、将数据库的驱动jar文件需放置在tomcat的lib下

4、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中获取JNDI容器中的数据源

48304ba5e6f9fe08f3fa1abda7d326ab.png1 public class JdbcUtils_JNDI { 2      3     private static DataSource ds = null; 4     //在静态代码块中创建数据库连接池 5     static{ 6         try{ 7              //初始化JNDI 8             Context initCtx = new InitialContext(); 9              //得到JNDI容器10             Context envCtx = (Context) initCtx.lookup("java:comp/env");11              //从JNDI容器中检索name为jdbc/datasource的数据源12             ds = (DataSource)envCtx.lookup("jdbc/datasource");13         }catch (Exception e) {14             throw new ExceptionInInitializerError(e);15         }16     }17     18     public static Connection getConnection() throws SQLException{19         //从数据源中获取数据库连接20         return ds.getConnection();21     }22     23 24     public static void release(Connection conn,Statement st,ResultSet rs){25         if(rs!=null){26             try{27                 //关闭存储查询结果的ResultSet对象28                 rs.close();29             }catch (Exception e) {30                 e.printStackTrace();31             }32             rs = null;33         }34         if(st!=null){35             try{36                 //关闭负责执行SQL命令的Statement对象37                 st.close();38             }catch (Exception e) {39                 e.printStackTrace();40             }41         }42         43         if(conn!=null){44             try{45                 //将Connection连接对象还给数据库连接池46                 conn.close();47             }catch (Exception e) {48                 e.printStackTrace();49             }50         }51     }52 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

写一个Servlet测试JNDI数据源

48304ba5e6f9fe08f3fa1abda7d326ab.png1 public class JNDITest extends HttpServlet { 2  3     public void doGet(HttpServletRequest request, HttpServletResponse response) 4             throws ServletException, IOException { 5         Connection conn = null; 6         PreparedStatement st = null; 7         ResultSet rs = null; 8         try{ 9             //获取数据库连接10             conn = JdbcUtils_JNDI.getConnection();11             String sql = "insert into test1(name) values(?)";12             st = conn.prepareStatement(sql);13             st.setString(1, "gacl");14             st.executeUpdate();15             //获取数据库自动生成的主键16             rs = st.getGeneratedKeys();17             if(rs.next()){18                 System.out.println(rs.getInt(1));19             }20         }catch (Exception e) {21             e.printStackTrace();22         }finally{23             //释放资源24             JdbcUtils_JNDI.release(conn, st, rs);25         }26     }27 28     public void doPost(HttpServletRequest request, HttpServletResponse response)29             throws ServletException, IOException {30         doGet(request, response);31     }33 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

5f37628559badc978b16f0236e792138.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值