每次有人插入或更新数据库时,我都在尝试实现 jtable 模型刷新。
当一些用户试图向表中插入一些东西时,它应该通知连接到服务器的其他用户数据库发生了变化,并基于该设置的新 jtable 模型。
这里是更多上下文的一些代码:
客户处理程序:
public class ClientHandler implements Runnable {
private static ArrayList<ClientHandler> listOfUsers = new ArrayList<>();
private Socket socket;
private DataInputStream in;
private DataOutputStream out;
private static Account account;
public ClientHandler(Socket socket) {
try {
this.socket = socket;
this.in = new DataInputStream(socket.getInputStream());
this.out = new DataOutputStream(socket.getOutputStream());
this.account = CurrentAccount.getInstance(null).getAccount();
listOfUsers.add(this);
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
@Override
public void run() {
String dbChange;
while (!socket.isClosed()) {
try {
dbChange = in.readUTF();
if (dbChange.equals("Change on table!")) {
out.writeUTF(dbChange);
}
notifyAllUsers(dbChange);
} catch (IOException ex) {
close(socket, in, out);
break;
}
}
}
private void notifyAllUsers(String change) {
try {
for (ClientHandler user : listOfUsers) {
if (user.account.getAccountId() != user.account.getAccountId()) {
user.out.writeUTF(change);
}
}
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
}
}
private void close(Socket socket, DataInputStream in, DataOutputStream out) {
removeUser();
try {
if (socket != null) {
socket.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
private void removeUser() {
System.out.println(listOfUsers.remove(this));
}
}
登录服务:
public class LoginService implements Observer {
private LoginGUI loginGUI;
private LoginHandler loginHandler;
private final AccountContract acc;
public LoginService(LoginGUI loginGUI, LoginHandler loginHandler) {
this.loginGUI = loginGUI;
this.loginHandler = loginHandler;
this.acc = new AccountAccess();
loginGUI.setVisible(true);
}
@Override
public void performAction(String usernameEmail, String password) {
login(usernameEmail, password);
}
private void login(String usernameEmail, String password) {
if (loginHandler.handle(usernameEmail, password)) {
try {
Account account = acc.getAccount(usernameEmail);
switch (CurrentAccount.getInstance(account).getAccount().getAccountType()) {
case 'A' -> {
try {
Socket socket = new Socket("localhost", 7007);
AdminGUI adminGUI = new AdminGUI();
if (account.getAccountId() != 1) {
adminGUI.getControl_Tabbed_().setEnabledAt(3, false);
}
AdminService adminService = new AdminService(adminGUI, socket);
adminService.initAdmin();
adminService.listenForChanges();
loginGUI.dispose();
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
case 'I' -> {
InstructorGUI instructorGUI = new InstructorGUI();
InstructorService instructorService = new InstructorService(instructorGUI);
instructorService.initInstructor();
loginGUI.dispose();
}
case 'S' -> {
StudentGUI studentGUI = new StudentGUI();
StudentService studentService = new StudentService(studentGUI);
studentService.initStudent();
loginGUI.dispose();
}
}
JOptionPane.showMessageDialog(null, "You have successfully logged in!", "Login successful!", JOptionPane.INFORMATION_MESSAGE);
} catch (SQLException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
}
}
行政服务:
public class AdminService {
private AdminGUI adminGUI;
private AdminFacade adminFacade;
private Socket socket;
private DataInputStream in;
private DataOutputStream out;
public AdminService(AdminGUI adminGUI, Socket socket) {
this.adminGUI = adminGUI;
this.adminFacade = new AdminFacade();
try {
this.socket = socket;
this.in = new DataInputStream(socket.getInputStream());
this.out = new DataOutputStream(socket.getOutputStream());
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
fillStudentCombobox();
allAdminTableModel();
adminTableModel();
instructorTableModel();
studentTableModel();
adminGUI.setVisible(true);
}
public void initAdmin() {
adminGUI.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent windowEvent) {
int choice = JOptionPane.showConfirmDialog(null, "Are you sure you want to leave?\nYou will be logged out!", "Check!", JOptionPane.YES_NO_OPTION);
if (choice == 1 || choice == -1) {
adminGUI.setDefaultCloseOperation(AdminGUI.DO_NOTHING_ON_CLOSE);
return;
}
CurrentAccount.getInstance(null).logoutAccount();
close(socket, in, out);
Main.go();
adminGUI.dispose();
adminGUI.setDefaultCloseOperation(AdminGUI.DO_NOTHING_ON_CLOSE);
}
});
adminGUI.getAdd_Admin_Button_().addActionListener(e -> addAdmin());
adminGUI.getAdd_Instructor_Button_().addActionListener(e -> addInstructor());
adminGUI.getAdd_Student_Button_().addActionListener(e -> addStudent());
adminGUI.getEdit_Admin_Button_().addActionListener(e -> editAdmin());
adminGUI.getDelete_Admin_Button_().addActionListener(e -> deleteAdmin());
/*
adminGUI.getEdit_Instructor_Button_().addActionListener(e -> editInstructor());
adminGUI.getDelete_Instructor_Button_().addActionListener(e -> deleteInstructor());
adminGUI.getEdit_Student_Button_().addActionListener(e -> editStudent());
adminGUI.getDelete_Student_Button_().addActionListener(e -> deleteStudent());
adminGUI.getEdit_Admin_Button_().addActionListener(e -> godAdminEdit());
adminGUI.getDelete_Admin_Button_().addActionListener(e -> godAdminDelete());
*/
}
private void addAdmin() {
String username = adminGUI.getAdmin_Username_Field_().getText();
String password = adminGUI.getAdmin_Password_Field_().getText();
String firstName = adminGUI.getAdmin_First_Name_Field_().getText();
String lastName = adminGUI.getAdmin_Last_Name_Field_().getText();
String email = adminGUI.getAdmin_Email_Field_().getText();
String phoneNumer = adminGUI.getAdmin_Phone_Number_Field_().getText();
if (adminFacade.adminCheck(username, password, firstName, lastName, email, phoneNumer)) {
JOptionPane.showMessageDialog(null, "New admin was added!", "Info!", JOptionPane.INFORMATION_MESSAGE);
adminGUI.getAdmin_First_Name_Field_().setText(null);
adminGUI.getAdmin_Last_Name_Field_().setText(null);
adminGUI.getAdmin_Phone_Number_Field_().setText(null);
adminGUI.getAdmin_Email_Field_().setText(null);
adminGUI.getAdmin_Username_Field_().setText(null);
adminGUI.getAdmin_Password_Field_().setText(null);
}
}
private void addInstructor() {
String email = adminGUI.getInstructor_Email_Field_().getText();
String password = adminGUI.getInstructor_Password_Field_().getText();
String firstName = adminGUI.getInstructor_First_Name_Field_().getText();
String lastName = adminGUI.getInstructor_Last_Name_Field_().getText();
String initials = adminGUI.getInstructor_Initials_Field_().getText();
String phoneNumber = adminGUI.getInstructor_Phone_Number_Field_().getText();
boolean male = adminGUI.getInstructor_Gender_Male_().isSelected();
boolean female = adminGUI.getInstructor_Gender_Female_().isSelected();
Date birthdate = adminGUI.getInstructor_Birthdate_DateChooser_().getDate();
if (adminFacade.instructorCheck(email, password, firstName, lastName, initials, phoneNumber, male, female, birthdate)) {
JOptionPane.showMessageDialog(null, "New instructor was added!", "Info!", JOptionPane.INFORMATION_MESSAGE);
adminGUI.getInstructor_Email_Field_().setText(null);
adminGUI.getInstructor_Password_Field_().setText(null);
adminGUI.getInstructor_First_Name_Field_().setText(null);
adminGUI.getInstructor_Last_Name_Field_().setText(null);
adminGUI.getInstructor_Initials_Field_().setText(null);
adminGUI.getInstructor_Phone_Number_Field_().setText(null);
adminGUI.getInstructor_Gender_ButtonGroup_().clearSelection();
adminGUI.getInstructor_Birthdate_DateChooser_().setCalendar(null);
}
}
private void addStudent() {
String email = adminGUI.getStudent_Email_Field_().getText();
String password = adminGUI.getStudent_Password_Field_().getText();
String firstName = adminGUI.getStudent_First_Name_Field_().getText();
String lastName = adminGUI.getStudent_Last_Name_Field_().getText();
String city = adminGUI.getStudent_City_Field_().getText();
String street = adminGUI.getStudent_Street_Field_().getText();
String postalCode = adminGUI.getStudent_Postal_Code_Field_().getText();
boolean male = adminGUI.getStudent_Gender_Male_().isSelected();
boolean female = adminGUI.getStudent_Gender_Female_().isSelected();
Date birthdate = adminGUI.getStudent_Birthdate_DateChooser_().getDate();
int index = adminGUI.getStudent_Instructor_ComboBox_().getSelectedIndex();
if (adminFacade.studentCheck(email, password, firstName, lastName, city, street, postalCode, male, female, birthdate, index)) {
JOptionPane.showMessageDialog(null, "New student was added!", "Info!", JOptionPane.INFORMATION_MESSAGE);
adminGUI.getStudent_Email_Field_().setText(null);
adminGUI.getStudent_Password_Field_().setText(null);
adminGUI.getStudent_First_Name_Field_().setText(null);
adminGUI.getStudent_Last_Name_Field_().setText(null);
adminGUI.getStudent_City_Field_().setText(null);
adminGUI.getStudent_Street_Field_().setText(null);
adminGUI.getStudent_Postal_Code_Field_().setText(null);
adminGUI.getStudent_Gender_ButtonGroup_().clearSelection();
adminGUI.getStudent_Birthdate_DateChooser_().setCalendar(null);
adminGUI.getStudent_Instructor_ComboBox_().setSelectedIndex(0);
try {
out.writeUTF("Change on table!");
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
}
private void fillStudentCombobox() {
adminGUI.getStudent_Instructor_ComboBox_().setModel(adminFacade.setStudentComboboxModel());
}
private void allAdminTableModel() {
adminGUI.getGod_Admin_Table_().setModel(adminFacade.setAllAdminTableModel());
}
private void adminTableModel() {
adminGUI.getAdmin_Table_().setModel(adminFacade.setAdminTableModel());
}
private void instructorTableModel() {
adminGUI.getInstructor_Table_().setModel(adminFacade.setInstructorTableModel());
}
private void studentTableModel() {
adminGUI.getStudent_Table_().setModel(adminFacade.setStudentTableModel());
}
private void editAdmin() {
if (adminGUI.getAdmin_Table_().getSelectionModel().isSelectionEmpty()) {
JOptionPane.showMessageDialog(null, "You must have a selected row first!", "Info!", JOptionPane.INFORMATION_MESSAGE);
return;
}
int row = adminGUI.getAdmin_Table_().getSelectedRow();
int id = Integer.parseInt(adminGUI.getAdmin_Table_().getModel().getValueAt(row, 1).toString());
String password = adminGUI.getAdmin_Table_().getModel().getValueAt(row, 3).toString();
String firstName = adminGUI.getAdmin_Table_().getModel().getValueAt(row, 4).toString();
String lastName = adminGUI.getAdmin_Table_().getModel().getValueAt(row, 5).toString();
String email = adminGUI.getAdmin_Table_().getModel().getValueAt(row, 6).toString();
String phoneNumber = adminGUI.getAdmin_Table_().getModel().getValueAt(row, 7).toString();
if (adminFacade.editAdminCheck(id, password, firstName, lastName, email, phoneNumber)) {
JOptionPane.showMessageDialog(null, "You have edited this admin!", "Info!", JOptionPane.INFORMATION_MESSAGE);
}
}
private void deleteAdmin() {
if (adminGUI.getAdmin_Table_().getSelectionModel().isSelectionEmpty()) {
JOptionPane.showMessageDialog(null, "You must have a selected row first!", "Info!", JOptionPane.INFORMATION_MESSAGE);
return;
}
int row = adminGUI.getAdmin_Table_().getSelectedRow();
int id = Integer.parseInt(adminGUI.getAdmin_Table_().getModel().getValueAt(row, 1).toString());
if (adminFacade.deleteAdminCheck(id)) {
JOptionPane.showMessageDialog(null, "You have deleted this admin!", "Info!", JOptionPane.INFORMATION_MESSAGE);
allAdminTableModel();
adminTableModel();
instructorTableModel();
studentTableModel();
}
}
public void listenForChanges() {
new Thread(
() -> {
String change;
while (socket.isConnected()) {
try {
change = in.readUTF();
if (change.equals("Change on table!")) {
allAdminTableModel();
adminTableModel();
instructorTableModel();
studentTableModel();
}
} catch (IOException ex) {
close(socket, in, out);
}
}
}, "listenThread"
).start();
}
private void close(Socket socket, DataInputStream in, DataOutputStream out) {
try {
if (socket != null) {
socket.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
}
DAO addStudent方法:
@Override
public boolean addStudent(Account account) throws SQLException {
query = "INSERT INTO account(username_email, password, account_type) VALUES(?, ?, ?);";
pst = DatabaseConnection.getInstance().getConnection().prepareStatement(query);
pst.setString(1, account.getUsernameEmail());
pst.setString(2, account.getPassword());
pst.setString(3, String.valueOf(account.getAccountType()));
pst.executeUpdate();
query = "INSERT INTO student (student_id, first_name, last_name, city, street, postal_code, birthdate, gender, instructor_id, admin_id) VALUES(LAST_INSERT_ID(), ?, ?, ?, ?, ?, ?, ?, ?, ?);";
pst = DatabaseConnection.getInstance().getConnection().prepareStatement(query);
pst.setString(1, account.getFirstName());
pst.setString(2, account.getLastName());
pst.setString(3, account.getCity());
pst.setString(4, account.getStreet());
pst.setInt(5, account.getPostalCode());
pst.setString(6, account.getBirthDate());
pst.setString(7, String.valueOf(account.getGender()));
pst.setInt(8, account.getInstructorId());
pst.setInt(9, account.getAdminId());
pst.executeUpdate();
pst.close();
}
adminFacadeModel 方法:
public DefaultTableModel getStudentTableModel() {
DefaultTableModel studentModel = new DefaultTableModel() {
@Override
public boolean isCellEditable(int row, int column) {
return switch (column) {
case 0, 1, 8 ->
false;
default ->
true;
};
}
};
studentModel.addColumn("No.");
studentModel.addColumn("Student ID");
studentModel.addColumn("Email");
studentModel.addColumn("Password");
studentModel.addColumn("First Name");
studentModel.addColumn("Last Name");
studentModel.addColumn("City");
studentModel.addColumn("Street");
studentModel.addColumn("Postal Code");
studentModel.addColumn("Instructor ID");
populateAdminStudentsList();
populateStudentTableModel(studentModel);
return studentModel;
}
private void populateAdminStudentsList() {
try {
adminStudentsList = adminDAO.getAccounts(admin.getAccountId(),'S');
} catch (SQLException ex) {
System.out.println(ex.getLocalizedMessage());
}
}
private void populateStudentTableModel(DefaultTableModel model) {
Object[] sRow = new Object[10];
String pwd;
int j = 0;
for (Account acc : adminStudentsList) {
sRow[0] = ++j;
sRow[1] = acc.getAccountId();
sRow[2] = acc.getUsernameEmail();
pwd = encryptor.getDecryptedString(acc.getPassword());
sRow[3] = pwd;
sRow[4] = acc.getFirstName();
sRow[5] = acc.getLastName();
sRow[6] = acc.getCity();
sRow[7] = acc.getStreet();
sRow[8] = acc.getPostalCode();
sRow[9] = acc.getInstructorId();
model.addRow(sRow);
}
}
检查学生方法:
public boolean addStudentCheck(String email, String password,
String firstName,
String lastName,
String city,
String street,
String postalCode,
boolean male,
boolean female,
Date birthdate,
int id) {
if (!parsable.isStringParsable(postalCode) && postalCode.length() > 4) {
JOptionPane.showMessageDialog(null, "Postal code can only be 4 digit numbers!", "Info!", JOptionPane.INFORMATION_MESSAGE);
return false;
}
if (!emailValidation.checkEmail(email)) {
JOptionPane.showMessageDialog(null, "Invalid email!", "Info!", JOptionPane.INFORMATION_MESSAGE);
return false;
}
if (password.length() < 6 || password.length() > 25) {
JOptionPane.showMessageDialog(null, "Password minimum size can be 6 and maximum 25 characters long!", "Info!", JOptionPane.INFORMATION_MESSAGE);
return false;
}
String pwd = encryptor.getEncryptedString(password);
char gender;
if (male) {
gender = 'M';
} else {
gender = 'F';
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(birthdate);
accountBuilder = new AccountBuilder();
director.buildStudentAccount(accountBuilder);
accountBuilder.usernameEmail(email)
.password(pwd)
.firstName(firstName)
.lastName(lastName)
.city(city)
.street(street)
.postalCode(Integer.parseInt(postalCode))
.birthDate(date)
.gender(gender)
.instructorId(id)
.adminId(admin.getAccountId());
newAccount = accountBuilder.build();
return add(newAccount);
}
private boolean add(Account acc) {
try {
return adminDAO.addStudent(acc);
} catch (SQLException ex) {
System.out.println(ex.getLocalizedMessage());
}
return false;
}
当管理员用户调用 addStudent 方法时,它会调用 adminFacade 方法,该方法基本上会进行更多检查,如果他们是 okej,它会将新学生插入数据库。
如果插入成功,它返回 true 并发送消息“Change on table!”将 DataOutputStream 传递给 clientHandler,这样它就可以通知其他用户发生了变化。
问题是当我尝试插入一个新学生时出现重复键输入异常,数据被插入并且 setModel 方法不执行。
Set 模型方法基本上从数据库中调用新数据并将其插入到模型中,该模型稍后会返回。
我不知道做错了什么。
主线程应该做操作,而监听线程应该只监听变化和调用设置方法。
任何帮助将不胜感激!