本系列文章仅是一名哈工大2020级菜狗完成zdc老师数据库系统实验时写下的实验记录,大部分是一些实验过程中查找博客的记录,只给出部分代码,但是希望对后来人有所帮助
相比起其他老师的数据库系统实验,zdc似乎更倾向界面和动态sql语句的编写,其他老师我了解了一下我其他专业的朋友,主要侧重SQL的练习。没有办法说好或者不好,工作量上可能是zdc老师的实验稍微大一些,但是也还可以,通过本次实验我也学会了简单使用java swing编写GUI,个人挺满意的
IDEA & Mysql环境配置
这是从零开始配置的版本
mysql8.0.25安装配置教程(windows 64位)最详细_mysql 8.0.25_聚精会神搞学习的博客-CSDN博客目录1.官网下载MySQL2.配置初始化文件my.ini3.初始化MySQL4.安装mysql服务并启动+修改密码5.配置环境变量6.部分疑难杂病7.使用连接工具连接mysql1.官网下载MySQL下载Mysql点击下载mysql.下载完成后解压到某一个文件夹(记住这个路径,一会要用到)2.配置初始化文件my.ini在根目录下创建一个txt文件,名字叫my,文件后缀为ini之后复制下面这个代码放在文件下(新解压的文件没有my.ini文件,需自行创建)以下代码除安装目录和数据的存放目录需修https://blog.csdn.net/weixin_43579015/article/details/117228159 连接数据库有可能出现时区不同的问题Server returns invalid timezone.解决方法也很简单:直接在URL后面添加?serverTimezone=UTC
Server returns invalid timezone.问题解决_何大春的博客-CSDN博客1、首先检查Test Connectin这是由于默认mysql用的时区和我国不同2、直接在URL后面添加?serverTimezone=UTC后来发现我需要的数据库还是没有在Schema中显示,原来是我自己没勾选上。记得一点要勾选上。具体可参考:链接: https://blog.csdn.net/liuqiker/article/details/102455077?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162222https://blog.csdn.net/weixin_44609958/article/details/117377342
生成数据
这一步相当于是要向java中插入mysql语句,将java变量值传入mysql语句,通过循环替换掉各个变量的值,从而利用同一条sql语句就可以生成足够多的数据
主要用到的就是sql中的statement,PreparedStatement等相关语句,?用于在sql语句中占位,确定各个属性值以后,再指定对应的占位符具体的值,下标从1开始
具体示例可参考以下博客,当然java向mysql传参也还有别的方式,大家可以再自行百度
https://www.cnblogs.com/huangjiangyang/p/16967222.htmlhttps://www.cnblogs.com/huangjiangyang/p/16967222.html 当然也可以面向chatgpt学习一些代码范例捏 AI EDU
chatgpt可比我强多了...
这里我看见了statement也可以调用close进行关闭,然后就好奇了一波这和connection的close有什么区别
关于statement.close和connection.close 备忘(上)_zwonder的博客-CSDN博客很多人都会有这个疑问。在回收数据库连接资源的时候,大家一般都用connection.close() ,那么在这个过程中其持有的statements和results是否被清理或标记为无效了呢?我们又应该用哪种方式来释放数据库资源呢?这个既和你使用数据库连接的方式有关,也和驱动有关,也就是和你的jdbc/odbc…… Driver有关。 我们来看看mysql-connector的源代码:https://blog.csdn.net/zwonder/article/details/6570851
游标使用
还是让gpt帮我写了一个代码范例,主要想学一下大概的框架语句,我改了改是可以使用的
import java.sql.*;
public class CursorExample {public static void main(String[] args) {try {Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");rs.beforeFirst();while (rs.next()) {String name = rs.getString("name");int age = rs.getInt("age");System.out.println("Name: " + name + ", Age: " + age);}rs.close();stmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}
}// 在此示例中,我们使用了ResultSet.TYPE_SCROLL_INSENSITIVE以允许游标向前和向后移动,并使用ResultSet.CONCUR_READ_ONLY指定结果集为只读。然后我们执行一个SELECT语句,并使用beforeFirst()将游标移动到第一行之前。然后我们使用next()方法逐行遍历结果集,读取每一行的“name”和“age”列,并将它们输出到控制台。最后,我们关闭了结果集、语句和连接。
一些设定参数上的博客解释
https://www.cnblogs.com/Syria/p/6295346.htmlhttps://www.cnblogs.com/Syria/p/6295346.html
界面编写
再写到这里时已经是我把实验全写完的时候了,界面我使用java swing进行编写,没有使用别的图形化工具,但我知道一些图形化工具可供使用(只是最开始不得要领然后放弃了罢了,纯用代码敲其实倒也还好,都是一些重复性的工作)
如果使用IDEA的话,图形化工具推荐JFormDesigner,破解版教程使用如下:
破解工具链接(转自其它博客JFormDesigner-7注册_jformdesigner注册码分享_Java凉凉每一天的博客-CSDN博客)
百度云链接
链接:https://pan.baidu.com/s/1DC_lUXt1pXdkHJz8k1lblA
提取码:cyj0
破解工具使用教程如下:IDEA Ui设计器JFormDesigner 永久激活插件+注册机(亲测一直在用)_java_脚本之家这篇文章主要介绍了IDEA Ui设计器JFormDesigner 永久激活----插件+注册机 自己一直在用的版本和注册机,非常不错,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下https://www.jb51.net/article/261150.htm 使用这个插件时,最好把页面布局设置为null,就可以自动调整自己想要的界面布局而不会受到固定布局的约束,具体使用教程可以自行寻找
如果希望使用代码编写的话,可以找一个范例参考学习一下,编写完一个界面,剩下的事情就是不断复制之前界面的组件代码,调整组件位置,编写对应监听器的逻辑代码使得组件可以被触发,从而实现交互
常见的套路是,一个界面对应一个JFrame(我直接在编写类时继承),可以往里边放若干个JPanel或者其他容器,JPanel里边可以放其他的组件。我粗浅的理解为JFrame是一个支架,JPanel或者其他容器是放在支架上的板子,这样组件才能被放上去
常用的改变属性的函数有setBorder(调整边框),setLayout(设置布局),setBounds(设置位置和大小,前两个参数决定位置,后两个参数决定大小),setFont(设置字体)等等
如果想要一个带滚动条的表格展示组件,可以使用JScrollPane容器,里边以DefaultTableModel为模板建立JTable
如果想要Button可以互动,可以绑定监听器addMouseListener,重写其中的代码
元数据可以获取一些模型信息,ResultSetMetaData可以获取ResultSet中的列数,还可以获取列的名字;DatabaseMetaData可以获取数据库内的表名,后边有编程任务需要用到这两个类,具体使用方法可查询其他资料,这里只给出部分代码截图
这里贴一个我的主菜单的代码供以参考(大概理解具体的逻辑就可以使用了):
// 主菜单界面代码
package Main;import ViewDataPackage.ViewData;import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Connection;
import java.sql.SQLException;
import ViewDataPackage.ViewData;
import TrySqlPackage.TrySql;
import InteractivePackage.Interactive;public class Launcher extends JFrame {// 本类用于书写主界面// 主界面上的button决定去往的功能// 外界使用APIpublic static void processing(){EventQueue.invokeLater(new Runnable() {public void run() {try {Launcher launcher = new Launcher() ;launcher.setVisible(true);} catch (Exception e) {e.printStackTrace();}}});}// 构造函数public Launcher() throws SQLException {// 设置相关属性(理论上会继承Frame的默认构造函数)setDefaultCloseOperation(EXIT_ON_CLOSE);setBounds(500,250,400,400);setTitle("SCT主菜单");// 创建panelJPanel panel = new JPanel() ;panel.setBorder(new EmptyBorder(5, 5, 5, 5));panel.setLayout(null);setContentPane(panel); // 将panel嵌入到框架里// 构造其他组件JButton ViewDataButton = new JButton("查看数据");ViewDataButton.setFont(new Font("微软雅黑",Font.PLAIN,20));ViewDataButton.setBounds(115, 50, 150, 50);ViewDataButton.setFocusPainted(false);panel.add(ViewDataButton);JButton TrySqlButton = new JButton("SQL练习");TrySqlButton.setFont(new Font("微软雅黑",Font.PLAIN,20));TrySqlButton.setBounds(115, 150, 150, 50);TrySqlButton.setFocusPainted(false);panel.add(TrySqlButton);JButton InteractiveButton = new JButton("交互式体验");InteractiveButton.setFont(new Font("微软雅黑",Font.PLAIN,20));InteractiveButton.setBounds(115, 250, 150, 50);InteractiveButton.setFocusPainted(false);panel.add(InteractiveButton);Connection conn = Connect.getConnection(); // 此处调用的是我重写的连接类// 绑定监听器ViewDataButton.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {ViewData.processing(conn);}});TrySqlButton.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {TrySql.processing(conn);}});InteractiveButton.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {Interactive.processing(conn);}});}public static void main(String[] args) {processing();}
}
再附一个查看数据界面的代码:
package ViewDataPackage;import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import Main.*;public class ViewData extends JFrame {// 本类用于展示SCT中三个表的数据public static Connection conn;public static void processing(Connection connection) {EventQueue.invokeLater(new Runnable() {public void run() {try {ViewData viewData = new ViewData(connection);viewData.setVisible(true);} catch (Exception e) {e.printStackTrace();}}});}public ViewData(Connection connection) {// 设置相关属性(理论上会继承Frame的默认构造函数)conn = connection;setDefaultCloseOperation(DISPOSE_ON_CLOSE);setBounds(500, 80, 500, 700);setTitle("查看数据");// 创建panelJPanel panel = new JPanel();panel.setBorder(new EmptyBorder(5, 5, 5, 5));panel.setLayout(null);setContentPane(panel); // 将panel嵌入到框架里// 创建组件// 流程:JLable - JButton - DefaultTableModel - JTable - JScrollPane// JLableJLabel labelStudent = new JLabel("Student");labelStudent.setFont(new Font("微软雅黑", Font.PLAIN, 14));labelStudent.setBounds(50, 25, 80, 25);panel.add(labelStudent);// JButtonJButton buttonStudent = new JButton("Load");buttonStudent.setFont(new Font("微软雅黑", Font.PLAIN, 13));buttonStudent.setBounds(350, 25, 80, 25);buttonStudent.setFocusPainted(false);panel.add(buttonStudent);// DefaultTableModelDefaultTableModel defaultTableModelStudent = new DefaultTableModel(null, new String[]{"Snum", "Sname", "Ssex", "Sage", "Sclass"});defaultTableModelStudent.setColumnCount(5);// JTableJTable jTableStudent = new JTable(defaultTableModelStudent);jTableStudent.setFont(new Font("微软雅黑", Font.PLAIN, 12));// JScrollPanelJScrollPane jScrollPaneStudent = new JScrollPane(jTableStudent);jScrollPaneStudent.setBounds(40, 60, 400, 150);panel.add(jScrollPaneStudent);// JLableJLabel labelCourse = new JLabel("Course");labelCourse.setFont(new Font("微软雅黑", Font.PLAIN, 14));labelCourse.setBounds(50, 225, 80, 25);panel.add(labelCourse);// JButtonJButton buttonCourse = new JButton("Load");buttonCourse.setFont(new Font("微软雅黑", Font.PLAIN, 13));buttonCourse.setBounds(350, 225, 80, 25);buttonCourse.setFocusPainted(false);panel.add(buttonCourse);// DefaultTableModelDefaultTableModel defaultTableModelCourse = new DefaultTableModel(null, new String[]{"Cnum", "Cname", "Credit", "Chours", "Tnum"});defaultTableModelCourse.setColumnCount(5);// JTableJTable jTableCourse = new JTable(defaultTableModelCourse);jTableCourse.setFont(new Font("微软雅黑", Font.PLAIN, 12));// JScrollPaneJScrollPane jScrollPaneCourse = new JScrollPane(jTableCourse);jScrollPaneCourse.setBounds(40, 260, 400, 150);panel.add(jScrollPaneCourse);// JLableJLabel labelSC = new JLabel("SC");labelSC.setFont(new Font("微软雅黑", Font.PLAIN, 14));labelSC.setBounds(50, 425, 80, 25);panel.add(labelSC);// JButtonJButton buttonSC = new JButton("Load");buttonSC.setFont(new Font("微软雅黑", Font.PLAIN, 13));buttonSC.setBounds(350, 425, 80, 25);buttonSC.setFocusPainted(false);panel.add(buttonSC);// DefaultTableModelDefaultTableModel defaultTableModelSC = new DefaultTableModel(null, new String[]{"Snum", "Cnum", "Score"});defaultTableModelSC.setColumnCount(3);// JTableJTable jTableSC = new JTable(defaultTableModelSC);jTableSC.setFont(new Font("微软雅黑", Font.PLAIN, 12));// JScrollPaneJScrollPane jScrollPaneSC = new JScrollPane(jTableSC);jScrollPaneSC.setBounds(40, 460, 400, 150);panel.add(jScrollPaneSC);// 绑定监听器buttonStudent.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {try {loadStudent(defaultTableModelStudent);} catch (SQLException sqlException) {// 处理异常:弹窗提示Sqlexception.process(sqlException.getMessage());}}});// 绑定监听器buttonCourse.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {try {loadCourse(defaultTableModelCourse);} catch (SQLException sqlException) {// 处理异常:弹窗提示Sqlexception.process(sqlException.getMessage());}}});// 绑定监听器buttonSC.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {try {loadSC(defaultTableModelSC);} catch (SQLException sqlException) {// 处理异常:弹窗提示Sqlexception.process(sqlException.getMessage());}}});}// 获取Student表的数据public void loadStudent(DefaultTableModel defaultTableModelStudent) throws SQLException {ArrayList<String> newrow = new ArrayList<>();String sql = "SELECT * FROM Student";Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);ResultSet resultSet = stmt.executeQuery(sql);resultSet.beforeFirst();while (resultSet.next()) {// 每次循环清空newrow.clear();for (int i = 1; i <= 5; i++) {newrow.add(resultSet.getString(i));}defaultTableModelStudent.addRow(newrow.toArray());}}// 获取Course表的数据public void loadCourse(DefaultTableModel defaultTableModelCourse) throws SQLException {ArrayList<String> newrow = new ArrayList<>();String sql = "SELECT * FROM Course";Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);ResultSet resultSet = stmt.executeQuery(sql);resultSet.beforeFirst();while (resultSet.next()) {// 每次循环清空newrow.clear();for (int i = 1; i <= 5; i++) {newrow.add(resultSet.getString(i));}defaultTableModelCourse.addRow(newrow.toArray());}}// 获取Student表的数据public void loadSC(DefaultTableModel defaultTableModelSC) throws SQLException {ArrayList<String> newrow = new ArrayList<>();String sql = "SELECT * FROM SC";Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);ResultSet resultSet = stmt.executeQuery(sql);resultSet.beforeFirst();while (resultSet.next()) {// 每次循环清空newrow.clear();for (int i = 1; i <= 3; i++) {newrow.add(resultSet.getString(i));}defaultTableModelSC.addRow(newrow.toArray());}}}
如若希望复制后可以在自己的电脑上运行,也许需要删除一些import并注释掉一些代码
最终完成整个实验后感觉还蛮有意思的,难度也还可以,很多时间花在调整界面上,逻辑代码编写并不困难