Get database connection from a connection pool

前端 未结 4 1485
逝去的感伤
逝去的感伤 2020-12-15 10:50

I am refactoring others code. The one thing I notice is that of the manner on how the system is getting a connection from the connection pool.

Sample is like this.

相关标签:
4条回答
  • 2020-12-15 11:04

    The method I have used in the past is to create a singleton class that holds the datasource

    E.g.

    public class DatabaseConnectionManager {
    
        DataSource ds;
    
        public void init() {
            InitialContext initialContext = new InitialContext();
            ds = (javax.sql.DataSource)initialContext.lookup("jdbc/mysqldb");
        }
    
        public Connection getConnection() {
            if(ds == null) init();
    
            return ds.getConnection();
        }
    }
    

    This means that you have a shared reference to your datasource, taking away the jndi lookup overhead.

    0 讨论(0)
  • 2020-12-15 11:04

    I just did some testing with this, and found that jndi lookup time is not that heavy. 50.000 lookups in about 1 sec here.

    So in many cases, I don't see a reason for caching the DataSource at all.

    Problem with caching is that you might end up with a stale DataSource, forcing you to restart your app if you change anything related to the datasource definition.

    0 讨论(0)
  • 2020-12-15 11:04

    Adding to what's said, there's a design pattern called Service Locator, which is a basically a singleton containing a registry called "service" that holds your JNDI objects.

    Basically, if the object isn't found in the registry, the service is taken from the JNDI pool and registered in the registry. The next call will simply pull the object from registry.

    Hope this helps.

    0 讨论(0)
  • 2020-12-15 11:22

    Do it once in a ServletContextListener instead of everytime in init() of many servlets. The contextInitialized() method is executed only once during webapp's startup.

    public class Config implements ServletContextListener {
        private static final String ATTRIBUTE_NAME = "config";
        private DataSource dataSource;
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
            ServletContext servletContext = event.getServletContext();
            String databaseName = servletContext.getInitParameter("database.name");
            try {
                dataSource = (DataSource) new InitialContext().lookup(databaseName);
            } catch (NamingException e) {
                throw new RuntimeException("Config failed: datasource not found", e);
            }
            servletContext.setAttribute(ATTRIBUTE_NAME, this);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            // NOOP.
        }
    
        public DataSource getDataSource() {
            return dataSource;
        }
    
        public static Config getInstance(ServletContext servletContext) {
            return (Config) servletContext.getAttribute(ATTRIBUTE_NAME);
        }
    }
    

    Configure it as follows in web.xml:

    <context-param>
        <param-name>database.name</param-name>
        <param-value>jdbc/mysqldb</param-value>
    </context-param>
    <listener>
        <listener-class>com.example.Config</listener-class>
    </listener>
    

    You can obtain it in your servlet as follows (init() or doXXX() method, you choose):

    DataSource dataSource = Config.getInstance(getServletContext()).getDataSource();
    

    I'd however refactor it a step further, JDBC code should preferably be placed in its own classes, not in servlets. Lookup the DAO pattern.

    0 讨论(0)
提交回复
热议问题