当前位置: 首页 > news >正文

【项目管理】DBClient

DBClient

System : Windows 10
Intellij IDEA : Ultimate 2020.3.4
Java : 1.8.0_333
MySQL : 8.0.30

Gitee 地址

链接: https://gitee.com/lijinjiang01/DBClient

1.介绍

该项目是一款使用 Java Swing 技术制作的数据库管理工具,具有简单连接数据库查看数据功能,仅做学习使用。该项目使用了一款国人开发的 LAF(LookAndFeel) beautyeye,感觉蛮好看的。

2.项目主体

2.1 关于页面

主要代码

/**
 * @ClassName AboutDialog
 * @Description 关于页面
 * @Author Li
 * @Date 2022/8/15 13:00
 * @ModifyDate 2022/8/15 13:00
 * @Version 1.0
 */
public class AboutDialog extends JDialog {
    private MainFrame mainFrame; // 主界面对象

    public AboutDialog(MainFrame mainFrame) {
        this.mainFrame = mainFrame;
        this.setSize(new Dimension(600, 400)); // 设置大小
        this.setTitle("关于"); // 设置标题
        this.setUndecorated(true); // 禁用对话框的装饰

        JPanel contentPane = new JPanel();
        contentPane.setBackground(new Color(60, 60, 60));
        contentPane.setBorder(BorderFactory.createEtchedBorder());
        contentPane.setLayout(new GridBagLayout());

        JPanel panel = new JPanel();
        panel.setBackground(new Color(60, 60, 60));
        panel.setLayout(new GridLayout(2, 1, 0, 20));
        // 上半部分 LOGO + 名称
        JPanel topPanel = new JPanel();
        topPanel.setBackground(new Color(60, 60, 60));
        topPanel.setLayout(new FlowLayout());
        JLabel logoLabel = new JLabel(new ImageIcon(ImageUtil.LOGO_IMAGE.getScaledInstance(40, 40, Image.SCALE_SMOOTH)));
        JLabel nameLabel = new JLabel("DBClient");
        nameLabel.setFont(new Font("微软雅黑", 1, 48));
        nameLabel.setForeground(Color.WHITE);
        topPanel.add(logoLabel);
        topPanel.add(nameLabel);
        // 下半部分,作者
        JPanel bottomPanel = new JPanel();
        bottomPanel.setBackground(new Color(60, 60, 60));
        JLabel authorLabel = new JLabel("Author : lijinjiang01");
        authorLabel.setFont(new Font("微软雅黑", 1, 25));
        authorLabel.setForeground(Color.WHITE);
        bottomPanel.add(authorLabel);

        panel.add(topPanel);
        panel.add(bottomPanel);
        contentPane.add(panel);

        this.setContentPane(contentPane);
        this.setAlwaysOnTop(true); // 设置永远显示在最上面
        this.addWindowFocusListener(new WindowFocusListener() {
            @Override
            public void windowGainedFocus(WindowEvent e) {

            }

            @Override
            public void windowLostFocus(WindowEvent e) {
                // 当点击 JDialog 外的地方时,则关闭 JDialog 窗口
                AboutDialog.this.dispose();
            }
        });
        this.setResizable(false); // 不可变化大小
        this.setLocationRelativeTo(this.mainFrame); // 相对主界面居中
        this.setVisible(true); // 设置可见
    }
}

效果演示

2.2 新建连接

主要代码

// 新建时的确定按钮:保存连接信息
confirmBtn.addActionListener(e -> {
    // 得到用户输入的信息,并返回一个ServerConnection
    ServerConnection sc = getCurrentSC();
    if (!dataValidate(sc)) {
        JOptionPane.showMessageDialog(SCDialog.this, "配置信息不能为空,请补充完整!", "错误", JOptionPane.ERROR_MESSAGE);
        return;
    }
    // 判断连接名是否重复
    if (this.ctx.getSC(sc.getName()) != null) {
        JOptionPane.showMessageDialog(SCDialog.this, "已存在命名为" + sc.getName() + "的连接!", "错误", JOptionPane.ERROR_MESSAGE);
        return;
    }
    // 直接保存,不需要创建任何连接
    this.ctx.addSC(sc);
    // 保存到属性文件
    this.ctx.getPropertiesHandler().saveSC(sc);
    // 刷新树节点中的连接
    this.mainFrame.getLeftPane().addSCNode(sc);
    this.dispose();
});

效果演示

2.3 连接节点右键菜单

效果演示

2.4 新建数据库

主要代码

/**
 * 创建一个数据库,并返回其排序位置的索引
 * @param dialog
 * @param database
 * @return
 */
public int createDatabase(DBDialog dialog, Database database) {
    if (database != null) {
        String name = database.getDbName();
        if (name != null && !"".equalsIgnoreCase(name)) {
            String sql = "CREATE DATABASE " + name + " DEFAULT CHARACTER SET " + database.getCharset() + " DEFAULT COLLATE " + database.getCollation();
            try {
                Statement stmt = getStatement();
                stmt.executeUpdate(sql);
                dialog.dispose();
                List<Database> dbs = getDatabases();
                for (int i = 0; i < dbs.size(); i++) {
                    if (name.equalsIgnoreCase(dbs.get(i).getDbName())) {
                        return i;
                    }
                }
                return -1;
            } catch (Exception e) {
                JOptionPane.showMessageDialog(dialog, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                return -1;
            }
        } else {
            return -1;
        }
    } else {
        return -1;
    }
}

效果演示

2.5 查询数据库中的表、视图、存储过程

主要代码

// 获取该数据库下的所有的表单
public List<Table> getTables() {
    List<Table> list = new ArrayList<>();
    // 去系统表information_schema查询
    String sql = "SELECT TABLE_NAME FROM information_schema.TABLES sc WHERE (sc.TABLE_TYPE='" + MySQLUtil.TABLE_TYPE
            + "' OR sc.TABLE_TYPE='" + MySQLUtil.SYSTEM_VIEW_TYPE + "') AND sc.TABLE_SCHEMA='" + this.dbName
            + "' ORDER BY TABLE_NAME";
    try {
        // 获得本连接下面的所有数据库
        Statement stmt = getStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            String tableName = rs.getString("TABLE_NAME");
            Table table = new Table(this, tableName);
            list.add(table);
        }
        rs.close();
        return list;
    } catch (Exception e) {
        return list;
    }
}

// 获取该数据库下的所有的视图
public List<View> getViews() {
    List<View> list = new ArrayList<>();
    // 到 information_schema 数据库中的 VIEWS 表查询
    String sql = "SELECT * FROM information_schema.VIEWS sc WHERE sc.TABLE_SCHEMA='" + this.dbName
            + "' ORDER BY TABLE_NAME";
    try {
        // 获得本连接下面的所有数据库
        Statement stmt = getStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            String viewName = rs.getString("TABLE_NAME");
            View view = new View(this, viewName);
            list.add(view);
        }
        rs.close();
        return list;
    } catch (Exception e) {
        return list;
    }
}

// 获取所有的存储过程
public List<Procedure> getProcedures() {
    List<Procedure> list = new ArrayList<>();
    // 去系统表information_schema查询
    String sql = "SELECT * FROM information_schema.Routines WHERE ROUTINE_SCHEMA='" + dbName
            + "' AND ROUTINE_TYPE='" + MySQLUtil.PROCEDURE_TYPE + "' ORDER BY ROUTINE_NAME";
    try {
        // 获得一个连接下面的所有数据库
        Statement stmt = getStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            String procedureName = rs.getString("ROUTINE_NAME");
            Procedure procedure = new Procedure(this, procedureName);
            list.add(procedure);
        }
        rs.close();
        return list;
    } catch (Exception e) {
        return list;
    }
}

效果演示

2.6 表单数据的查看

2.7 选项卡的关闭

主要代码

// 显示表单数据
public void showTableData(Table table) {
    if (table != null) {
        Database db = table.getDatabase();
        String title = table.getTableName() + "@" + db.getDbName() + "  ";
        JPanel tabComponent = new JPanel();
        tabComponent.setOpaque(false); // 设置背景透明
        tabComponent.setLayout(new BorderLayout());
        JLabel titleLabel = new JLabel(title);
        tabComponent.add(titleLabel, BorderLayout.WEST);
        JLabel closeLabel = new JLabel();
        closeLabel.setIcon(ImageUtil.CLOSE_ICON);
        tabComponent.add(closeLabel, BorderLayout.EAST);

        int count = this.getTabCount();
        for (int i = 0; i < count; i++) {
            String s = this.getTitleAt(i);
            if (s.equalsIgnoreCase(title)) {
                this.setSelectedIndex(i);
                return;
            }
        }
        TableDataPane dataPanel = new TableDataPane(table);
        this.insertTab(title, null, dataPanel, null, count); // 添加一页显示对应表单数据
        this.setTabComponentAt(count, tabComponent);
        // 关闭的图片添加监听,点击关闭
        closeLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
                    JLabel source = (JLabel) e.getSource();
                    Component parent = source.getParent();
                    RightPane.this.removeTabAt(RightPane.this.indexOfTabComponent(parent));
                }
            }

            // 鼠标移上去切换关闭图标
            @Override
            public void mouseEntered(MouseEvent e) {
                closeLabel.setIcon(ImageUtil.CLOSE_ENTERED_ICON);
            }

            // 鼠标移走,图标恢复
            @Override
            public void mouseExited(MouseEvent e) {
                closeLabel.setIcon(ImageUtil.CLOSE_ICON);
            }
        });

        this.setSelectedIndex(count); // 切换到数据显示页
    } else {
        System.out.println("表单为空!");
    }
}

效果演示

2.8 选项卡的右键功能

主要代码

// 关闭 操作
private void closeTabAction() {
    rightPane.remove(selectIndex);
}

// 关闭其它 操作
private void closeOtherTabAction() {
    if (selectIndex == 0) {
        for (int i = 1; i < tabCount; i++) {
            rightPane.removeTabAt(1);
        }
    } else if (selectIndex > 0) {
        for (int i = 1; i < selectIndex; i++) {
            rightPane.removeTabAt(1);
        }
        for (int i = selectIndex + 1; i < tabCount; i++) {
            rightPane.removeTabAt(2);
        }
    }
}

// 全部关闭 操作
private void closeAllTabAction() {
    for (int i = 1; i < tabCount; i++) {
        rightPane.removeTabAt(1);
    }
}

// 关闭右侧选项卡 操作
private void closeRightTabAction() {
    int index = selectIndex + 1;
    for (int i = index; i < tabCount; i++) {
        rightPane.removeTabAt(index);
    }
}

效果演示

2.9 查询功能实现

这里的查询功能实现不仅是查询功能,只要是正确的 SQL,增删改查都可执行,由于时间问题,只演示了查询功能
主要代码

runBtn.addActionListener(e -> {
        this.infoArea.setText(""); // 清空信息面板
        removeResultPaneTab(); // 清空选项卡
        String text = queryArea.getText();
        if (text != null && !"".equalsIgnoreCase(text)) {
            String[] sqlArray = text.split(";");
            int index = 1;
            for (String sql : sqlArray) {
                String lowerSql = sql.toLowerCase();
                if (lowerSql.startsWith("insert") || lowerSql.startsWith("delete") || lowerSql.startsWith("update")) {
                    QueryData queryData = new QueryData(db, sql); // 直接执行 sql 语句就行
                    try {
                        long startTime = System.currentTimeMillis();
                        queryData.execute();
                        long endTime = System.currentTimeMillis();
                        long time = endTime - startTime;
                        appendInfo(sql, "OK", time);
                    } catch (QueryException qe) {
                        // 出现异常
                        appendInfo(sql, qe.getMessage(), 0);
                        resultPane.setSelectedIndex(0);
                        return;
                    }
                } else if (lowerSql.startsWith("select")) {
                    try {
                        long startTime = System.currentTimeMillis();
                        DataTable dataTable = new DataTable(db, sql);
                        long endTime = System.currentTimeMillis();
                        long time = endTime - startTime;
                        appendInfo(sql, "OK", time);
                        resultPane.addTab("结果" + index, dataTable);
                        resultPane.setSelectedComponent(dataTable);
                        dataTable.setBorder(null);
                        index++;
                    } catch (QueryException qe) {
                        appendInfo(sql, qe.getMessage(), 0);
                        resultPane.setSelectedIndex(0);
                        return;
                    }
                } else {
                    appendInfo(sql, "请确认 SQL 语句是否正确", 0);
                }
            }
        }
});

效果演示

相关文章:

  • 猿创征文 |【C++】面向对象之微观部分——类的组成(中)
  • 微服务项目:尚融宝(24)(后端搭建:JWT令牌测试)
  • 第6章 MyBatis框架入门详解(2)
  • 【图像识别-指纹识别】指纹特征提取附matlab代码
  • 3道Java基础题
  • Docker 安装 MySQL、Redis、Nginx
  • 疫情宅在家,研究一下fastjson中字段智能匹配的原理
  • 【MapGIS精品教程】001:MapGIS K9完整图文安装教程
  • 指针和数组笔试题解析
  • 人脸检测5种方法
  • SparkSQL 总结(未完待续)
  • 51单片机入门——数模\模数转换
  • 【毕业设计】 单片机自动写字机器人设计与实现 - 物联网 嵌入式 stm32
  • 花边新闻获取易语言代码
  • HTML5入门(1)——HTML基础
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • Fabric架构演变之路
  • flask接收请求并推入栈
  • magento2项目上线注意事项
  • MySQL数据库运维之数据恢复
  • Python语法速览与机器学习开发环境搭建
  • Redis中的lru算法实现
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Spring核心 Bean的高级装配
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 正则学习笔记
  • Java数据解析之JSON
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 从如何停掉 Promise 链说起
  • ​一些不规范的GTID使用场景
  • ###C语言程序设计-----C语言学习(3)#
  • #微信小程序:微信小程序常见的配置传值
  • %check_box% in rails :coditions={:has_many , :through}
  • (1)(1.9) MSP (version 4.2)
  • (26)4.7 字符函数和字符串函数
  • (33)STM32——485实验笔记
  • (4)事件处理——(7)简单事件(Simple events)
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (转)shell中括号的特殊用法 linux if多条件判断
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • ./configure、make、make install 命令
  • .Family_物联网
  • .NET : 在VS2008中计算代码度量值
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本