Правильное использование пула соединений JDBC (Glassfish)

Мне нужно подключение к базе данных в веб-службе Java, реализованной как сеансовый компонент, и я не уверен, правильно ли я это делаю.

я создал класс

public final class SQLUtils   {  
    //.....  
    private static DataSource  m_ds=null;    

    static  
    {  
        try
        {
            InitialContext ic = new InitialContext();
            m_ds = (DataSource) ic.lookup(dbName); //Connection pool and jdbc resource previously created in Glassfish  , dbName contains the proper JNDI resource name 

        }
        catch (Exception e)
        {
            e.printStackTrace();
            m_ds = null;
        }

    }

    public static Connection getSQLConnection() throws SQLException  
    {  
        return m_ds.getConnection();             
    }
}

Всякий раз, когда мне нужна связь, я

 Connection cn = null;  
 try  
 {
     cn = SQLUtils.getSQLConnection();
     // use connection
 }
 finally 
 {
     if (null != cn)
     {
         try
         {
             cn.close();
         }
         catch (SQLException e)
         {

         }
     }
 }

Можно ли использовать его таким образом, или я DataSource должен быть членом bean-компонента?

  @Stateless  
  @WebService  
  public class TestBean  {  
   private @Resource(name=dbName) DataSource m_ds;   
  }  

Извините, если это пустой вопрос, но я новичок в Java. Заранее спасибо.


person a1ex07    schedule 16.12.2009    source источник


Ответы (3)


Помимо форматирования в стиле C, нескольких ненужных строк и немного плохой обработки исключений, вы можете просто сделать это.

Вот как бы я это сделал:

public final class SQLUtil {
    private static DataSource dataSource;
    // ..

    static {
        try {
            dataSource = (DataSource) new InitialContext().lookup(name);
        } catch (NamingException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static Connection getConnection() throws SQLException {  
        return dataSource.getConnection();             
    }
}

Я бросаю здесь ExceptionInInitializerError, чтобы приложение немедленно остановитесь, чтобы вам не пришлось столкнуться с «необъяснимым» NullPointerException при попытке установить соединение.

person BalusC    schedule 16.12.2009
comment
Однако я бы предпочел инъекцию в самом компоненте, потому что его легче имитировать и тестировать. - person ewernli; 16.12.2009
comment
Как заметил Паскаль, на самом деле вам все это не нужно. Просто @Resource достаточно. - person BalusC; 17.12.2009

В древнем мире J2EE традиционным способом управления этим было использование файла ServiceLocator. Ниже пример реализации (неоптимизированный, DataSource может кэшироваться):

public class ServiceLocator {
    private Context initalContext;

    private static ServiceLocator ourInstance = new ServiceLocator();

    public static ServiceLocator getInstance() {
        return ourInstance;
    }

    private ServiceLocator() {
        try {
            this.initalContext = new InitialContext();
        } catch (NamingException ex) {
            throw new ServiceLocatorException(...);
        }
    }

    public DataSource getDataSource(String dataSourceName) {
        DataSource datasource = null;

        try {
            Context ctx = (Context) initalContext.lookup("java:comp/env");
            datasource = (DataSource) ctx.lookup(dataSourceName);
        } catch (NamingException ex) {
            throw new ServiceLocatorException(...);
        }

        return datasource;
    }
}

Чтобы использовать его, просто вызовите его следующим образом:

DataSource ds = ServiceLocator.getInstance().getDataSource("jdbc/mydatabase");

Но это было до эпохи EJB3 и внедрения зависимостей. Теперь, при использовании EJB3, если вы настроили DataSource в своем контейнере EJB, все, что вам нужно сделать, чтобы автоматически внедрить DataSource в ваш компонент без сохранения состояния, — это написать (где mydatabase — имя источника данных ):

@Resource
private DataSource mydatabase;

Используйте атрибут name, если вы хотите явно указать имя:

@Resource(name="jdbc/mydatabase")
private DataSource dataSource;

EJB3 фактически делает шаблон ServiceLocator устаревшим, и вам действительно следует предпочесть внедрение при работе с ними.

person Pascal Thivent    schedule 16.12.2009
comment
Ах, черт, я знал это. Это действительно намного лучше, чем какой-нибудь вспомогательный класс. +1. - person BalusC; 17.12.2009

Эм, разве это не пример JDBC DataSource, а не пула соединений Glassfish?

person Per Lindberg    schedule 08.02.2013