• 【项目管理】DBClient


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

    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); // 设置可见
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    效果演示

    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();
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    效果演示

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    效果演示

    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    效果演示

    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("表单为空!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    效果演示

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    效果演示

    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);
                    }
                }
            }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    效果演示

    3.源码地址

    Gitee:https://gitee.com/lijinjiang01/DBClient

  • 相关阅读:
    衍射:经典波动行为
    三面面试官:运行 npm run xxx 的时候发生了什么?
    源码分享-M3U8数据流ts的AES-128解密并合并---GoLang实现
    手写堆与堆的常见操作
    通过SpringBoot+Vue+ElementUI+EasyExcel实现文件的导入导出
    RabbitMQ 集群 - 普通集群、镜像集群、仲裁队列
    SpringMvc-HttpMessageConverter接口
    golang学习笔记01——基本数据类型
    Qt_线程(待完善)
    算法记录|笔试中遇到的题
  • 原文地址:https://blog.csdn.net/qq_35132089/article/details/126775353