在Java中使用线程时重复键输入异常

问题描述 投票:0回答:0

每次有人插入或更新数据库时,我都在尝试实现 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 模型方法基本上从数据库中调用新数据并将其插入到模型中,该模型稍后会返回。

我不知道做错了什么。

主线程应该做操作,而监听线程应该只监听变化和调用设置方法。

任何帮助将不胜感激!

java multithreading
© www.soinside.com 2019 - 2024. All rights reserved.