我正在创建一个连接到多个数据库的java应用程序。用户将能够从下拉框中选择要连接的数据库。
然后,程序通过将名称传递给创建初始上下文的方法来连接到数据库,以便它可以与oracle Web逻辑数据源进行通信。
public class dbMainConnection {
private static dbMainConnection conn = null;
private static java.sql.Connection dbConn = null;
private static javax.sql.DataSource ds = null;
private static Logger log = LoggerUtil.getLogger();
private dbMainConnection(String database) {
try {
Context ctx = new InitialContext();
if (ctx == null) {
log.info("JDNI Problem, cannot get InitialContext");
}
database = "jdbc/" + database;
log.info("This is the database string in DBMainConnection" + database);
ds = (javax.sql.DataSource) ctx.lookup (database);
} catch (Exception ex) {
log.error("eMTSLogin: Error in dbMainConnection while connecting to the database : " + database, ex);
}
}
public Connection getConnection() {
try {
return ds.getConnection();
} catch (Exception ex) {
log.error("Error in main getConnection while connecting to the database : ", ex);
return null;
}
}
public static dbMainConnection getInstance(String database) {
if (dbConn == null) {
conn = new dbMainConnection(database);
}
return conn;
}
public void freeConnection(Connection c) {
try {
c.close();
log.info(c + " is now closed");
} catch (SQLException sqle) {
log.error("Error in main freeConnection : ", sqle);
}
}
}
我的问题是,如果有人忘记为数据库创建数据源但他们仍然将其添加到下拉框中会发生什么?现在发生的事情是,如果我尝试连接到没有数据源的数据库,则表示无法获得连接。这是我想要的,但是如果我连接到一个数据源的数据库首先有效,那么尝试连接到没有数据源的数据库,再次出错
javax.naming.NameNotFoundException:无法解析'jdbc.peterson'。已解决'jdbc';剩下的名字'彼得森'。
我再次期待,但令我感到困惑的是,它抓住了最后一个良好的连接,这是一个不同的数据库并处理所有事情,好像什么也没发生。
任何人都知道为什么会这样吗? weblogic是否将连接或某些内容缓存为故障安全?以这种方式创建连接是一个坏主意吗?
答案 0 :(得分:5)
您将在类的静态变量中存储唯一的数据源(和连接以及dbMainConnection)。每当有人请求数据源时,您将用新的数据源替换前一个数据源。如果从JNDI获取数据源时发生异常,则静态数据源保持原样。您不应该将任何内容存储在静态变量中。由于dbMainConnection类是使用数据库的名称构造的,并且有多个数据库名称,因此将其设置为单例是没有意义的。
只需使用以下代码访问数据源:
public final class DataSourceUtil {
/**
* Private constructor to prevent unnecessary instantiations
*/
private DataSourceUtil() {
}
public static DataSource getDataSource(String name) {
try {
Context ctx = new InitialContext();
String database = "jdbc/" + name;
return (javax.sql.DataSource) ctx.lookup (database);
}
catch (NamingException e) {
throw new IllegalStateException("Error accessing JNDI and getting the database named " + name);
}
}
}
让调用者从数据源获取连接,并在完成使用后关闭它。
答案 1 :(得分:0)
您在查找不存在的数据源时捕获JNDI异常,但您的单例仍保留对先前查找的数据源的引用。作为A.B. Cade说,在异常时甚至在此之前对ds引用null。
更一般地说,也许使用Singleton不是最好的主意。