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;
目录
相关文章
|
2月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
351 7
|
3月前
|
SQL Java 关系型数据库
Java连接MySQL数据库环境设置指南
请注意,在实际部署时应该避免将敏感信息(如用户名和密码)硬编码在源码文件里面;应该使用配置文件或者环境变量等更为安全可靠地方式管理这些信息。此外,在处理大量数据时考虑使用PreparedStatement而不是Statement可以提高性能并防止SQL注入攻击;同时也要注意正确处理异常情况,并且确保所有打开过得资源都被正确关闭释放掉以防止内存泄漏等问题发生。
149 13
|
4月前
|
机器学习/深度学习 算法 数据库
基于GoogleNet深度学习网络和GEI步态能量提取的步态识别算法matlab仿真,数据库采用CASIA库
本项目基于GoogleNet深度学习网络与GEI步态能量图提取技术,实现高精度步态识别。采用CASI库训练模型,结合Inception模块多尺度特征提取与GEI图像能量整合,提升识别稳定性与准确率,适用于智能安防、身份验证等领域。
|
5月前
|
人工智能 Java 关系型数据库
Java的时间处理与Mysql的时间查询
本文总结了Java中时间与日历的常用操作,包括时间的转换、格式化、日期加减及比较,并介绍了MySQL中按天、周、月、季度和年进行时间范围查询的方法,适用于日常开发中的时间处理需求。
104 0
|
7月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
8月前
|
关系型数据库 分布式数据库 数据库
一库多能:阿里云PolarDB三大引擎、四种输出形态,覆盖企业数据库全场景
PolarDB是阿里云自研的新一代云原生数据库,提供极致弹性、高性能和海量存储。它包含三个版本:PolarDB-M(兼容MySQL)、PolarDB-PG(兼容PostgreSQL及Oracle语法)和PolarDB-X(分布式数据库)。支持公有云、专有云、DBStack及轻量版等多种形态,满足不同场景需求。2021年,PolarDB-PG与PolarDB-X开源,内核与商业版一致,推动国产数据库生态发展,同时兼容主流国产操作系统与芯片,获得权威安全认证。
|
9月前
|
数据库
【YashanDB数据库】yasboot查询数据库状态时显示数据库状态为off
yasboot查询数据库状态时显示数据库状态为off
|
10月前
|
JSON Java 关系型数据库
Hutool创建数据源工厂动态查询不同数据库不同数据表的数据
Hutool创建数据源工厂动态查询不同数据库不同数据表的数据
239 2
|
10月前
|
存储 Java 关系型数据库
java调用mysql存储过程
在 Java 中调用 MySQL 存储过程主要借助 JDBC(Java Database Connectivity)。其核心原理是通过 JDBC 与 MySQL 建立连接,调用存储过程并处理结果。具体步骤包括:加载 JDBC 驱动、建立数据库连接、创建 CallableStatement 对象、设置存储过程参数并执行调用。此过程实现了 Java 程序与 MySQL 数据库的高效交互。
|
10月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
389 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战