您当前的位置: 首页 >  Java

wespten

暂无认证

  • 1浏览

    0关注

    899博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JavaWeb开发与代码的编写(十六)

wespten 发布时间:2019-08-24 10:56:41 ,浏览量:1

JavaWeb开发与代码的编写(十六)

JDBC进行批处理

  在实际的项目开发中,有时候需要向数据库发送一批SQL语句执行,这时应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。   JDBC实现批处理有两种方式:statement和preparedstatement

使用Statement完成批处理

  1、使用Statement对象添加要批量执行SQL语句,如下:

Statement.addBatch(sql1);
Statement.addBatch(sql2);
Statement.addBatch(sql3);

   2、执行批处理SQL语句:Statement.executeBatch();    3、清除批处理命令:Statement.clearBatch();

使用Statement完成批处理范例

  1、编写测试的SQL脚本创建表

  create table testbatch
 (
      id int primary key,
      name varchar(20)
 );

  2、编写测试代码,如下所示:

  package me.gacl.demo;
  
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.Statement;
  import me.gacl.utils.JdbcUtils;
  import org.junit.Test;
  
/**
* @ClassName: JdbcBatchHandleByStatement
* @Description: 使用Statement实现JDBC批处理操作
 *
 */ 
 public class JdbcBatchHandleByStatement {
 
     @Test
     public void testJdbcBatchHandleByStatement(){
         Connection conn = null;
         Statement st = null;
         ResultSet rs = null;
         try{
             conn = JdbcUtils.getConnection();
             String sql1 = "insert into testbatch(id,name) values(1,'aaa')";
             String sql2 = "insert into testbatch(id,name) values(2,'bbb')";
             String sql3 = "insert into testbatch(id,name) values(3,'CCC')";
             String sql4 = "insert into testbatch(id,name) values(4,'DDD')";
             String sql5 = "update testbatch set name='gacl' where id=1";
             String sql6 = "insert into testbatch(id,name) values(5,'FFF')";
             String sql7 = "delete from testbatch where id=2";
            st = conn.createStatement();
            //添加要批量执行的SQL
             st.addBatch(sql1);
             st.addBatch(sql2);
             st.addBatch(sql3);
             st.addBatch(sql4);
             st.addBatch(sql5);
             st.addBatch(sql6);
             st.addBatch(sql7);
             //执行批处理SQL语句
             st.executeBatch();
             //清除批处理命令
             st.clearBatch();
         }catch (Exception e) {
             e.printStackTrace();
        }finally{
             JdbcUtils.release(conn, st, rs);
         }
     }
 }

采用Statement.addBatch(sql)方式实现批处理的优缺点

  采用Statement.addBatch(sql)方式实现批处理:     优点:可以向数据库发送多条不同的SQL语句。     缺点:SQL语句没有预编译。     当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:

Insert into user(name,password) values('aa','111');
Insert into user(name,password) values('bb','222');
Insert into user(name,password) values('cc','333');
Insert into user(name,password) values('dd','444');

使用PreparedStatement完成批处理

使用PreparedStatement完成批处理范例

  测试代码如下:

  package me.gacl.demo;
  
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import me.gacl.utils.JdbcUtils;
  import org.junit.Test;
  
  /**
 * @ClassName: JdbcBatchHandleByStatement
 * @Description: 使用prepareStatement实现JDBC批处理操作
 *
 */ 
 public class JdbcBatchHandleByPrepareStatement {
 
     @Test
     public void testJdbcBatchHandleByPrepareStatement(){
         long starttime = System.currentTimeMillis();
         Connection conn = null;
         PreparedStatement st = null;
         ResultSet rs = null;
         
         try{
             conn = JdbcUtils.getConnection();
             String sql = "insert into testbatch(id,name) values(?,?)";
             st = conn.prepareStatement(sql);
             for(int i=1;i
  
 
 
     
     
         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
     
 
 

 如下图所示:

 

  3、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池

 1 package me.gacl.util;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 import com.mchange.v2.c3p0.ComboPooledDataSource;
 8 
 9 /**
10 * @ClassName: JdbcUtils_C3P0
11 * @Description: 数据库连接工具类
15 */ 
16 public class JdbcUtils_C3P0 {
17     
18     private static ComboPooledDataSource ds = null;
19     //在静态代码块中创建数据库连接池
20     static{
21         try{
22             //通过代码创建C3P0数据库连接池
23             /*ds = new ComboPooledDataSource();
24             ds.setDriverClass("com.mysql.jdbc.Driver");
25             ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
26             ds.setUser("root");
27             ds.setPassword("XDP");
28             ds.setInitialPoolSize(10);
29             ds.setMinPoolSize(5);
30             ds.setMaxPoolSize(20);*/
31             
32             //通过读取C3P0的xml配置文件创建数据源,C3P0的xml配置文件c3p0-config.xml必须放在src目录下
33             //ds = new ComboPooledDataSource();//使用C3P0的默认配置来创建数据源
34             ds = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置来创建数据源
35             
36         }catch (Exception e) {
37             throw new ExceptionInInitializerError(e);
38         }
39     }
40     
41     /**
42     * @Method: getConnection
43     * @Description: 从数据源中获取数据库连接
45     * @return Connection
46     * @throws SQLException
47     */ 
48     public static Connection getConnection() throws SQLException{
49         //从数据源中获取数据库连接
50         return ds.getConnection();
51     }
52     
53     /**
54     * @Method: release
55     * @Description: 释放资源,
56     * 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
58     *
59     * @param conn
60     * @param st
61     * @param rs
62     */ 
63     public static void release(Connection conn,Statement st,ResultSet rs){
64         if(rs!=null){
65             try{
66                 //关闭存储查询结果的ResultSet对象
67                 rs.close();
68             }catch (Exception e) {
69                 e.printStackTrace();
70             }
71             rs = null;
72         }
73         if(st!=null){
74             try{
75                 //关闭负责执行SQL命令的Statement对象
76                 st.close();
77             }catch (Exception e) {
78                 e.printStackTrace();
79             }
80         }
81         
82         if(conn!=null){
83             try{
84                 //将Connection连接对象还给数据库连接池
85                 conn.close();
86             }catch (Exception e) {
87                 e.printStackTrace();
88             }
89         }
90     }
91 }

  测试C3P0数据源

 package me.gacl.test;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import org.junit.Test;
 import me.gacl.util.JdbcUtils_C3P0;
 import me.gacl.util.JdbcUtils_DBCP;
 
 public class DataSourceTest {
     
     @Test
     public void c3p0DataSourceTest() {
        Connection conn = null;
         PreparedStatement st = null;
         ResultSet rs = null;
         try{
             //获取数据库连接
             conn = JdbcUtils_C3P0.getConnection();
             String sql = "insert into test1(name) values(?)";
             st = conn.prepareStatement(sql);
             st.setString(1, "gacl");             st.executeUpdate();
             //获取数据库自动生成的主键
             rs = st.getGeneratedKeys();
             if(rs.next()){
                 System.out.println(rs.getInt(1));
             }
        }catch (Exception e) {
            e.printStackTrace();
         }finally{
             //释放资源
             JdbcUtils_C3P0.release(conn, st, rs);
         }
     }
 }

 

配置Tomcat数据源

  在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可。要想让Tomcat服务器在启动的时候帮我们创建一个数据库连接池,那么需要简单配置一下Tomcat服务器。

JNDI技术简介

  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服务器的数据源:

 
  
 

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

  对于上面的name="jdbc/datasource"数据源资源,在应用程序中可以用如下的代码去获取

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/datasource");

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

 

 

配置Tomcat数据源

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

  如下图所示:

  

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

  
   
 

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

  

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

 1 package me.gacl.util;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 import javax.naming.Context;
 8 import javax.naming.InitialContext;
 9 import javax.sql.DataSource;
10 
11 /**
12 * @ClassName: JdbcUtils_DBCP
13 * @Description: 数据库连接工具类
16 *
17 */ 
18 public class JdbcUtils_JNDI {
19     
20     private static DataSource ds = null;
21     //在静态代码块中创建数据库连接池
22     static{
23         try{
24              //初始化JNDI
25             Context initCtx = new InitialContext();
26              //得到JNDI容器
27             Context envCtx = (Context) initCtx.lookup("java:comp/env");
28              //从JNDI容器中检索name为jdbc/datasource的数据源
29             ds = (DataSource)envCtx.lookup("jdbc/datasource");
30         }catch (Exception e) {
31             throw new ExceptionInInitializerError(e);
32         }
33     }
34     
35     /**
36     * @Method: getConnection
37     * @Description: 从数据源中获取数据库连接
39     * @return Connection
40     * @throws SQLException
41     */ 
42     public static Connection getConnection() throws SQLException{
43         //从数据源中获取数据库连接
44         return ds.getConnection();
45     }
46     
47     /**
48     * @Method: release
49     * @Description: 释放资源,
50     * 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
52     *
53     * @param conn
54     * @param st
55     * @param rs
56     */ 
57     public static void release(Connection conn,Statement st,ResultSet rs){
58         if(rs!=null){
59             try{
60                 //关闭存储查询结果的ResultSet对象
61                 rs.close();
62             }catch (Exception e) {
63                 e.printStackTrace();
64             }
65             rs = null;
66         }
67         if(st!=null){
68             try{
69                 //关闭负责执行SQL命令的Statement对象
70                 st.close();
71             }catch (Exception e) {
72                 e.printStackTrace();
73             }
74         }
75         
76         if(conn!=null){
77             try{
78                 //将Connection连接对象还给数据库连接池
79                 conn.close();
80             }catch (Exception e) {
81                 e.printStackTrace();
82             }
83         }
84     }
85 }

 写一个Servlet测试JNDI数据源

 package me.gacl.test;
 
 import java.io.IOException;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import me.gacl.util.JdbcUtils_JNDI;
 
 public class JNDITest extends HttpServlet {
 
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         Connection conn = null;         PreparedStatement st = null;
         ResultSet rs = null;
         try{
             //获取数据库连接
             conn = JdbcUtils_JNDI.getConnection();             String sql = "insert into test1(name) values(?)";
             st = conn.prepareStatement(sql);
             st.setString(1, "gacl");
             st.executeUpdate();
             //获取数据库自动生成的主键
            rs = st.getGeneratedKeys();
             if(rs.next()){
                 System.out.println(rs.getInt(1));
             }
         }catch (Exception e) {
             e.printStackTrace();
         }finally{
             //释放资源
             JdbcUtils_JNDI.release(conn, st, rs);
         }
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

 

 

关注
打赏
1665965058
查看更多评论
立即登录/注册

微信扫码登录

0.0449s