0

I have this method that is supposed to be executed in a transaction. As I get and close connections in DAO, I suppose that it should to be a part of DAO.

void setStatusDeclinedAndRefund() {
// sets Order status to DECLINED
// refund money to user's balance
}

But I though DAO implementations should implement only CRUD methods, is it ok for such a method to be there?

If it violates, I can call 2 update methods from Service layer ( but how am I supposed to create a transaction there? Open connection -> pass it DAO - seems like a pretty bad idea )

UPD: The class I get connections from ( just to show that I use ComboPooledDataSource for connections ).

 public class DBManager {
  private static DBManager instance;
  private ComboPooledDataSource cpds;

  /**
   * Singleton.
   */
  public static synchronized DBManager getInstance() {
    if (instance == null) {
      instance = new DBManager();
    }
    return instance;
  }

  private DBManager() {
    try {
      init();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Create pool.
   *
   * @throws Exception the exception
   */
  private void init() throws Exception {
    createPool();
  }

  /**
   * Establishes a connection to the database.
   *
   * @return the connection to the database
   */
  public Connection getConnection() {
    Connection conn = null;
    try {
      conn = this.cpds.getConnection();
    } catch (SQLException e) {
      e.printStackTrace();
    }
    return conn;
  }

  /**
   * Closes the connection.
   *
   * @param conn closes the database connection
   */
  public void closeConnection(Connection conn) {
    try {
      conn.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

  /**
   * Gets utils properties.
   *
   * @return the databases properties
   * @throws IOException by failed or interrupted I/O operations.
   */
  private Properties getProperties() throws IOException {
    Properties props = new Properties();
    props.load(DBManager.class.getResourceAsStream("/db.properties"));
    return props;
  }

  /**
   * Create a pool.
   *
   * @throws Exception the exception
   */
  private void createPool() throws Exception {
    Class.forName("org.postgresql.Driver");
    Properties props = getProperties();
    cpds = new ComboPooledDataSource();
    cpds.setDriverClass(props.getProperty("driver"));
    cpds.setJdbcUrl(props.getProperty("url"));
    cpds.setUser(props.getProperty("user"));
    cpds.setPassword(props.getProperty("password"));
    cpds.setMaxStatements(180);
  }

}
  • Does this answer your question? [Where does the @Transactional annotation belong?](https://stackoverflow.com/questions/1079114/where-does-the-transactional-annotation-belong) – pringi Mar 25 '22 at 13:55
  • @pringi Nope, the question is about low-level JDBC, no JPA or Hibernate –  Mar 25 '22 at 13:58
  • 2
    "How am I supposed to create a transaction there", it depends on how you've designed your code. Clearly you haven't considered a situation where a transaction encompasses more than a single dao operation. Time for thinking about design and refactoring? – Kayaman Mar 25 '22 at 14:02
  • @Kayaman thank you, yes, that is true, my service layer is not suitable for executing dao methods in a transaction. But how can I do it? Getting connection in a service and passing it dao seems like a wrong decision. Could you please send a link or a github example, I would appreciate it so much! –  Mar 25 '22 at 15:04
  • Keep the connection encapsulated in the dao, but call `dao.beginTrx();` and `dao.commit();` from the service. For example. – Kayaman Mar 25 '22 at 20:58
  • @Kayaman, Thank you, but as far as I understand that means that dao class should have one instance of connection. And one method - `dao.beginTrx()` that initializes it with the one from connection pool and `dao.commit` that commit and closes the connection. But is it safe to have a single instance of connection for a class? –  Mar 26 '22 at 10:16
  • 1
    Well `ThreadLocal` could be used to take care of that. But this is just an example of how it could be done, encapsulating transaction logic inside the dao itself. – Kayaman Mar 26 '22 at 17:49
  • @Kayaman I really sorry to bother you, but there is noone I can ask. I've updated my answer with the code I get Connection from ( ComboPooledDataSource ). Is it possible to use it instead of ThreadLocal to achieve the same result? –  Mar 26 '22 at 21:07

0 Answers0