ltf*_*hie 10 java mongodb nosql
像MongoDB这样的NoSQL数据存储的一个主要优点是它们是无模式的.使用动态类型语言,这似乎很自然.您可以接收一些任意JSON输入,在已知字段上执行业务逻辑,并在不必先定义对象的情况下保留整个事物.
如果您选择的语言仅限于静态类型,比如Java,该怎么办?我怎样才能达到同样的灵活性?
典型的数据流如下:
其中序列化到对象步骤是必要的,因为您想要使用POJO而不是JSON字符串执行业务逻辑.但是,在我将输入序列化为对象之前,我必须首先定义它.如果输入包含对象中未定义的其他字段,该怎么办?虽然它们可能不会用于业务逻辑,但我仍然希望能够坚持它们.我似乎已经将未定义的字段放入地图中,但我不确定这是否是最好的方法.首先,未定义的字段也可以是复杂的对象.
无架构数据不一定意味着无结构数据; 这些字段通常是预先知道的,并且可以在其上应用一些类型安全的模式以避免Magic Container反模式但是情况并非总是如此.有时键是由用户输入的,并且不能提前知道.
我已经多次使用角色对象模式来使动态结构保持一致.我认为它适用于这两种情况.
角色对象模式定义了访问对象的不同视图的方法.规范示例是可以承担多个角色的用户,例如客户,供应商和卖方.这些视图中的每一个都可以执行不同的操作,并且可以从任何其他视图访问.通用字段通常在接口级别可用(特别是userId()在您的情况下toJson()).
以下是使用该模式的示例:
public void displayPage(User user) {
display(user.getName());
if (user.hasView(Customer.class))
displayShoppingCart(user.getView(Customer.class);
if (user.hasView(Seller.class))
displayProducts(user.getView(Seller.class));
}
Run Code Online (Sandbox Code Playgroud)
对于具有已知结构的数据,您可以使用多个视图将不同的键集合转换为内聚单元.这些不同的视图可以读取构造中的json数据.
在具有动态结构的数据的情况下,权威的RawDataView可以使用其动态形式的数据(即,像a 的Magic容器HashMap<String, Object>).这可用于查询动态数据.同时,可以懒惰地创建类型安全的包装器,并且可以委托给RawDataView来协助程序的可读性/可维护性:
public class Customer implements User {
private final RawDataView data;
public CustomerView(UserView source) {
this.data = source.getView(RawDataView.class);
}
// All User views must specify this
@Override
public long id() {
return data.getId();
}
@Override
public <T extends UserView> T getView(Class<T> view) {
// construct or look up view
}
@Override
public Json toJson() {
return data.toJson();
}
//
// Specific to Customer
//
public List<Item> shoppingCart() {
List<Item> items = (List<Item>) data.getValue("items", List.class);
}
// etc....
}
Run Code Online (Sandbox Code Playgroud)
我用这两种方法都取得了成功.以下是我在此过程中发现的一些额外指示:
_userId)equals()并hashcode()实现user.getView(A.class).equals(user.getView(B.class))了对于同一用户始终如此.toJson())返回公共字段(如userId()); 并实施equals()和hashcode().让所有视图委托给这个核心对象hasView()方法或getView返回来完成Optional<T>| 归档时间: |
|
| 查看次数: |
1318 次 |
| 最近记录: |