#java #mysql #jdbc #dao #preparedstatement
Как мне в этом коде, сделать так, чтобы я верно использовал PrepareStatement? Я уже всю реализацию ДАО не скидываю, так как очень много кода. В моем коде PrepareStatement замедляет работу, а нужно чтобы ускорял. Я его использую не верно. Я так понимаю, мне его как то открыть надо один раз, потом использовать везде как-то, и потом закрыть? Буду рад любой помощи. public class MySqlDaoStudent implements DaoStudent { private PreparedStatement stm=null; private final Connection connection; private ResultSet rs=null; public MySqlDaoStudent(Connection connection) { this.connection = connection; } @Override public Student read(int key) throws SQLException { String sql="SELECT * FROM student_db.student where id = ?;"; Student student = new Student(); try { stm = connection.prepareStatement(sql); stm.setInt(1, key); rs = stm.executeQuery(); rs.next(); student.setId(rs.getInt("ID")); student.setFirst_name(rs.getString("FIRST_NAME")); student.setSecond_name(rs.getString("SECOND_NAME")); } catch (SQLException e) { e.printStackTrace(); } finally { if(rs!=null){ rs.close(); } if(connection!=null){ connection.close(); } if (stm!=null){ stm.close(); } } return student; } @Override public ListgetAll() throws SQLException { String sql="SELECT * FROM student_db.student"; List list=new ArrayList<>(); Student student=new Student(); try{ stm=connection.prepareStatement(sql); rs=stm.executeQuery(); while(rs.next()){ student.setId(rs.getInt("ID")); student.setFirst_name(rs.getString("FIRST_NAME")); student.setSecond_name(rs.getString("SECOND_NAME")); list.add(student); } } catch (SQLException e){ e.printStackTrace(); } finally { if(rs!=null){ rs.close(); } if(connection!=null){ connection.close(); } if (stm!=null){ stm.close(); } } return list; } }
Ответы
Ответ 1
Смысл PreparedStatement в том, чтобы скомпилировать запрос один раз и использовать все время меняя только параметры запроса. Фактически, компиляция запроса происходит при вызове PrepareStatement() - ваша проблема в том, что вы при каждом выполнении запроса заново компилируете запрос. Отделите мух от котлет, а именно: разделите этап компиляции запроса и этап выполнения прекомпилированного запроса. Ну и на закуску: поскольку PreparedStatement привязан к Connection, то при закрытии соединения естественно вы теряете свой прекомплированный запрос (на что вам и указывают в комментариях)Ответ 2
рекомендую модернизировать код таким образом import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * Created by TS on 07.02.2017. */ public class MySqlDaoStudent implements DaoStudent { private static final String ALL_STUDENTS = "SELECT * FROM student_db.student"; private PreparedStatement stm = null; private PreparedStatement allPreparedStatement = null; private final Connection connection; public MySqlDaoStudent(Connection connection) { this.connection = connection; } private void init() throws SQLException { if (allPreparedStatement == null) allPreparedStatement = connection.prepareStatement(ALL_STUDENTS); } public Student read(int key) throws SQLException { // у нас каждый раз новый key, и так как у нас 1 параметр, запрос легче сформировать так String sql = String.format("SELECT * FROM student_db.student where id = %s;", key); Student student = new Student(); try (ResultSet rs = stm.executeQuery(sql)) { // такая конструкция позволяет закрывать rs (вместо finally) rs.next(); student.setId(rs.getInt("ID")); student.setFirst_name(rs.getString("FIRST_NAME")); student.setSecond_name(rs.getString("SECOND_NAME")); } catch (SQLException e) { e.printStackTrace(); } return student; } public ListgetAll() throws SQLException { init(); List list = new ArrayList<>(); Student student = new Student(); try (ResultSet rs = allPreparedStatement.executeQuery()) { while (rs.next()) { student.setId(rs.getInt("ID")); student.setFirst_name(rs.getString("FIRST_NAME")); student.setSecond_name(rs.getString("SECOND_NAME")); list.add(student); } } catch (SQLException e) { e.printStackTrace(); throw e; } return list; } public void closeConnection() throws SQLException { if (connection != null) { connection.close(); } } } Ответ 3
Верное использование PreparedStatement заключается в том, что необходимо подготовить запрос в СУБД, прежде, чем он будет отправлен. Его нужно подготовить, сохранить в поле, а потом использовать, таким образом достигается максимальная скорость обработки любых запросов в любом кол-ве. Вот код решения моего вопроса: (sql запрос сохранил в константу) /* Константа sql запроса */ private static final String SQL_SELECT_ALL_STUDENT = "SELECT id, first_name, second_name FROM student_db.student"; /* поле подключения */ private Connection connection = null; /* поле PS */ private PreparedStatement psSelectAllStudent = null; // использую Properties для чтения user,password,driver,url // подключаюсь к СУБД private Connection getConnection() throws DaoException { Properties property = new Properties(); InputStream inputStream = null; try { inputStream = this.getClass().getResourceAsStream("/config.properties"); property.load(inputStream); String url = property.getProperty("url"); String user = property.getProperty("user"); String password = property.getProperty("password"); String driver = property.getProperty("driver"); Class.forName(driver); if (connection == null) { connection = DriverManager.getConnection(url, user, password); } } catch (IOException ex) { DaoException er = new DaoException("ошибка загрузки файла ", ex); throw er; } catch (ClassNotFoundException ex) { DaoException er = new DaoException("ошибка Class.forName(driver) ", ex); throw er; } catch (SQLException ex) { DaoException er = new DaoException("ошибка соединения с СУБД ", ex); throw er; } return connection; } //подготавливаю PS в СУБД и сохраняю в поле private void selectAllStudentPs(String sql) throws DaoException { getConnection(); try { if (psSelectAllStudent == null) { psSelectAllStudent = connection.prepareStatement(sql); } } catch (SQLException er) { DaoException ex = new DaoException("ошибка подготовки запроса в selectStudentPs ", er); throw ex; } } //получаю список того, что было необходимо сделать в задании @Override public ListselectAllStudent() throws DaoException { ResultSet resultSet=null; List list = new ArrayList<>(); try { selectAllStudentPs(SQL_SELECT_ALL_STUDENT); resultSet = psSelectAllStudent.executeQuery(); while (resultSet.next()) { Student ss = new Student(); ss.setId(resultSet.getInt("id")); ss.setFirstName(resultSet.getString("first_name")); ss.setSecondName(resultSet.getString("second_name")); list.add(ss); } } catch (SQLException ex) { DaoException er = new DaoException("ошибка выполения SQL_SELECT_ALL_STUDENT ", ex); throw er; }finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException ex) { DaoException er = new DaoException("ошибка закрытия resultSet в " + "selectStudent ", ex); throw er; } } } return list; } /* ---- */ Таким образов и получается именно ускорение PreparedStatement !
Комментариев нет:
Отправить комментарий