There is an abstract class DAOFactory, you need to do the following: when creating a DAO, give it a connection, so that the DAO inside can use it so as not to pull the DAOFactory every time, as I have now implemented, DAOFactory daofactory = new DAOFactory (); Naturally, this field should not be here, using the example of code, how to implement all this?

public abstract class DAOFactory implements DAOFactotyInterface { Connection connection = null; public Connection getConnection() throws DAOException { InputStream read = null; try { read = this.getClass().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(read); String dbUrl = properties.getProperty("db.url"); String dbUser = properties.getProperty("db.user"); String dbPassword = properties.getProperty("db.password"); String dbDriver = properties.getProperty("db.driver"); Class.forName(dbDriver); if (connection == null) { connection = DriverManager.getConnection(dbUrl, dbUser, dbPassword); } } catch (IOException e) { throw new DAOException("Properties file is missing ", e); } catch (ClassNotFoundException e) { throw new DAOException("Driver missing ", e); } catch (SQLException e) { throw new DAOException("No connection ", e); } finally { if (read != null) { try { read.close(); } catch (IOException e) { throw new DAOException("InputStream is not closed.", e); } } } return connection; } @Override public ProfileDAO getProfileDAO() { return new MySQLProfileDAO(); } @Override public ImagesDAO getImagesDAO() { return new MySQLImagesDAO(); } @Override public RelationshipsDAO getRelationshipsDAO() { return new MySQLRelationshipsDAO(); } @Override public ScrobblesDAO getScrobblesDAO() { return new MySQLScrobblesDAO(); } } public class MySQLImagesDAO implements ImagesDAO { PreparedStatement preparedStatement = null; Connection connection = null; DAOFactory daofactory = new DAOFactory(); private void getPreparedStatement(String sql) throws DAOException { connection = daofactory.getConnection(); if (preparedStatement == null) { try { preparedStatement = connection.prepareStatement(sql); } catch (Exception e) { throw new DAOException("Get preparedStatment failed.", e); } } } /** * @see ImagesDAO#selectAllImages() */ public List<Images> selectAllImages() throws DAOException { List<Images> allImages = new ArrayList<>(); Statement st = null; ResultSet rs = null; try { connection = daofactory.getConnection(); st = connection.createStatement(); rs = st.executeQuery(PrepStatName.SELECT_IMAGES); while (rs.next()) { Images image = new Images(); image.setId(rs.getInt("id")); image.setIdProfile(rs.getInt("id_profiles")); image.setAvatar(rs.getString("avatar")); allImages.add(image); } } catch (Exception e) { throw new DAOException("List of images is not selected.", e); } finally { try { if (st != null) { st.close(); } if (rs != null) { rs.close(); } } catch (Exception e) { throw new DAOException("The ResultSet/Statement is not closed.", e); } } return allImages; } /** * @see ImagesDAO#updateImages(Images) */ public void updateImages(Images images) throws DAOException { try { getPreparedStatement(PrepStatName.UPDATE_IMAGES); preparedStatement.setInt(1, images.getIdProfile()); preparedStatement.setString(2, images.getAvatar()); preparedStatement.setInt(3, images.getId()); preparedStatement.executeUpdate(); } catch (Exception e) { throw new DAOException("The images is not updated.", e); } } /** * @see ImagesDAO#deleteImages(Images) */ public void deleteImages(Images images) throws DAOException { try { getPreparedStatement(PrepStatName.DEL_IMAGES); preparedStatement.setInt(1, images.getId()); preparedStatement.executeUpdate(); } catch (Exception e) { throw new DAOException("The images is not delete.", e); } } /** * @see ImagesDAO#insertImages(Images) */ public void insertImages(Images images) throws DAOException { try { getPreparedStatement(PrepStatName.INSERT_IMAGES); preparedStatement.setInt(1, images.getIdProfile()); preparedStatement.setString(2, images.getAvatar()); preparedStatement.executeUpdate(); } catch (Exception e) { throw new DAOException("The images is not create.", e); } } public void close() throws DAOException { try { if (preparedStatement != null) { preparedStatement.close(); preparedStatement = null; } } catch (Exception e) { throw new DAOException("The preparedStatement is not closed. ", e); } try { if (connection != null) { connection.close(); connection = null; } } catch (Exception e) { throw new DAOException("The connection is not closed.", e); } } } 
  • There is a lot of code. Is it possible to isolate from this a part of the code that directly illustrates the question or reproduces the problem? - Nick Volynkin
  • Yes, it’s possible a smaller question such as from this method @Override public ImagesDAO getImagesDAO() { return new MySQLImagesDAO(); } @Override public ImagesDAO getImagesDAO() { return new MySQLImagesDAO(); } pass the connection to the DAO to accept it in the private void getPreparedStatement(String sql) throws DAOException { } method. private void getPreparedStatement(String sql) throws DAOException { } i.e. the task is: “when creating a dao, give him a connection, so that tao inside can use it, and not pull the factor every time” is not sure what it is in these places of the code that is implemented, therefore he posted a full listing of classes - PolkovnikJ

1 answer 1

Thats what you call a factory is not really a factory, but something completely incomprehensible.

Let's take out all the code associated with connecting to the database in a separate class. On the good, here it is better to use ready implementation DataSource from any library.

 public class CustomDataSource { private final Properties props = new Properties(); private Connection connection; public CustomDataSource(String filename) { try ( InputStream is = this.getClass().getResourceAsStream(filename) ) { props.load(is); } catch (Exception e) { throw new RuntimeException("Properties file is missing", e); } } public Connection getConnection() { if ( connection == null ) { try { Class.forName(props.getProperty("db.driver")); connection = DriverManager.getConnection(props.getProperty("db.url"), props.getProperty("db.user"), props.getProperty("db.password")); } catch (ClassNotFoundException e) { throw new DAOException("Driver missing", e); } catch (SQLException e) { throw new DAOException("No connection", e); } } return connection; } } 

This is just an extra class from which all DAOs will inherit, as a sign that they work with JDBC. It is also worth writing down any additional methods for working with the database.

 public abstract class JDBCSupport { protected CustomDataSource dataSource = null; public JDBCSupport(CustomDataSource dataSource) { this.dataSource = dataSource; } } 

The idea of checked exceptions has long died, no one wants to drag throws through all classes - use unchecked .

 public class DAOException extends RuntimeException { public DAOException(String message, Throwable cause) { super(message, cause); } } 

DAO implementation. The fact that you close all the statements is good, but the huge finally blocks do not add readability. Use the try-with-resources construct.

 public interface ImagesDao { List<Image> findAll(); } public class MySQLImagesDAO extends JDBCSupport implements ImagesDao { public MySQLImagesDAO(CustomDataSource dataSource) { super(dataSource); } @Override public List<Image> findAll() { List<Image> images = new ArrayList<>(); try ( Statement st = dataSource.getConnection().createStatement() ) { try ( ResultSet rs = st.executeQuery("SELECT FROM ..") ) { while ( rs.next() ) { Image image = new Image(); // set values images.add(image); } return images; } } catch (Exception e) { throw new DAOException("List of images is not selected.", e); } } } 

Factory, if you still need it.

 public class DaoFactory { public static MySQLImagesDAO createImagesDao(CustomDataSource dataSource) { return new MySQLImagesDAO(dataSource); } } 

Example of use:

 CustomDataSource dataSource = new CustomDataSource("some_config.properties"); MySQLImagesDAO imagesDao = DaoFactory.createImagesDao(dataSource); List<Image> images = imagesDao.findAll(); 
  • Thank you for such an extended response, very useful and informative - PolkovnikJ