4

Its more like subjective question, The main objective of the question is to Cache java.sql.ResultSet. But I know it is not preferred mechanism as it is tightly coupled with Connection, and data may get flushed when the connection is closed. To address this issue, I am using CachedRowSet. The instance of CachedRowSet will be cached using third party caching tool, which will help me to reduce db calls.

Code snippet of my implementation is given below. The method executeQuery(String) is implemented in an abstract class, which all sub classes would use to execute the query. There could be customer subclasses as well using this method to fetch data from our system.

public final ResultSet executeQuery(String query){
        try {
        // return data if it is available in cache, else execute and store in cache
            CachedRowSet cachedRowSet=getDataFromCache(query);
            if(cachedRowSet!=null) {
                return cachedRowSet;   
            }
            PreparedStatement statement=getStatment();
            ResultSet rs= statement.executeQuery(query);
            CachedRowSet cachedRowSet=new CachedRowSetImpl();
            cachedRowSet.populate(rs);
                    cachedData(cachedRowSet);
            return cachedRowSet;
        } catch (Exception e) {
            return null;
        }
    }

Now, I am bit confused with below points

  1. Instead of ResultSet interface, I will return instance of CachedResultSet. Would be that correct replacement for resultSet. Driver JAR,DB classes can be varying across customer environment. Customer would write custom classes and expecting a resultSet from Abstract class. Would that cause any issue? Some thing like below

    public class CustomerXX extends BaseClass {

    public void process(String query){
    
        ResultSet rs = executeQuery(query);
    
        //process rs to fetch data
    
    }
    

    }

  2. Risk involved in this kind of operation( Caching CachedRowSet, data correctness)

  3. Performance of creating CachedRowSet

  4. Compatibility with all ResultSet operations ( ResultSet.getString(), ResultSet.get..()). If at all Driver expect/produces different subclass of ResultSet ( Say jdbcResultSet,BaseResultSet, etc)

I have similar kind of many other question is my mind, I am just writing few of them that I feel valid and has higher priority.

Not sure my question is so vague, does have enough clarity of my requirements.

Any ideas, thoughts, suggestions are highly appreciated, and many thanks in advance

4

1 回答 1

4

实现自定义CachedRowSet可能会很痛苦,因为您已经实现了ResultSet接口公开的所有方法。

我建议不要在 jdbc 级别缓存,而是在数据访问层缓存一些值对象。

例如,如果您使用带有 id、name 和 email 列的用户表,您可以有以下值对象

class User {
    Long id;
    String name;
    String email;
} 

接下来可以介绍数据访问层

interface UserRepository {
    List<User> retrieveUsers();
}

使用从数据库加载数据的默认 JdbcUserRepository。

缓存可以使用代理模式来实现:

class CachingUserRepository implements UserRepository {
    private Cache cache;
    private UserRepository delegate;

    List<User> retrieveUsers() {
        List<User> result = cache.get(USERS_KEY);
        if (result == null) {
            result = delegate.retrieveUsers();
        }

        return result;
    }

}

实现缓存是最具挑战性的部分。您必须担心:

  1. 并发 - 多个线程将访问缓存
  2. 内存 - 缓存可能变得太大,可能会发生 OutOfMemoryException。

我建议使用一些现有的缓存解决方案,而不是编写自己的解决方案。我发现google guava稳定且易于使用。

于 2012-10-21T20:13:16.790 回答