我试图创建一个访问器,以使用Java在Cassandra中运行稍微更复杂的查询。我的语法没有问题,可以正常使用,但是我的问题是:有没有一种方法可以在访问器中动态声明键空间?
例如,如果为MappingManager创建表映射,则将声明@Table并为其提供键空间和表名称,如下所示:
@Table(keypace="mykeyspace", name="orders")
public class Orders {
@PartitionKey
public UUID id;
//blah blah blah, rest of code
}
现在为该特定表创建访问器很容易:
@Accessor
public interface OrdersAccessor {
@Query("SELECT * FROM orders WHERE status = :status")
Result pending(@Param("status") Integer status);
}
简单。问题是它需要一个键空间,而且我是从不对任何事情进行硬编码的忠实拥护者。我意识到我正在“硬编码” MappingManager类定义中Table定义中的键空间,但是如果需要的话,我只在那里更改它并更新与此有关的所有内容。如果我对访问器内部的每个@Query定义中的键空间进行硬编码,则如果更新键空间,则可能必须更改一堆不同的项目,而不是仅在@Table定义中更改一个位置。
我已经在Google上搜索了几个小时,但找不到一个有人动态地声明带有访问器的键空间的实例,只有成千上万个访问器示例,它们将键空间硬编码到@Query中,如下所示:
@Accessor
public interface OrdersAccessor {
@Query("SELECT * FROM keyspace.orders WHERE status = :status")
Result pending(@Param("status") Integer status);
}
我意识到我编写的查询并不是访问器的真正原因,为了示例起见,我只是对其进行了简化。所以我来社区寻求帮助,我在任何地方都找不到任何示例。我无法想象我是有史以来第一个想要这样做的人,我只是找不到任何其他人解决这个问题的例子。预先感谢您提供的任何帮助,我真的可以使用。
最佳答案
@Sudhir这是我想出的解决方案。我确信有更好的方法来处理连接,但是对于cassandra和Java来说我还是很陌生,这对于我的需求来说很好用。我希望这有帮助...
public class DbInterface {
private Cluster cluster;
private Session session;
private Map<String, Session> dbMap;
private Map<String, Map<String, Mapper<Class>>> mappers = new ConcurrentHashMap<>();
public DbInterface(String host) {
Map<String, Session> connections = createConnection(host);
Session crSession = connections.get("crSession");
Session hppSession = connections.get("hppSession");
cluster = Cluster.builder().addContactPoint(host).build();
Session crSession = cluster.connect("mykeyspace");
Session hppSession = cluster.connect("hpp");
MappingManager crManager = new MappingManager(crSession);
MappingManager hppManager = new MappingManager(hppSession);
mappers.put("mykeyspace", new ConcurrentHashMap<>());
mappers.put("mykeyspace2", new ConcurrentHashMap<>());
Map cr = mappers.get("mykeyspace");
Map hpp = mappers.get("mykeyspace2");
cr.put("status", crManager.mapper(OrderStatus.class));
hpp.put("status", hppManager.mapper(OrderStatus.class));
cr.put("status_accessor", crManager.createAccessor(OrderStatusAccessor.class));
hpp.put("status_accessor", hppManager.createAccessor(OrderStatusAccessor.class));
cr.put("users", crManager.mapper(Users.class));
hpp.put("users", hppManager.mapper(Users.class));
cr.put("orders", crManager.mapper(Orders.class));
hpp.put("orders", hppManager.mapper(Orders.class));
cr.put("order_detail", crManager.mapper(OrderDetail.class));
hpp.put("order_detail", hppManager.mapper(OrderDetail.class));
cr.put("chal_orders", crManager.mapper(ChalOrder.class));
hpp.put("chal_orders", hppManager.mapper(ChalOrder.class));
cr.put("chal_order_detail", crManager.mapper(ChalOrderDetail.class));
hpp.put("chal_order_detail", hppManager.mapper(ChalOrderDetail.class));
cr.put("detail_accessor", crManager.createAccessor(OrderDetailAccessor.class));
hpp.put("detail_accessor", hppManager.createAccessor(OrderDetailAccessor.class));
cr.put("tracking_labels", crManager.mapper(TrackingLabels.class));
hpp.put("tracking_labels", hppManager.mapper(TrackingLabels.class));
}
public Session getConnection(String type) {
if(dbMap.containsKey(type)) {
return dbMap.get(type);
}
if(dbMap.containsKey(type.toLowerCase() +"Session")) {
return dbMap.get(type.toLowerCase() +"Session");
}
return dbMap.get("crSession");
}
public Map<String, Session> createConnection(String host) {
dbMap = new HashMap<>();
cluster = Cluster.builder().addContactPoint(host).build();
Session crSession = cluster.connect("mykeyspace");
Session hppSession = cluster.connect("hpp");
dbMap.put("crSession", crSession);
dbMap.put("hppSession", hppSession);
return dbMap;
}
public Map getDBMap(String client) {
if(mappers.containsKey(client)) {
return mappers.get(client);
}
throw new RuntimeException("Unknown Client: " + client);
}
}
我正在考虑做的一件事是将会话创建和Map创建移到单独的功能,然后仅连接并构建所需会话的地图。就像在调用DbInterface()时默认不连接到两个会话一样,仅连接到通过“主机”参数请求的会话。
任何人,希望这对您有所帮助。如果您需要它,这是我的另一个使用此库的示例。
public class MyRestController {
private final DbInterface db = new DbInterface(IPADDRESS);
@CrossOrigin
@RequestMapping("/status")
public String getStatus() {
Map managerMap = db.getDBMap("mykeyspace");
OrderStatusAccessor statuses = (OrderStatusAccessor) managerMap.get("status_accessor");
Result<OrderStatus> allStatuses = statuses.getAll();
//rest of the code here
}
}