繁体   English   中英

自动打开和关闭连接

[英]Automatically opening and closing connection

instead of multiple vargs . 注意:请忽略我使用而不是多个vargs

Java中有这样做的标准方法吗?

我所拥有的是从远程服务器返回的资源。 但是在每个查询之前,必须打开远程连接,并在返回返回之后–必须关闭它。

因此,执行此操作的自然方法是:

Connection c = config.configureConnection();
c.open();       //open
List<Car> cars;
try{
   cars = c.getCars();
}finally{
   c.close();   //close
}

现在,我想实现一些在资源本身级别上运行的操作,而不必担心连接,例如:

List<Car> cars = new CarResource().all(); //opens and closes connection

and , which any class extending it must implement. 我目前的操作方式是通过一个抽象类AbstractQueriable调用抽象方法 ,任何扩展它的类都必须实现。

, and - which are the public facing methods. AbstractQuerieable实现了Queriable接口,从而使它公开了三个公共方法 -它们是面向公众的方法。

这是Queriable接口:

public interface Queriable <T>{
    public T get(String id);
    /** Simply returns all resources */
    public Collection<T> all(); 
    public Collection<T> filter(MultivaluedMap<String, String> args);   
}

这是实现它的AbstractQueriable类:

public abstract class AbstractQueriable<T> implements Queriable<T> {

@Override
public final T get(String id) {
    setup();
    try {
        return query(id);
    } finally {
        cleanup();
    }
}

@Override
public final Collection<T> filter(MultivaluedMap<String, String> args) {
    setup();
    try {
            return query(args);
    } finally {
        cleanup();
    }
}

/**
 * Returns all resources.
 * 
 * This is a convenience method that is equivalent to passing an empty
 * arguments list to the filter function.
 * 
 * @return The collection of all resources if possible
 */
    @Override
public final Collection<T> all() {      
    return filter(null);
}

/**
 * Queries for a resource by id.
 * 
 * @param id
 *            id of the resource to return
 * @return
 */
protected abstract T query(String id);

/**
 * Queries for a resource by given arguments.
 * 
 * @param args
 *            Map of arguments, where each key is the argument name, and the
 *            corresponing values are the values
 * @return The collection of resources found
 */
protected abstract Collection<T> query(MultivaluedMap<String, String> args);

private void cleanup() {
    Repository.close();
}

private void setup() {
    Repository.open();
}

最后,例如,我想在代码中使用的资源必须扩展AbstractQueriable类(请注意,这些方法的细节并不重要):

public class CarRepositoryResource extends AbstractQueriable<Car> {

    @Override
    protected Car query(String id) {
        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
        params.add("CarID", id);

        // Delegate the query to the parametarized version
        Collection<cars> cars = query(params);
        if (cars == null || cars.size() == 0) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        if (cars.size() > 1) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return cars.iterator().next();
    }

    @Override
    protected Collection<Car> query(MultivaluedMap<String, String> params) {
        Collection<Car> cars = new ArrayList<Car>();        

        Response response = Repository.getConnection().doQuery("Car");
        while (response.next()) {
            Returned returned = response.getResult();
            if (returned != null) {
                cars.add(returned);
            }
        }
        return cars;
    }

}

最后,我可以在代码中使用:

Collection<Car> cars = new CarRepositoryResource().all();
//... display cars to the client etc...

对于这种设置,我有些不满意的地方:

  1. 每次执行查询时,我都必须实例化“ CarRepositoryResource”的新实例。
  2. 方法名称“ query”,尽管是内部的和私有的,但仍然令人困惑和笨拙。
  3. 我不确定是否有更好的模式或框架。

我正在使用的连接不支持/实现JDBC api,也不基于sql。

您可以在视图模式中使用著名的Open会话的变体。

基本上可以归结为:

  1. 定义一个可用连接的“上下文”(通常是Web应用程序中的请求)
  2. 进入/退出上下文时处理(可能是惰性的)初始化和释放连接
  3. 将您的方法编码为理所当然的,它们只会在这样的上下文中使用

实现起来并不难(将连接存储在静态ThreadLocal中以使其成为线程安全),并且肯定会省去一些打开/关闭调用(在性能方面可能会获得很大的收益,具体取决于连接的强度)。

上下文类可能类似于(考虑此伪代码);

public class MyContext{
  private static final
  ThreadLocal<Connection> connection = new ThreadLocal<Connection>();

  public static void enter() {
     connection.set(initializeConnection());
     // this is eager initialization
     // if you think it will often the case that no connection is actually
     // required inside a context, you can defer the actual initialization
     // until the first call to get()
  }

  public static void exit() {
    try { connection.close(); }
    catch(Throwable t) { /* panic! */ }
    finally { connection.set(null); }
  }

  public static Connection get() {
    Connection c = connection.get();
    if (c == null) throw new IllegalStateException("blah blah");
    return c;
  }
}

然后,您将使用如下连接:

MyContext.enter();
try {
   // connections are available here:
   // anything that calls MyContext.get()
   // gets (the same) valid connection instance
} finally {
  MyContext.exit();
}

此块可以放在任何位置(在webapp中,它通常包装每个请求的处理)-从main方法开始(如果您要编写一个简单的案例,当您希望在整个应用程序的整个生命周期中都可以使用单个连接时) API中的方法。

您可能想看一看流畅的 界面在这里有一个有趣的示例)及其“构建器”模式。

您将这样查询:

cars().in(DB).where(id().isEqualTo(1234));

例如,通过这种方法,您可以在最外面的cars()方法中隐藏连接/断开连接代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM