Мне нужно соединение с базой данных в веб-сервисе 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 должен быть членом боба?
@Stateless
@WebService
public class TestBean {
private @Resource(name=dbName) DataSource m_ds;
}
Я сожалею, если это - nube вопрос, но я довольно плохо знаком с Java. Заранее спасибо.
Помимо форматирования в стиле 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
при попытке установить соединение.
В древнем мире 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
в ваш Stateless Bean, - это написать (где mydatabase
- имя источника данных):
@Resource
private DataSource mydatabase;
Используйте атрибут name, если вы хотите явно, ну, установить имя:
@Resource(name="jdbc/mydatabase")
private DataSource dataSource;
EJB3 фактически делает ServiceLocator
, и вам действительно следует предпочесть инъекцию при работе с ними.