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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL---数据库从入门走向大神系列(十一)-Java获取数据库/结果集的元信息、将数据表写入excel表格

测试类:

package cn.hncu.pool2;
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('P203','关羽',30) ";
            st.execute(sql);
            sql ="insert into stud values('P204','张飞',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);
                    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('P40"+n+"','刘备"+n+"',30) ";
            st.execute(sql);
            sql ="insert into stud values('P41"+n+"','曹操"+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();//这样,我们直接调用close方法就可以了!!!
                }
            } catch (SQLException e) {
                throw new RuntimeException("第"+n+"连接关闭失败!", e);
            }
        }
    }
}

测试结果:

image.png

代理模式:

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。

好处就是:

在某些情况下,如果不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

可以为原来的方法增加或者修改动作!

代理模式一般需要3个角色:

抽象角色:声明真实对象和代理对象的共同接口(必须是接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装与包装。

真实角色(被代理的角色):代理角色所代表的真实对象,是我们最终要引用的对象。

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 续处理。

接口:

package cn.hncu.proxy.demo1;
public interface IRenter {
    public void rent(int i);
    public String say();
}

实际对象:

package cn.hncu.proxy.demo1;
public class Renter implements IRenter{
    @Override
    public void rent(int i) {
        System.out.println("给你"+i+"个房间,需要交500元!");
    }
    public String say() {
        System.out.println("Renter:你好,我是房东,房子实际只要300元");
        return "房东的返回结果...";
    }
}

代理模式的核心部分:

package cn.hncu.proxy.demo1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
    public static void main(String[] args) {
        //被代理的对象
        final IRenter r = new Renter();
        //这个obj是代理后的对象
        Object obj = Proxy.newProxyInstance(Client.class.getClassLoader(),
                new Class[]{IRenter.class},
                new InvocationHandler() {
                    @Override
                    //proxy是代理后的对象(等价于返回的obj),method就是类反射中的方法对象, args是执行method方法所需的参数
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        System.out.println("我是中介...");
                        //在这里,我们把房东说的话和返回值给拦截了。
                        if(method.getName().equals("say")){
                            System.out.println("我是中介,你还没交中介费,无法联系房东...");
                            return "";
                        }
                        Object obj = method.invoke(r, args);
                        System.out.println("欢迎再来找我中介...");
                        //r就是原来的对象
                        return obj;
                        //这个返回结果是调用r中的方法method.invoke(r, args);返回的结果
                    }
                });
        IRenter ir = (IRenter) obj;
        ir.rent(3);
        System.out.println(ir.say());
    }
}

可以看出来InvocationHandler这个接口中的invoke方法是最核心的部分!!!

在里面我们利用类加载器和类反射,直接可以来调用原来的类,而且可以加上自己需要的功能,或者实现拦截!!!

上面的例子只能实现对Renter 类的代理。

通用的代理模板类:

public interface IAnimal {
   public void run();
}
public class Dog implements IAnimal{
    private String name;
    public Dog(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println("Doge:"+name+"is 
running...");
    }
}
public interface IPerson {
   public void sayHi();
}
public class Person implements IPerson {
    private String name;
    public Person(String name){
        this.name = name;
    }
    @Override
    public void sayHi() {
        System.out.println(name+"说:祝你快乐...");
    }
}

ProxyUtil.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil implements InvocationHandler{
   private Object srcObj=null;
    public ProxyUtil(Object srcObj) {
        this.srcObj=srcObj;
    }
    public static Object getProxy(Object srcObj){
        Object obj = Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),
                srcObj.getClass().getInterfaces(),
                new ProxyUtil(srcObj)); 
        //obj是代理后的返回结果其实就是method.invoke(srcObj, args)的返回结果
        return obj;
    }
    //这个就是代理的方法了
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("进入了代理区域~~");
        //这个srcObj就是原来的对象
        return method.invoke(srcObj, args);
    }
}

client

package cn.hncu.proxy.demo2;
import cn.hncu.proxy.demo2.domain.Dog;
import cn.hncu.proxy.demo2.domain.IAnimal;
import cn.hncu.proxy.demo2.domain.IPerson;
import cn.hncu.proxy.demo2.domain.Person;
public class Client {
    public static void main(String[] args) {
        Dog dag = new Dog("旺财");
        IAnimal iDag = (IAnimal) ProxyUtil.getProxy(dag);
        iDag.run();
        Person p = new Person("小明");
        IPerson ip =(IPerson)  ProxyUtil.getProxy(p);
        ip.sayHi(); 
    }
}

输出结果:

image.png

我们现在再来把之前用装饰模式写的ConnsUtil类改写成代理模式:

ConnsUtil类的代理模式:

package cn.hncu.pool3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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>();
    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++){
                final Connection conn = DriverManager.getConnection(url, user, password);
                //只需要改这里就行了!
                //使用动态代理代理conn对象,实现对close方法的拦截
                Object obj = Proxy.newProxyInstance(
                        ConnsUtil.class.getClassLoader(),
                        conn.getClass().getInterfaces(),
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args)
                                    throws Throwable {
                                if(method.getName().equalsIgnoreCase("close") && (args==null || args.length==0)){
                                    pool.add((Connection)proxy);
                                    return null;
                                }else{
                                    return method.invoke(conn, args);
                                }
                            }
                        });
                pool.add((Connection)obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static synchronized Connection getConn() throws Exception{
        if(pool.size()<=0){
            Thread.sleep(100);
            return getConn();
        }
        return pool.remove(0);
    }
}

大家可以自己动手写一写,加深印象, Proxy.newProxyInstance(类加载器,class数组(被代理对象的接口的class数组),new InvocationHandler());

记住这个就可以了!

被代理对象的接口的class数组可以用conn.getClass().getInterfaces(),来获得。

conn为被代理的对象!

动态代理比装饰模式方便很多!

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
24天前
|
Python
使用OpenPyXL库实现Excel单元格其他对齐方式设置
本文介绍了如何使用Python的`openpyxl`库设置Excel单元格中的文本对齐方式,包括文本旋转、换行、自动调整大小和缩进等,通过具体示例代码展示了每种对齐方式的应用方法,适合需要频繁操作Excel文件的用户学习参考。
154 85
使用OpenPyXL库实现Excel单元格其他对齐方式设置
|
2天前
|
自然语言处理 Java
Java中的字符集编码入门-增补字符(转载)
本文探讨Java对Unicode的支持及其发展历程。文章详细解析了Unicode字符集的结构,包括基本多语言面(BMP)和增补字符的表示方法,以及UTF-16编码中surrogate pair的使用。同时介绍了代码点和代码单元的概念,并解释了UTF-8的编码规则及其兼容性。
75 60
|
7天前
|
NoSQL 关系型数据库 分布式数据库
基于PolarDB的图分析:通过DTS将其它数据库的数据表同步到PolarDB的图
本文介绍了使用DTS任务将数据从MySQL等数据源实时同步到PolarDB-PG的图数据库中的步骤.
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
58 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
29天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
2月前
|
数据格式 UED
记录一次NPOI库导出Excel遇到的小问题解决方案
【11月更文挑战第16天】本文记录了使用 NPOI 库导出 Excel 过程中遇到的三个主要问题及其解决方案:单元格数据格式错误、日期格式不正确以及合并单元格边框缺失。通过自定义单元格样式、设置数据格式和手动添加边框,有效解决了这些问题,提升了导出文件的质量和用户体验。
210 3
|
2月前
|
Java BI API
Java Excel报表生成:JXLS库的高效应用
在Java应用开发中,经常需要将数据导出到Excel文件中,以便于数据的分析和共享。JXLS库是一个强大的工具,它基于Apache POI,提供了一种简单而高效的方式来生成Excel报表。本文将详细介绍JXLS库的使用方法和技巧,帮助你快速掌握Java中的Excel导出功能。
73 6
|
2月前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
2月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
关系型数据库 MySQL
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
79 5