文件中。
三、实验环境
1. 硬件环境:
2. 软件环境:JDK1.5
图2 模型-视图-控制器参考实现图
class AddActionListener implements
ActionListener {
public void actionPerformed(ActionEvent e) {
Address address;
try {
address = addressBookJFrame.getAddress();
addressBookModel.writeAddress(address);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class FirstActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Address address;
try {
address = addressBookModel.readFirst();
addressBookJFrame.setAddress(address);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
|
图3 侦听Add按钮和First按钮的侦听器例
|
四、算法描述及实验步骤
1. 算法描述(可以用类图、流程图、伪代码或源程序描述)

2. 实验步骤
l 分别为问题设计模型类、视图类和控制类
l 进行编译
l 进行测试,使用的测试用例:
输入: 预期输出:
五、调试过程
1. 编译过程
(1)、返回语句之后的语句无法执行:
return readAddress(currentPosition);
FixedLengthStringDB.getRst().absolute(length -
1);因为return语句执行完了之后,就直接返回而不会执行下面的语句。
改正:把下面的语句直接删掉,因为放在return语句之前就失去意义了。
2. 调试过程
(1)、读完最后一条语句之后无法停止读取而是读取第一条记录。这是因为读完只有一条语句之后,结果集指向的位置为rst.afterLast(),而对应的位置的行号为rst.getRow()的值为0,在直径rst.next();之后又会循环读取记录。
改正:改变readFixedLengthString(int position, String
columnName)方法中的部分代码:
原来:else {
rst.absolute(position);
rst.next();
}
改成:else {
rst.absolute(position);
str = rst.getString(1);
if (position != getLengthOfRow()) {
rst.absolute(position);
rst.next();
}
这样子改是为了判断是否已经读到最后一条记录,如果是的话,就不执行rst.next();语句,而rst.absolute(position);语句则是把指针设为原来的位置,然后再执行rst.next();因为getLengthOfRow()已经把指针放到末尾了所以要重新设位置。
(2)、读到最后一条记录,然后往回读的过程中,倒数第二条记录被隐藏掉,不能读取。原因是通过上面的修改,读取最后一条记录时,并没有执行rst.next();语句,而在readPrevious()方法中返回值为return
readAddress(currentPosition - 2);这就直接导致倒数第二条记录无法读取。
改正:在原来的基础上加上else if语句,如下所示:
if (currentPosition > 1 &&
currentPosition!=length){
return readAddress(currentPosition - 2);
}
else if(currentPosition == length)
return readAddress(currentPosition - 1);
使得读取最后一条记录时返回值为:return readAddress(currentPosition - 1);
六、实验结果
输入:往数据库增加5条记录,具体内容如下:
+--------------+------------+-----------+--------+--------+
| studentName | street | city | state | zip |
+--------------+------------+-----------+--------+--------+
| ganwenxin | zhetiaojie | nanping | fujian | 125478 |
| huangronghan | natiaojie | zhangzhou | fujian | 123547 |
| huangzhitan | natiaojie | putian | fujian | 356214 |
| liteng | natiaojie | zhangzhou | fujian | 145269 |
| xuyouliang | natiaojie | xiamen | fujian | 123654 |
+--------------+------------+-----------+--------+--------+
在界面中进行查找:
点First按钮:

点Next按钮:

点Last按钮:

点Previous按钮:

增加操作:加入一条记录,xuqihong zhetiaojie quanzhou fujian 125478
这是数据库就多出一条记录:

在界面上也可以找到记录:

结果分析:结果正确
七、总结
通过这次上机实验,我主要学到以下内容:
(1)、使用MVC的设计模式,同个这种设计模式,把视图层,模式层,控制层分开了,能够更清晰的进行设计,并且带来良好的扩展性。
(2)、巩固了GUI的知识,并且对GUI的相关应用更加熟悉,比如说三种常用的布局管理器,如何把组件添加到容器中,并设置组件的属性等。
(3)、掌握了对事件的处理,如何给按钮添加事件。
(4)、在这次实验中,实验涉及的范围很广,设计的灵活性也较高,特别是将数据库与界面之间进行关联,通过各种方法来传递值,在这次实验中,更重要的是获得程序设计上的经验。
这次实验,还存在很清晰,特别是数据库方面的内容,比如说程序中ResultSet这个类,以下几点不足:
(1)、逻辑不是类里面的方法很多,但是要通过选择这些适合的方法来进行设计却不容易,很容易出现BUG。
(2)、对知识的综合应用的能力还欠缺,设计的时候经常拆东墙补西墙,一个BUG修护好了,又有新的问题出现。
附录:
package com.john.project5;
public class Address {
// Specify the size of five string fields in the record
final static int NAME_SIZE = 32;
final static int STREET_SIZE = 32;
final static int CITY_SIZE = 12;
final static int STATE_SIZE = 5;
final static int ZIP_SIZE = 5;
final static int RECORD_SIZE =
(NAME_SIZE + STREET_SIZE + CITY_SIZE + STATE_SIZE +
ZIP_SIZE);
private String name;
private String street;
private String city;
private String state;
private String zip;
public Address() {
this("","", "", "", "");
}
public Address(String name, String street, String city,
String state, String zip) {
this.setName(name);
this.setStreet(street);
this.setCity(city);
this.setState(state);
this.setZip(zip);
}
public String getName() {
return name;
}
public void setName(String name) {
name = name.trim();
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getFullAddress() {
return street + '' + city + ", " + state + ' ' + zip + '';
}
}
package com.john.project5;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.io.IOException;
import java.sql.SQLException;
public class AddressBookJFrame extends JFrame{
//存储的默认情况下为e:ew_raf.sql
private AddressBookModelRAF abm = new AddressBookModelRAF();
private Address address = new Address();
//类属性 5个文本框 + 5个按钮
//创建文本框,用于显示Name\Sreeet\City\State\Zip
private JTextField jtfName = new
JTextField(Address.NAME_SIZE);
private JTextField jtfStreet = new
JTextField(Address.STREET_SIZE);
private JTextField jtfCity = new
JTextField(Address.CITY_SIZE);
private JTextField jtfState = new
JTextField(Address.STATE_SIZE);
private JTextField jtfZip = new JTextField(Address.ZIP_SIZE);
//创建按钮
private JButton jbtAdd = new JButton("Add");
private JButton jbtFirst = new JButton("First");
private JButton jbtNext = new JButton("Next");
private JButton jbtPrevious = new JButton("Previous");
private JButton jbtLast = new JButton("Last");
//类方法
//构造方法
public AddressBookJFrame(){
//初始化数据库连接
FixedLengthStringDB db = new FixedLengthStringDB();
System.out.println(" *****数据库连接成功***** ");
//调用事件侦听器的函数,使按钮产生相应事件
add_All_ActionListener();
System.out.println("*****添加事件侦听器成功*****");
//调用initComponents方法,使容器用户界面可以显示
initComponents();
System.out.println(" ****用户界面加载成功**** ");
}
//用于设计应用程序的窗口界面
private void initComponents(){
//生成Zip模块
JPanel zip = new JPanel();
zip.add(new JLabel("Zip"),new BorderLayout().WEST);
zip.add(jtfZip,new BorderLayout().CENTER);
//生成State模块
JPanel state = new JPanel();
state.add(new JLabel("State"),new BorderLayout().WEST);
state.add(jtfState,new BorderLayout().CENTER);
JPanel z_s = new JPanel();
z_s.add(state,new BorderLayout().WEST);
z_s.add(zip,new BorderLayout().CENTER);
JPanel city = new JPanel();
city.add(new JLabel("City "),new BorderLayout().WEST);
city.add(jtfCity,new BorderLayout().CENTER);
JPanel z_s_City = new JPanel();
z_s_City.add(city,new BorderLayout().CENTER);
z_s_City.add(z_s,new BorderLayout().EAST);
JPanel street = new JPanel();
street.add(new JLabel("Street"),new BorderLayout().WEST);
street.add(jtfStreet,new BorderLayout().CENTER);
JPanel name = new JPanel();
name.add(new JLabel("Name"),new BorderLayout().EAST);
name.add(jtfName,new BorderLayout().CENTER);
JPanel show_Panel = new JPanel(new GridLayout(3,1,0,0));
show_Panel.add(name);
show_Panel.add(street);
show_Panel.add(z_s_City);
//
show_Panel.setBorder(new BevelBorder(BevelBorder.RAISED));
JPanel control_Panel = new JPanel();
control_Panel.add(jbtAdd);
control_Panel.add(jbtFirst);
control_Panel.add(jbtNext);
control_Panel.add(jbtPrevious);
control_Panel.add(jbtLast);
JPanel window = new JPanel();
window.add(show_Panel,new BorderLayout().CENTER);
window.add(control_Panel,new BorderLayout().SOUTH);
//添加部件window,使之可以在程序运行后显示在窗口中
add(window);
}
public void setAddress(Address address){
jtfName.setText(address.getName());
jtfStreet.setText(address.getStreet());
jtfCity.setText(address.getCity());
jtfState.setText(address.getState());
jtfZip.setText(address.getZip());
}
public void getAddress(){
//把文本框的值以字符串的形式传递到Address类中相应的属性
address.setName(jtfName.getText());
address.setStreet(jtfStreet.getText());
address.setCity(jtfCity.getText());
address.setState(jtfState.getText());
address.setZip(jtfZip.getText());
// return address;
}
//创建5个按钮的侦听器,使单击按钮时产生相应的事件
public void add_All_ActionListener(){
//Add按钮
jbtAdd.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
getAddress();
abm.writeAddress(address);
Address newAddress = new Address();
setAddress(newAddress);
} catch (SQLException e2) {
e2.printStackTrace();
}
};
});
//First按钮
jbtFirst.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readFirst();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Next按钮
jbtNext.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readNext();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Previous按钮
jbtPrevious.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readPrevious();
setAddress(address);
} catch (SQLException e1) {
e1.printStackTrace();
}
};
});
//Last按钮
jbtLast.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
address = abm.readLast();
setAddress(address);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
};
});
}
//定义主函数,在主函数中通过创建对象来调用构造函数,使窗体添加
public static void main(String[] args) {
AddressBookJFrame frame = new AddressBookJFrame();
frame.setLocation(200, 150);
frame.setSize(500, 250);
frame.setTitle("Address Book Input Frame");
frame.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
package com.john.project5;
public abstract class AddressBookModel {
public abstract void writeAddress(Address address) throws Exception
;
public abstract Address readFirst() throws Exception ;
public abstract Address readNext() throws Exception ;
public abstract Address readPrevious() throws Exception;
public abstract Address readLast() throws Exception;
}
package com.john.project5;
import java.io.*;
import java.sql.SQLException;
import javax.swing.JOptionPane;
public class AddressBookModelRAF extends AddressBookModel{
public AddressBookModelRAF() {
}
public void writeAddress(Address address) throws SQLException
{
FixedLengthStringDB.writeFixedLengthString(FixedLengthStringDB.toString(address));
}
public Address readFirst() throws SQLException {
return readAddress(0);
}
public Address readNext() throws SQLException {
int currentPosition = FixedLengthStringDB.getRst().getRow();
FixedLengthStringDB.getRst().last();
int length = FixedLengthStringDB.getRst().getRow();
if (currentPosition <= length)
return readAddress(currentPosition);
else{
JOptionPane.showMessageDialog(null,"已经是最后一条记录!");
return readAddress(currentPosition - 1);
}
}
public Address readPrevious() throws SQLException {
int currentPosition = FixedLengthStringDB.getRst().getRow();
int length = FixedLengthStringDB.getLengthOfRow();
FixedLengthStringDB.getRst().absolute(currentPosition);
if (currentPosition > 1 &&
currentPosition!=length){
return readAddress(currentPosition - 2);
}
else if(currentPosition == length)
return readAddress(currentPosition - 1);
else{
JOptionPane.showMessageDialog(null,"已经是第一条记录!");
return readAddress(0);
}
}
public Address readLast() throws SQLException {
FixedLengthStringDB.getRst().last();
int lastPosition = FixedLengthStringDB.getRst().getRow();
return readAddress(lastPosition);
}
private Address readAddress(int position) throws
SQLException{
// int length = FixedLengthStringDB.getLengthOfRow();
if ( position >=0 ) {
String name = FixedLengthStringDB.readFixedLengthString(
position,"studentName");
String street = FixedLengthStringDB.readFixedLengthString(
position,"street");
String city = FixedLengthStringDB.readFixedLengthString(
position,"city");
String state = FixedLengthStringDB.readFixedLengthString(
position,"state");
String zip = FixedLengthStringDB.readFixedLengthString(
position,"zip");
return new Address(name, street, city, state, zip);
} else {
return null;
}
}
}
package com.john.project5;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.*;
import javax.sound.midi.SysexMessage;
import javax.swing.JOptionPane;
public class FixedLengthStringDB {
//定义类属性
private static Connection conn;
private static Statement stmt;
private static ResultSet rst;
private static String driverName = new
String("com.mysql.jdbc.Driver");
private static String url = new
String("jdbc:mysql://localhost/addressBook");
private static String user = new String("john");
private static String password = new String("john");
//定义类方法
//定义构造函数,用于加载数据库
public FixedLengthStringDB() {
initalizeDB();
}
public static ResultSet getRst() {
return rst;
}
private static void initalizeDB() {
try {
//加载驱动
Class.forName(driverName);
System.out.println("驱动器已加载...");
} catch (ClassNotFoundException e) {
System.out.println("驱动器无法加载,请检查驱动路径是否正确!");
System.out.println(e.getMessage());
}
try {
//建立连接
conn = DriverManager.getConnection(url, user, password);
System.out.println("MySQL连接已建立...");
} catch (SQLException e) {
System.out.println("MySql连接无法建立,请检查连接路径是否正确!");
System.out.println(e.getMessage());
}
try {
//创建Statement
stmt = conn.createStatement();
System.out.println("Statement创建完毕!");
} catch (SQLException e) {
System.out.println("创建Statement的时候出现异常!");
System.out.println(e.getMessage());
}
try {
rst = stmt.executeQuery("select * from Address;");
System.out.println("ResultSet初始化完毕!");
} catch (SQLException e) {
System.out.println("ResultSet初始化异常!");
System.out.println(e.getMessage());
}
}
public static String readFixedLengthString(int position, String
columnName)
throws SQLException {
String queryString = "Select " + columnName + " From Address
;";
rst = stmt.executeQuery(queryString);
String str = new String("");
if (position == 0) {
rst.first();
str = rst.getString(1);
rst.next();
} else {
rst.absolute(position);
str = rst.getString(1);
if (position != getLengthOfRow()) {
rst.absolute(position);
rst.next();
}
}
return new String(str);
}
public static String toString(Address address) {
String value = new String("");
value += "('" + address.getName() + "','"
+ address.getStreet() + "','" + address.getCity() + "','"
+ address.getState() + "','" + address.getZip() + "')";
String column = new String("");
column += "(studentName,street,city,state,zip)";
String updateString = "insert into Address" + column + " values
"
+ value + ";";
return new String(updateString);
}
public static void writeFixedLengthString(String
updateString)
throws SQLException {
System.out.println("语句没语法问题!");
try {
stmt.executeUpdate(updateString);
System.out.println("执行语句没有问题!");
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "无法实现添加功能,请检查Name是否重复!");
System.out.println(e.getMessage());
System.exit(0);
}
}
public static int getLengthOfRow() throws SQLException {
getRst().last();
return rst.getRow();
}
}