# DBClient **Repository Path**: lijinjiang01/DBClient ## Basic Information - **Project Name**: DBClient - **Description**: 制作一款自己的数据库数据库管理工具 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 9 - **Created**: 2022-08-10 - **Last Updated**: 2025-05-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DBClient ![Java](https://img.shields.io/badge/Java-8-blue.svg) ![IDE](https://img.shields.io/badge/IDE-IntelliJ%20IDEA-brightgreen.svg) ![License](https://img.shields.io/badge/License-Apache2-orange.svg) > 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 关于页面 主要代码 ```java /** * @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); // 设置可见 } } ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/pic01.png) ### 2.2 新建连接 主要代码 ```java // 新建时的确定按钮:保存连接信息 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(); }); ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif02.gif) ### 2.3 连接节点右键菜单 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif03.gif) ### 2.4 新建数据库 主要代码 ```java /** * 创建一个数据库,并返回其排序位置的索引 * @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 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; } } ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif04.gif) ### 2.5 查询数据库中的表、视图、存储过程 主要代码 ```java // 获取该数据库下的所有的表单 public List getTables() { List
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 getViews() { List 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 getProcedures() { List 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; } } ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif05.gif) ### 2.6 表单数据的查看 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif06.gif) ### 2.7 选项卡的关闭 主要代码 ```java // 显示表单数据 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("表单为空!"); } } ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif07.gif) ### 2.8 选项卡的右键功能 主要代码 ```java // 关闭 操作 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); } } ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif08.gif) ### 2.9 查询功能实现 这里的查询功能实现不仅是查询功能,只要是正确的 SQL,增删改查都可执行,由于时间问题,只演示了查询功能 主要代码 ```java 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); } } } }); ``` 效果演示 ![](https://gitee.com/lijinjiang01/DBClient/raw/master/screenshot/gif09.gif)