一、实验目的及要求
(1)实验目的:掌握Java Swing窗口、常用组件和布局,熟悉MVC结构的概念和特点,掌握事件处理机制,通过事件处理程序将GUI与后台数据库连接,完成学生成绩的查询、修改、删除、退出功能。
(2)实验要求:管理系统采用MVC结构,实验前对可能出现的数据库连接、事件响应等问题预先分析,确定调试步骤和测试方法,编写源程序,实现可行的应用程序,尽可能考虑程序的健壮性,对实验中出现的问题进行分析、总结。
二、实验环境(工具、配置等)
1.硬件要求:计算机一台。
2.软件要求:Windows操作系统,使用Java语言,集成开发环境建议使用如Eclipse。
三、实验内容(实验方案、实验步骤、设计思路等)
1.实验方案:实验中,设计一个UI功能操作界面,通过界面输入功能输入n条学生的成绩,每条记录由学号、姓名和分数组成,然后编写事件处理程序完成下列操作:查询功能:实现学生成绩查询功能;修改功能:实现学生成绩修改功能;删除功能:实现学生成绩删除功能;退出功能等,完成实验报告。
2.实验步骤:根据教材和老师课堂的讲解。
1)设计两个类 Demo类和SqlConnect类
2)Demo类中进行窗口、按钮、文本框、标签的添加和组合,并且为五个按钮添加指定的动作侦听器,以接收发每个按钮的动作事件。
3)SqlConnect类中对数据库进行链接,创建了五个函数,用来插入学号,姓名,成绩、查询姓名,成绩、修改成绩、删除一条记录。
3.设计思路:
首先在SqlConnect类中加载驱动和数据库建立链接,然后创建五个函数,insert()函数中通过链接创建一个sql命令发送器PreparedStatement,设置参数,使用sql命令发送器向数据库发送sql命令,执行预处理插入语句,插入成功输出insert successfully!;findSname()函数中,通过链接创建一个sql命令发送器PreparedStatement,设置参数,使用sql命令发送器向数据库发送sql命令,执行预处理查询姓名语句,并将一开始初始值为” ”的name赋值为查询到的sno的值,返回name;findSgrade()函数中和findSname()函数不一样的是sql命令是查询成绩,将成绩grade赋值为查询到的sgrade的值,返回grade;changeSgrade()函数是发送的命令是update命令,对指定的sno更改sgrade;delete()函数就是发送的是delete语句,删除指定sno的那一行的记录,删除成功后输出delete succeessfully!。然后在Demo类中new一个SqlConnect类的对象sql,然后创建底层容器jf,接着创建了五个按钮、四个文本框、四个标签,并添加到了容器上,进行了一定的排列和设计,然后为插入按钮添加监视器,将前三个文本框的内容都传入insert()函数;为查询按钮添加监视器,将文本框1获得的学号信息传入findSname()和findSgrade()函数,将返回来的信息填入文本框2和3,如果findSname()函数的返回值仍是name初始值” ”,则意味着没有查询到,弹出提示框显示查不到;为修改按钮添加监视器,获取文本框1和4的学号和修改后的成绩的信息,传入changeSgrade()函数,然后清空文本框4的内容,此时重新点击查询就可以看见更改后的内容了;为删除按钮添加监视器,获取文本框1的学号信息,然后传入delete()函数,删除这一条记录;最后为退出按钮添加监视器,jf调用dispose()函数,关闭窗体,释放资源。
图4-1 数据库原始表
图4-2 运行初始界面
图4-3 插入数据
图4-4 查询前
图4-5 查询后
图4-6 修改成绩前
图4-7修改成绩后查询
图4-8 删除数据
图4-9 删除后查询
图4-10 退出界面
实验分析:
1.实验遇到的问题:
1)jl4.setBounds(380,70,60,50)语句不起作用,在容器上的位置不按照设定的位置进行排列,花费大量时间进行排列仍不起效果。
2)报错:Statement.executeQuery() cannot issue statements that do not produce result sets.
2.问题解决的方法:
1)原因是忘记设置jf.setLayout(null),把容器的布局设置为null布局,然后组件调用setBounds(int a,int b,int width,int height)函数设置本身大小和在容器中的位置。
2)update语句对应于executeUpdate 方法,而我的代码里调用到了executeQuery方法。
修改调用的方法即可,并且返回int,所以新增int rs1。
Demo类:
package shiyanbaogao_qi;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
SqlConnect sql=new SqlConnect();
//创建的底层窗口
JFrame jf=new JFrame("学生成绩管理系统");
jf.setBounds(200,200,500,300);
//创建按钮
//查询、修改、删除、退出
JButton jb1=new JButton("查询");
jb1.setBounds(20,10,100,50);
JButton jb2=new JButton("修改");
jb2.setBounds(130,10,100,50);
JButton jb3=new JButton("删除");
jb3.setBounds(240,10,100,50);
JButton jb4=new JButton("退出");
jb4.setBounds(350,10,100,50);
//插入
JButton jb=new JButton("插入");
jb.setBounds(190,190,100,50);
//创建文本框
//查询、修改、删除、退出
JTextField jt1=new JTextField();
jt1.setBounds(20,130,100,50);
JTextField jt2=new JTextField();
jt2.setBounds(130,130,100,50);
JTextField jt3=new JTextField();
jt3.setBounds(240,130,100,50);
JTextField jt4=new JTextField();
jt4.setBounds(350,130,100,50);
//创建标签
//查询、修改、删除、退出
JLabel jl1=new JLabel("学号");
jl1.setBounds(50,70,60,50);
JLabel jl2=new JLabel("姓名");
jl2.setBounds(160,70,60,50);
JLabel jl3=new JLabel("成绩");
jl3.setBounds(270,70,60,50);
JLabel jl4=new JLabel("成绩1");
jl4.setBounds(380,70,60,50);
//将按钮 文本框 标签 添加到容器上
jf.add(jb1);
jf.add(jb2);
jf.add(jb3);
jf.add(jb4);
jf.add(jb);
jf.add(jt1);
jf.add(jt2);
jf.add(jt3);
jf.add(jt4);
jf.add(jl1);
jf.add(jl2);
jf.add(jl3);
jf.add(jl4);
// 居中
jf.setLocationRelativeTo(null);
//关闭退出程序
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置用户界面上的屏幕组件的格式布局
jf.setLayout(null);
//设置为 可见
jf.setVisible(true);
//插入按钮 监视器
jb.addActionListener(new ActionListener() {
//重写接口中的方法作为事件处理
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//获取 学号 姓名 成绩 的信息
String s1=jt1.getText();
String s2=jt2.getText();
String s3=jt3.getText();
//调用insert()函数插入信息
sql.insert(s1, s2, s3);
}
});
//查询按钮 监视器
jb1.addActionListener(new ActionListener(){
//重写接口中的方法作为事件处理
public void actionPerformed(ActionEvent e) {
//获取文本框1 学号的信息
String s1=jt1.getText();
//将 返回回来的name和grade打印到文本框2 和 文本框3
jt2.setText(sql.findSname(s1));
jt3.setText(sql.findSgrade(s1));
//如果findSname(s1)返回值是函数里的name的初始值" ",则说明没有查询到name
//弹出提示框 显示 数据查不到
if(sql.findSname(s1)==" ") {
JOptionPane.showMessageDialog(null, "查询不到此数据,请重新输入");
}
}
});
//修改按钮 监视器
jb2.addActionListener(new ActionListener() {
//重写接口中的方法作为事件处理
public void actionPerformed(ActionEvent e) {
//获取 文本框1和文本框4中的数据
// 即获取到了 学号 和 更改后的成绩
String s1=jt1.getText();
String s2=jt4.getText();
//调用函数changeSgrade()
sql.changeSgrade(s1, s2);
//执行完修改操作后 将文本框4的值清空
jt4.setText("");//此时点击查询按钮可以看见更改后的数据
}
});
//删除按钮 监视器
jb3.addActionListener(new ActionListener(){
//重写接口中的方法作为事件处理
public void actionPerformed(ActionEvent e) {
//获取文本框1的数据 即学号信息
String s1=jt1.getText();
//调用delete函数 删掉学号为s1时的这一条记录
sql.delete(s1);
}
});
//退出按钮 监视器
jb4.addActionListener(new ActionListener() {
//重写接口中的方法作为事件处理
public void actionPerformed(ActionEvent e) {
//直接弹出提示框 提示确定是否要退出
JOptionPane.showMessageDialog(null, "确定退出?");
//关闭窗体,释放资源
jf.dispose();
}
});
}
}
SqlConnect类:
package shiyanbaogao_qi;
import java.lang.invoke.StringConcatFactory;
import java.sql.*;
public class SqlConnect {
Connection con=null;
Statement sql;
PreparedStatement sql1;
ResultSet rs;//用于select语句的返回值
int rs1;//用于update delete语句的返回值
SqlConnect() {
//加载驱动
String driverName="com.mysql.cj.jdbc.Driver";
try {
Class.forName(driverName);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//和数据库建立连接 ip port deptnme
String url="jdbc:mysql://localhost:3306/studentgrade?characterEncoding=utf-8";
String user="root";
String password="000000";
try {
con=DriverManager.getConnection(url,user,password);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//插入 学号 姓名 学号 的函数
public void insert(String s1,String s2,String s3) {
try {
//通过链接创建一个sql命令发送器PreparedStatement
sql1=con.prepareStatement("insert into info values(?,?,?)");
sql1.setString(1, s1);
sql1.setString(2, s2);
sql1.setString(3, s3);
//使用sql命令发送器向数据库发送sql命令
//这里用的时rs1,因为executeUpdate返回值是int类型
rs1=sql1.executeUpdate(); //执行预处理语句
System.out.println("insert successfully!");
}
catch(SQLException e) {
System.out.println(e);
}
}
//查询 姓名 的函数
public String findSname(String s) {
// 设置初始值 用来确定返回值是否有内容 若无 会弹出提示框
String name=" ";
try {
//设置sql语句中的where语句后面的内容
//where number=s;
//通过链接创建一个sql命令发送器PreparedStatement
sql1=con.prepareStatement("select * from info where sno=?");
sql1.setString(1, s);//设置参数
//使用sql命令发送器向数据库发送sql命令
rs=sql1.executeQuery();//执行预处理语句
//处理结果
while(rs.next()) {
//name赋值为mess表中的第二列的sname的一个值
name=rs.getString(2);
}
}
catch(SQLException e) {
System.out.println(e);
}
//返回name
return name;
}
//查询 成绩 的函数
public String findSgrade(String s) {
// 设置初始值 用来确定返回值是否有内容
//但是 这个为空不设置 弹出提示框 因为已经利用findSname()函数已经设置这样的功能
String grade=" ";
try {
//设置sql语句中的where语句后面的内容
//where number=s;
//通过链接创建一个sql命令发送器PreparedStatement
sql1=con.prepareStatement("select * from info where sno=?");
sql1.setString(1, s);
//使用sql命令发送器向数据库发送sql命令
rs=sql1.executeQuery(); //执行预处理语句
//处理结果
while(rs.next()) {
//name赋值为mess表中的第三列的sgrade的一个值
grade=rs.getString(3);
}
}
catch(SQLException e) {
System.out.println(e);
}
//返回grade
return grade;
}
//修改 成绩 的函数
public void changeSgrade(String s1,String s2) {
try {
//设置sql语句中的where语句后面的内容
//where number=s1;
//设置sql语句中的set语句后面的内容
//set grade=s2;
//通过链接创建一个sql命令发送器PreparedStatement
sql1=con.prepareStatement("update info set sgrade=? where sno=?");
sql1.setString(1, s2);
sql1.setString(2, s1);
//使用sql命令发送器向数据库发送sql命令
//这里用的时rs1,因为executeUpdate返回值是int类型
rs1=sql1.executeUpdate(); //执行预处理语句
}
catch(SQLException e) {
System.out.println(e);
}
}
//删除 一条记录 的函数
public void delete(String s) {
try {
//设置sql语句中的where语句后面的内容
//where number=s;
//通过链接创建一个sql命令发送器PreparedStatement
sql1=con.prepareStatement("delete from info where sno=?");
sql1.setString(1, s);
//使用sql命令发送器向数据库发送sql命令
//这里用的时rs1,因为executeUpdate返回值是int类型
rs1=sql1.executeUpdate(); //执行预处理语句
System.out.println("delete succeessfully!");//打印语句用来显示删除成功
}
catch(SQLException e) {
System.out.println(e);
}
}
}