MySQL---数据库从入门走向大神系列(十一)-Java获取数据库/结果集的元信息、将数据表写入excel表格(1)

简介: MySQL---数据库从入门走向大神系列(十一)-Java获取数据库/结果集的元信息、将数据表写入excel表格

问题概述:

之前本系列博客写的,全部都是一个connection对象,不知道大家发现没有,我们既然做了一个Connection工具类,那么大家肯定都是从那里面拿Connection对象的,之前的如果是多线程运行,很容易出问题的,你想想事务处理就知道了,同时用事务处理操作同一个Connection,肯定会出问题的。

例如:

一方的事务在提交的时候,你正好运行了一个事务中的一个操作,那么你这个操作也会被提交,而且你后面的提交或回滚失效的,如果对方把Connection关闭了,你的程序还会挂。

等等问题…

那么,我们就需要一个Connection对象池,谁来了,就去池中拿对象,不会再是同一个了,而且可以很好的控制池中Connection对象的数目,不可能一直new Connection对象的,如果池中的对象用完了,我们就让那个客户端等,等别人用完Connection对象还回到池中。

配置文件:jdbc.propertise

##MySQL
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///hncu?useUnicode=true&characterEncoding=utf-8
username=root
password=1234
##Oracle
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#username=scott
#password=tiger

ConnsUtil:Connection池

package cn.hncu.pool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class ConnsUtil {
    //声明一个池
    private static List<Connection> pool = new ArrayList<Connection>();
    //声明池中的Connection对象个数
    private static final int NUM = 3;
    static{
        try {
            //读取配置文件
            Properties p = new Properties();
            p.load(ConnsUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            String driver = p.getProperty("driver");
            String url = p.getProperty("url");
            String user = p.getProperty("username");
            String password = p.getProperty("password");
            Class.forName(driver);
            for(int i=0;i<NUM;i++){
                Connection con = DriverManager.getConnection(url, user, password);
                //加入池中
                pool.add(con);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static synchronized Connection getConnection() throws InterruptedException{
        if(pool.size()<=0){
            Thread.sleep(100);
            return getConnection();
        }
        return pool.remove(0);
    }
    public static void back(Connection con){
        System.out.println("还回来一个Connection连接...");
        pool.add(con);
    }
}

测试类:

package cn.hncu.pool;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class TestPool {
    public static void main(String[] args) {
        Connection con = null;
        try{
            con = ConnsUtil.getConnection();
            con.setAutoCommit(false);
            Statement st = con.createStatement();
            String sql ="insert into stud values('P201','关羽',30) ";
            st.execute(sql);
            sql ="insert into stud values('P202','张飞',25) ";
            st.execute(sql);
            new OneThread(1).start();
            new OneThread(2).start();
            new OneThread(3).start();
            new OneThread(4).start();
            new OneThread(5).start();
            System.out.println("主线程准备提交...");
            con.commit();
            System.out.println("主线程提交完毕...");
        }catch (Exception e) {
            try {
                con.rollback();
                System.out.println("主线程回滚了...");
            } catch (SQLException e1) {
                throw new RuntimeException("主线程事务回滚失败!", e1);
            }
        }finally{
            try {
                if(con!=null){
                    con.setAutoCommit(true);
                    ConnsUtil.back(con);
                    //con.close();//如果要把close内部的功能换成还连接,就需要我们以后的技术来实现
                }
            } catch (SQLException e) {
                throw new RuntimeException("主线程连接关闭失败!", e);
            }
        }
    }
}
class OneThread extends Thread{
    private int n;
    public OneThread(int n) {
        this.n = n;
    }
    @Override
    public void run() {
        Connection con = null;
        try{
            con = ConnsUtil.getConnection();
            con.setAutoCommit(false);
            Statement st = con.createStatement();
            String sql ="insert into stud values('P30"+n+"','刘备',30) ";
            st.execute(sql);
            sql ="insert into stud values('P31"+n+"','曹操',25) ";
            st.execute(sql);
            System.out.println("第"+n+"个线程准备提交...");
            con.commit();
            System.out.println("第"+n+"个线程提交完毕...");
        }catch (Exception e) {
            try {
                con.rollback();
                System.out.println("第"+n+"个线程回滚了...");
            } catch (SQLException e1) {
                throw new RuntimeException("第"+n+"事务回滚失败!", e1);
            }
        }finally{
            try {
                if(con!=null){
                    con.setAutoCommit(true);
                    //con.close();//这里就是我们需要改进的地方
                    ConnsUtil.back(con);
                }
            } catch (SQLException e) {
                throw new RuntimeException("第"+n+"连接关闭失败!", e);
            }
        }
    }
}

image.png

image.png

在调用返回Connection对象回到池中的时候,用普通的调用,不可避免的要去调用自己写的一个返回方法,如何在不改变程序员变成习惯(一般都习惯用close()去关闭那个对象)的情况下去实现Connection对象的回收呢,那就需要用到装饰模式,或者代理模式了。

装饰模式:

装饰模式又名包装(Wrapper)模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

其实我们要做的就是写一个MyConnection类实现Connection接口,实现所有方法,再进行扩展!

public class ConnsUtil {
    private static List<Connection> pool = new ArrayList<Connection>();
    private static final int NUM=3;
    static{
        try {
            Properties p = new Properties();
            p.load(ConnsUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            String drive = p.getProperty("driver");
            String url = p.getProperty("url");
            String user = p.getProperty("username");
            String password = p.getProperty("password");
            Class.forName(drive);
            for(int i=0;i<NUM;i++){
                Connection conn = DriverManager.getConnection(url, user, password);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    public static synchronized Connection getConnection() throws InterruptedException{
        if(pool.size()<=0){
            Thread.sleep(50);
            return getConnection();
        }
        return pool.remove(0);
    }
    static class MyConnection implements Connection{
        //封装一个Connection
        private Connection con;
        public MyConnection(Connection con){
            this.con=con;
        }
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return con.unwrap(iface);
        }
        @Override
        public void rollback() throws SQLException {
            con.rollback();
        }
        @Override
        public Statement createStatement() throws SQLException {
            return con.createStatement();
        }
        @Override
        public void setAutoCommit(boolean autoCommit) throws SQLException {
            con.setAutoCommit(autoCommit);
        }
        @Override
        public void commit() throws SQLException {
            con.commit();
        }
        ......
        //...需要把接口的所有方法都实现了,按照上面的样式去写就行,如果不用增加功能或修改的,直接返回con.方法(参数);就可以了。如果需要修改,就自己写。比如:这里我们需要修改close();方法.
        @Override
        public void close() throws SQLException {
            pool.add(this);
            //直接把自己这个对象加进去
        }
    }
}
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
JavaScript 前端开发 Java
通义灵码 Rules 库合集来了,覆盖Java、TypeScript、Python、Go、JavaScript 等
通义灵码新上的外挂 Project Rules 获得了开发者的一致好评:最小成本适配我的开发风格、相当把团队经验沉淀下来,是个很好功能……
2245 103
|
10月前
|
SQL 关系型数据库 MySQL
如何将Excel表的数据导入RDS MySQL数据库?
本文介绍如何通过数据管理服务DMS将Excel文件(转为CSV格式)导入RDS MySQL数据库,涵盖建表、编码设置、导入模式选择及审批执行流程,并提供操作示例与注意事项。
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
4007 65
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
安全 druid Java
Java 访问数据库的奇妙之旅
本文介绍了Java访问数据库的几种常见方式
408 12
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
683 7
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
SQL Java
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
297 8
|
Java BI API
Java Excel报表生成:JXLS库的高效应用
在Java应用开发中,经常需要将数据导出到Excel文件中,以便于数据的分析和共享。JXLS库是一个强大的工具,它基于Apache POI,提供了一种简单而高效的方式来生成Excel报表。本文将详细介绍JXLS库的使用方法和技巧,帮助你快速掌握Java中的Excel导出功能。
799 6
|
人工智能 监控 数据可视化
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
551 3
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
482 2

推荐镜像

更多