在Java Swing中关闭数据库连接

0 java swing jdbc

我对jdbc关闭连接感到困惑.

package Login;
public class LoginFrame {
    private JFrame loginFrame;
    Connection conn = null;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LoginFrame window = new LoginFrame();
                    window.loginFrame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public LoginFrame() {
        initialize();
        conn = DBConnect.connectDB();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        loginFrame = new JFrame();
        loginFrame.setResizable(false);
        loginFrame.setTitle("XXX");
        loginFrame.setBounds(100, 100, 350, 300);
        loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        loginFrame.getContentPane().setLayout(null);

        panel = new JPanel();
        panel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Login", TitledBorder.LEADING, TitledBorder.TOP, null, SystemColor.inactiveCaptionText));
        panel.setBounds(96, 140, 139, 99);
        loginFrame.getContentPane().add(panel);
        panel.setLayout(null);

        loginField = new JTextField();
        loginField.setBounds(47, 16, 86, 20);
        panel.add(loginField);
        loginField.setColumns(10);

        passwordField = new JPasswordField();
        passwordField.setBounds(47, 37, 86, 20);
        panel.add(passwordField);

        JButton loginButton = new JButton("Login");
        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

                String sql = "select * from employees where login=? and password=?";
                try{
                    PreparedStatement pst = conn.prepareStatement(sql);
                    pst.setString(1, loginField.getText());
                    pst.setString(2, passwordField.getText());
                    ResultSet rs = pst.executeQuery();
                    int countUsr = 0;
                    while(rs.next()){
                        countUsr++;
                    }
                    if(countUsr == 1){
                        loginFrame.dispose();
                        AdminFrame adminFrame = new AdminFrame();
                        adminFrame.setVisible(true);
                    }else  if(countUsr > 1){
                        JOptionPane.showMessageDialog(null, "ERR");
                    }else{
                        JOptionPane.showMessageDialog(null, "ERR");
                        passwordField.setText("");
                    }
                rs.close();
                pst.close();
                }catch(Exception e){
                    JOptionPane.showMessageDialog(null, "ERR: "+e.getMessage());
                }
            }
        });
        loginButton.setBounds(25, 65, 89, 23);
        panel.add(loginButton);
    }
}   
Run Code Online (Sandbox Code Playgroud)

我不确定哪种方法更适合用于关闭连接:

@Override
protected void finalize() throws Throwable {
    conn.close();
    super.finalize();
}
Run Code Online (Sandbox Code Playgroud)

要么

finally {
    conn.close();
}
Run Code Online (Sandbox Code Playgroud)

在按钮ActionListener中尝试catch块之后.

在一些例子中,人们说最后块更好,但是当我有很多方法(4示例动作监听器)时,我会在DB上做一些操作.我应该在所有方法中打开和关闭连接还是只使用finalize方法?

Lui*_*oza 5

使用数据库时,需要考虑一些概念:

  • 不要让连接打开太多时间.要完成此任务,您应该在尽可能短的范围内打开和关闭它.这也可以帮助您使用相同的连接在同一事务中执行多个操作,特别是在多线程环境中.
  • 仅重用物理连接.这意味着,您打开连接一次,将其发送到SLEEP状态并在以后重复使用它.要做到这一点,不要重新发明轮子,而是使用数据库连接池自动为您处理.

执行此操作的步骤:

  • 在应用程序开始时,创建数据库连接池.
  • 在每种方法中,当您需要对数据库执行某些操作时,从数据库连接池获取连接,对数据库执行操作,然后关闭连接.
  • 在应用程序结束时,关闭数据库连接池.

以下是使用HikariCP执行此操作的示例:

定义将使用数据库连接池的数据源:

public final class DataSourceFactory {

    private static final Logger LOG = LoggerFactory.getLogger(DataSourceFactory.class);

    private static DataSource mySQLDataSource;

    private DataSourceFactory() { }

    private static DataSource getDataSource(String configurationProperties) {
        Properties conf = new Properties();
        try {
            conf.load(DataSourceFactory.class.getClassLoader().getResourceAsStream(configurationProperties));
        } catch (IOException e) {
            LOG.error("Can't locate database configuration", e);
        }
        HikariConfig config = new HikariConfig(conf);
        HikariDataSource dataSource = new HikariDataSource(config);
        return dataSource;
    }

    public static DataSource getMySQLDataSource() {
        LOG.debug("Retrieving data source for MySQL");
        if (mySQLDataSource == null) {
            synchronized(DataSourceFactory.class) {
                if (mySQLDataSource == null) {
                    LOG.debug("Creating data source for MySQL");
                    mySQLDataSource = getDataSource("mysql-connection.properties");
                }
            }
        }
        return mySQLDataSource;
    }
}
Run Code Online (Sandbox Code Playgroud)

在尽可能短的范围内使用连接.

public class LoginFrame {
    private JFrame loginFrame;
    //remove the Connection from here, this is not the shortest possible scope
    //Connection conn = null;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LoginFrame window = new LoginFrame();
                    window.loginFrame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public LoginFrame() {
        initialize();
        conn = DBConnect.connectDB();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        //...
        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //This is the shortest possible scope for the connection
                //Declare it here and use it
                Connection conn = DataSourceFactory.getMySQLDataSource().getConnection();
                String sql = "select * from employees where login=? and password=?";
                try{
                    PreparedStatement pst = conn.prepareStatement(sql);
                    pst.setString(1, loginField.getText());
                    pst.setString(2, passwordField.getText());
                    ResultSet rs = pst.executeQuery();
                    int countUsr = 0;
                    while(rs.next()){
                        countUsr++;
                    }
                    if(countUsr == 1){
                        loginFrame.dispose();
                        AdminFrame adminFrame = new AdminFrame();
                        adminFrame.setVisible(true);
                    }else  if(countUsr > 1){
                        JOptionPane.showMessageDialog(null, "ERR");
                    }else{
                        JOptionPane.showMessageDialog(null, "ERR");
                        passwordField.setText("");
                    }
                } catch(Exception e) {
                    //ALWAYS log the exception, don't just show a message
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(null, "ERR: "+e.getMessage());
                } finally {
                    try {
                        rs.close();
                        pst.close();
                        con.close();
                    } catch (SQLException silent) {
                        //do nothing
                    }
                }
            }
        });
        loginButton.setBounds(25, 65, 89, 23);
        panel.add(loginButton);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用Java 7或更高版本,那么请使用try-with-resources(毕竟这是语法糖):

loginButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        //This is the shortest possible scope for the connection
        //Declare it here and use it
        Connection conn = ;
        String sql = "select * from employees where login=? and password=?";
        try(Connection conn = DataSourceFactory.getMySQLDataSource().getConnection();
            PreparedStatement pst = conn.prepareStatement(sql);) {
            pst.setString(1, loginField.getText());
            pst.setString(2, passwordField.getText());
            try (ResultSet rs = pst.executeQuery();) {
                int countUsr = 0;
                while(rs.next()){
                    countUsr++;
                }
                if(countUsr == 1){
                    loginFrame.dispose();
                    AdminFrame adminFrame = new AdminFrame();
                    adminFrame.setVisible(true);
                } else if(countUsr > 1){
                    JOptionPane.showMessageDialog(null, "ERR");
                } else {
                    JOptionPane.showMessageDialog(null, "ERR");
                    passwordField.setText("");
                }
            }
        } catch(Exception e) {
            //ALWAYS log the exception, don't just show a message
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "ERR: "+e.getMessage());
        }
    }
});
Run Code Online (Sandbox Code Playgroud)