2

我想将以下 sql 中的所有数据放在一个地图中(因为这个 sql 被多次调用,而不是每次都去 db ),但我想知道如何为时间戳实现 <=

编辑:

我正在使用 Oracle,只是更新了标签,但是,我在 java 中使用 PreparedStatement 来缓存查询,而无需重新编译,但是我们的程序没有缓存解决方案来缓存表中的数据。去数据库并获取数据需要 2 毫秒的往返时间,但从 HashMap 获取数据需要一纳秒。该查询执行了大约 20,000 次,我们希望最初加载所有数据并将其放入 Hashmap 中。

编辑结束。

SELECT ar   
FROM table1   
WHERE fk_col1 = ?   
AND timestamp_col <= ?   
ORDER BY date DESC 

我这样做的方式如下:但我不确定,equals和hashCode中的timestamp_col是否正确。你能建议修改吗?

public class Table1Key
{
    private String fk_col1;
    private java.sql.Timestamp timestamp_col;
    //setters and getters here.
    //implementing hashCode and equals.
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((fk_col1 == null) ? 0 : fk_col1.hashCode());
        result = prime * result
                + ((timestamp_col == null) ? 0 : timestamp_col.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Table1Key other = (Table1Key) obj;
        if (fk_col1 == null) {
            if (other.fk_col1 != null)
                return false;
        } else if (!fk_col1.equals(other.fk_col1))
            return false;
        if (timestamp_col == null) {
            if (other.timestamp_col != null)
                return false;
        } else if (!timestamp_col.equals(other.timestamp_col))
            return false;
        return true;
    }
}

...

private Map<Table1Key, String> map = Functions.getHashMapInstance();

public class Functions {
...
  public static <K,V> HashMap<K,V> getHashMapInstance() {
      return new HashMap<K,V>();
  }
}

所以,我会像下面这样填充地图:

private void populateMap() throws SQLException {
      try {
        ps = conn.prepareStatement(table1Sql);
        ps.setFetchSize(20000);
        ResultSet rs = ps.executeQuery();
        while(rs.next()) {
            Table1Key rdk = new Table1Key();
            String ar = rs.getString(1);
            rdk.setFk_col1(rs.getString(2));
            rdk.setTimestampCol(rs.getTimestamp(3));
            if(actualRateMap.get(rdk) == null) {
                actualRateMap.put(rdk, ar);
            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
        throw e;
    } finally {
        ps.close();
    }
  }

//在这里设置密钥。

Table1Key tk = new Table1Key();
tk.setFk_col1(col1);
tk.setTimestampCol(timestamp);
String ar = actualRateMap.get(tk);

//我主要关心的是..如果sql有timestamp_col =?这将起作用,但是如果timestamp_col <而不是地图中存在的值怎么办?

if(actualRate != null) {
    Logger.info("Actual Rate:"+actualRate);
}
4

2 回答 2

2

HashMap不适合您的情况,而TreeMap可以提供帮助。

a): RangeMap解决方案

Guava RangeMap旨在处理这种情况:

//Initial RangeMap  
final RangeMap<java.sql.Timestamp, String> cache = TreeRangeMap.create();
...
String value = cache.get(thisTimestamp);
if(value == null){
     String queryFromDB = ...;//Query from DB
     cache.put(Range.atMost(thisTimestamp), queryFromDB);
     value = queryFromDB;
}

当然,'fk_coll' 是个问题。所以你可以定义Map<String/*fk_coll*/, RangeMap<java.sql.Timestamp, String>>来处理这个案子。

b):TreeMap解决方案

final TreeMap<java.sql.Timestamp, String> cache = new TreeMap<>();
...
//Get least key greater than or equal to the 'thisTimestamp' 
Map.Entry<java.sql.Timestamp, String> entry = cache.ceilingEntry(thisTimestamp);
if(entry == null){
   String queryFromDB = ...;//Query from DB
   cache.put(thisTimestamp, queryFromDB);
   value = queryFromDB;
} else {
   value = entry.getValue();
}

HashMap<String/*fk_coll*/, TreeMap<java.sql.Timestamp, String>>

处理“fk_coll”。

加:驱逐在任何缓​​存情况下都是一个问题。

于 2013-02-15T16:57:41.927 回答
0

虽然 HashMap 没有指定元素的顺序,但 TreeMap 可以。我没有测试以下代码,但我想它应该可以工作:

TreeMap<Timestamp, String> map = new TreeMap<Timestamp, String>(new Comparator<Timestamp>() {
    public int compare(Timestamp t1, Timestamp t2) {
       // Inverse order is required for using tailMap() as <= operator
       return t2.compareTo(t1);
    }

    public boolean equals(Object o) {
       throw new UnsupportedOperationException("This operation has not been implemented!");
    }
});
// TODO: insert data to the map
// ...

// Get the first key that is <= timestamp (remember that map is using inverse order)
TreeMap<Timestamp, String> tailMap = map.tailMap(timestamp);
Timestamp firstKey = tailMap.firstKey();
if (firstKey != null) {
  // Get the value
  String value = tailMap.get(firstKey);
}
于 2013-02-15T17:20:53.767 回答