MongoDB的存储是基于文档的,区别于以往的关系型数据库,它的数据模式可以更加宽松灵活,特别适合日益多变的互联网应用。在最开始接触MongoDB的时候就被它JavaScript式的操作所吸引,更被JSON式的数据存储所震撼。当时就有一种直觉,这将极大简化应用接口的开发工作,使得数据交互变得异常轻松。下面我将以示例代码的方式介绍我的使用方法。
本示例代码使用了如下开发包:
MongoDB的官方Driver包:mongo-2.7.3.jar
基于MongoDB的ORM产品:morphia-0.99.jar
性能与功能都很棒的Jackson JSON:jackson-all-1.9.3.jar
另外还要辅助一些其他的依赖包:
morphia-logging-slf4j-0.99.jar
slf4j-api-1.6.1.jar
slf4j-nop-1.6.1.jar
相关链接:
MongoDB安装为Windows服务方法与注意事项:http://blog.csdn.net/chaijunkun/article/details/7227967
Java中JSON解析器的一点见解:http://blog.csdn.net/chaijunkun/article/details/7208828
上面的两篇文章是本人总结的一些经验之谈。作为参考,朋友们可以在遇到问题的时候参阅上面两篇文章。
下面进入正题:
我的思路分为两方面,即数据的输入和数据的输出。
输入源是一个文本文件,其中的数据来自SQL Server中的Northwind示例数据库。具体来说是从其中的订单信息中抽离出相关联的部分,经过加工整理而成。(数据已经上传到CSDN资源频道,下载地址:http://download.csdn.net/detail/chaijunkun/4067684,不要资源分哦!)通过按行读取文件中的内容模拟Web应用各客户端发来的数据,然后将它们存储到MongoDB中;
输出部分将实现一个按条件查询,从MongoDB中得到的查询结果将通过控制台输出。这样就能模拟Web应用服务端响应请求,将数据推送到客户端页面的场景了。
(特别注意:本文中设计到的所有源代码都是UTF-8格式编码的)
先实现一个连接属性的配置
public class MongoDBConnConfig { //MongoDB主机名称或IP public static final String SERVER= "localhost"; //MongoDB端口 public static final int PORT= 27017; //使用的数据库名称 public static final String ORDERS_DATABASE= "orders"; }
再实现一个Morphia框架与MongoDB的集成方法
/** * MongoDB联合Morphia框架生成DataStore的类 * */ public class MongoDBDataStore { /** * 生成Orders数据库Datastore对象 * @return 返回Datastore对象 发生异常返回为null */ public static Datastore getOrdersInstance(){ Mongo connection = null; try { connection = new Mongo(MongoDBConnConfig.SERVER, MongoDBConnConfig.PORT); } catch (UnknownHostException e) { return null; } catch (MongoException e) { return null; } Morphia morphia= new Morphia(); return morphia.createDatastore(connection, MongoDBConnConfig.ORDERS_DATABASE); } }
我们还需要一个Java对象到MongoDB文档和Java对象到输出JSON对象的POJO实体:
//morphia中的注解 标明该对象存入orderInfo集合中 并且不存储类名 @Entity(value="orderInfo", noClassnameStored= true) public class OrderInfo { //morphia中的注解 标明该key为标识字段(MongoDB中特殊的ObjectId字段) @Id //Jackson中的注解 标明在序列化与反序列化过程中不使用该key @JsonIgnore(value= true) private ObjectId id; private Long orderId; private String productName; private Integer quantity; private Float unitPrice; //Jackson中的注解 标明该字段使用自定义的DateSerializer类实现序列化 @JsonSerialize(using= DateSerializer.class) //Jackson中的注解 标明该字段使用自定义的DateDeserializer类实现反序列化 @JsonDeserialize(using= DateDeserializer.class) private Date orderDate; private String contactName; private String address; private String phone; @SuppressWarnings("unused") //morphia中的注解 指示在存入MongoDB之前的操作 @PrePersist private void beforeSaving(){ System.out.println("即将保存对象:"+ this.toString()); } @SuppressWarnings("unused") //morphia中的注解 指示在存入MongoDB之后的操作 @PostPersist private void afterSaving(){ System.out.println("对象保存完毕:"+ this.toString()); } // 以下就是Getters和Setters了 // ....
我们注意到上面的POJO实体中包含Date(日期)类型的数据。这类数据特别指定了它的序列化与反序列化方法,下面我们来具体看一下:
序列化方法:DateSerializer.java
public class DateSerializer extends JsonSerializer<Date>{ @Override public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String formatedDate= sdf.format(date); jsonGenerator.writeString(formatedDate); } }
这其实是Jackson中的一个很实用的功能,通过自定义序列化器,可以实现Java对象到JSON的数据格式自定义。例如Date的格式我们可以任意改写。上面的泛型类被具象为Date类型。重写了serialize方法。输入的date参数就是将要被序列化的数据,jsonGenerator就是序列化的上下文。当数据内容被整理好后将内容写入序列化的上下文中就完成了自定义过程。
public class DateDeserializer extends JsonDeserializer<Date>{ @Override public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { String unformatedDate= jsonParser.getText(); SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date retVal; try { retVal = sdf.parse(unformatedDate); } catch (ParseException e) { return null; } return retVal; } }
泛型的JSON反序列化类被我们具象成了Date类型的,并且重写了deserialize方法。传入的jsonParser是反序列化过程中的上下文,通过它我们可以找到当前处理的JSON字段内容。然后将内容按照特定的要求来生成对应的数据类型(Date),然后作为返回值将其返回。此时POJO中相应的字段就顺利完成了反序列化。另外这样做还能保证类型安全。
再来看如何将数据输入MongoDB:
public class JSONTransformData { public static void main(String[] args) throws UnknownHostException, MongoException{ //创建Jackson全局的objectMapper 它既可以用于序列化 也可以用于反序列化 ObjectMapper objectMapper= new ObjectMapper(); //得到JSON处理的工厂对象 JsonFactory jsonFactory= objectMapper.getJsonFactory(); //得到Morphia框架的Datastore对象用于数据库操作 Datastore ds= MongoDBDataStore.getOrdersInstance(); //为保证每次本程序都得到相同结果 需要将之前的过期数据库删除 ds.getMongo().dropDatabase(MongoDBConnConfig.ORDERS_DATABASE); //进入读文件阶段 File dataFile= new File("jsonData.txt"); FileReader fr; Integer idx=1; try { fr = new FileReader(dataFile); BufferedReader br=new BufferedReader(fr); String currentJsonStr= null; try { //按行读取 while((currentJsonStr= br.readLine())!=null){ currentJsonStr= new String(currentJsonStr.getBytes(), "UTF-8"); if (currentJsonStr.trim().equals("")){ continue; } //进入反序列化阶段 //通过JSON处理工厂对象创建JSON分析器 JsonParser jsonParser= jsonFactory.createJsonParser(currentJsonStr); //反序列化的关键 OrderInfo orderInfo= jsonParser.readValueAs(OrderInfo.class); if (orderInfo!=null){ //将对象存入MongoDB Key<OrderInfo> key= ds.save(orderInfo); if (key!= null){ System.out.println("已存入:"+ key.getId() + ",元素序列:"+ idx); System.out.println(currentJsonStr); }else{ System.out.println("元素序列"+ idx+ "发生错误,JSON:"); System.out.println(currentJsonStr); break; } } idx++; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
通过代码中的注释,我们不难理解各行代码的含义。并且整个代码也很简洁。
以下是运行结果片段:
即将保存对象:net.csdn.blog.chaijunkun.entities.OrderInfo@1f8d244 对象保存完毕:net.csdn.blog.chaijunkun.entities.OrderInfo@1f8d244 已存入:4f3ca1785a27520bbb93c4c5,元素序列:2152 {"orderId":11077, "productName":"Louisiana Hot Spiced Okra", "quantity":1, "unitPrice":17.00, "orderDate":"1998-05-06 00:00:00", "contactName":"Paula Wilson", "address":"2817 Milton Dr.", "phone":"(505) 555-5939"} 即将保存对象:net.csdn.blog.chaijunkun.entities.OrderInfo@b48b11 对象保存完毕:net.csdn.blog.chaijunkun.entities.OrderInfo@b48b11 已存入:4f3ca1785a27520bbb93c4c6,元素序列:2153 {"orderId":11077, "productName":"R?d Kaviar", "quantity":2, "unitPrice":15.00, "orderDate":"1998-05-06 00:00:00", "contactName":"Paula Wilson", "address":"2817 Milton Dr.", "phone":"(505) 555-5939"} 即将保存对象:net.csdn.blog.chaijunkun.entities.OrderInfo@1f8d244 对象保存完毕:net.csdn.blog.chaijunkun.entities.OrderInfo@1f8d244 已存入:4f3ca1785a27520bbb93c4c5,元素序列:2152 {"orderId":11077, "productName":"Louisiana Hot Spiced Okra", "quantity":1, "unitPrice":17.00, "orderDate":"1998-05-06 00:00:00", "contactName":"Paula Wilson", "address":"2817 Milton Dr.", "phone":"(505) 555-5939"} 即将保存对象:net.csdn.blog.chaijunkun.entities.OrderInfo@b48b11 对象保存完毕:net.csdn.blog.chaijunkun.entities.OrderInfo@b48b11 已存入:4f3ca1785a27520bbb93c4c6,元素序列:2153 {"orderId":11077, "productName":"R?d Kaviar", "quantity":2, "unitPrice":15.00, "orderDate":"1998-05-06 00:00:00", "contactName":"Paula Wilson", "address":"2817 Milton Dr.", "phone":"(505) 555-5939"}
最后我们再来看一下查询的结果如何进行反序列化:
public class JSONQueryDemo { public static void main(String[] args) throws UnknownHostException, MongoException { //创建Jackson全局的objectMapper 它既可以用于序列化 也可以用于反序列化 ObjectMapper objectMapper= new ObjectMapper(); //得到Morphia框架的Datastore对象用于数据库操作 Datastore ds= MongoDBDataStore.getOrdersInstance(); //按条件进行查询 这里的条件是orderId等于10875的所有信息 //这里特别注意key和条件关系式"="之间要有空格 Query<OrderInfo> queryResult= ds.find(OrderInfo.class, "orderId =", 10875); //创建查询结果的迭代器 Iterator<OrderInfo> it= queryResult.iterator(); //遍历查询结果 while(it.hasNext()){ OrderInfo orderInfo= it.next(); System.out.println("================================================"); //由于Jackson写出JSON内容时统一采用流式写出 //为了以字符串形式能够展示生成的JSON 这里特别用到了StringWriter StringWriter sw= new StringWriter(); JsonGenerator jsonGenerator= null; try { //从全局的objectMapper建立JSON处理工厂,随即建立JSON生成器 jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(sw); //流式向StringWriter中写入JSON jsonGenerator.writeObject(orderInfo); jsonGenerator.flush(); jsonGenerator.close(); //输出的JSON字符串 System.out.println(sw.toString()); } catch (IOException e) { e.printStackTrace(); } } System.out.println("查询完成"); } }
下面是查询结果:
{"orderId":10875,"productName":"Teatime Chocolate Biscuits","quantity":25,"unitPrice":9.2,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} ================================================ {"orderId":10875,"productName":"Zaanse koeken","quantity":21,"unitPrice":9.5,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} ================================================ {"orderId":10875,"productName":"Maxilaku","quantity":15,"unitPrice":20.0,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} 查询完成 ================================================ {"orderId":10875,"productName":"Teatime Chocolate Biscuits","quantity":25,"unitPrice":9.2,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} ================================================ {"orderId":10875,"productName":"Zaanse koeken","quantity":21,"unitPrice":9.5,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} ================================================ {"orderId":10875,"productName":"Maxilaku","quantity":15,"unitPrice":20.0,"orderDate":"1998-02-06 12:00:00","contactName":"Christina Berglund","address":"Berguvsv?gen 8","phone":"0921-12 34 65"} 查询完成
我们看到,查询出的结果已经按照我们的约定方式进行显示了。
本文总结了一套完整的利用MongoDB与Jackson JSON框架结合实现快速开发应用接口的例子。在实际生产环境中,如果需求有所变动,我们完全可以通过更改POJO实体的方法来随意扩展。希望以上例子能给朋友们一点启发。也欢迎关注此技术的朋友一起探讨。
本文转自:http://www.uml.org.cn/sjjm/201203055.asp,为了方便查看手工排版了下。
相关推荐
利用MongoDB与Jackson JSON框架结合实现快速开发应用接口的例子,详情参见文章:http://blog.csdn.net/chaijunkun/article/details/7263804。
NULL 博文链接:https://cindy-zhong.iteye.com/blog/1939853
MongoDB的存储是基于文档的,区别...本示例代码使用了如下开发包:MongoDB的官方Driver包:mongo-2.7.3.jar基于MongoDB的ORM产品:morphia-0.99.jar性能与功能都很棒的JacksonJSON:jackson-all-1.9.3.jar另外还要辅助
包含jar(mongodb的实现类及实现接口(包含jar包))
mongodb创建库以及基本使用脚本说明.
Java对mongodb进行增删改查(CURD)的源码及调用接口和实现类,略有简陋,向各大拿讨教。
MongoDB练习文件
MongoDB的C#开发接口
Java 解析xml 存入mongodb 返回org.json json包
mongodb的开发和nio实现
[奥莱理] Node.js 应用程序开发 (MongoDB 及 Backbone 实现) (英文版) [奥莱理] Building Node Applications with MongoDB and Backbone (E-Book) ☆ 出版信息:☆ [作者信息] Mike Wilson [出版机构] 奥莱理 ...
7. 结合 Redis 模块和 MongoDB 模块,开发 HierarchicalModule 分层数据模型 构造一个 Redis 缓存层 + MongoDB 持久层的后台 Server 架构 并通过简单方便的接口供上层程序员使用,具体的数据分层处理对上层程序员...
MongoDB与jsp页面相结合的项目
此“帮助程序”的工作方式是将给定的Mongo $jsonSchema转换为可与任何模式验证库一起使用的标准模式。 例如 。 免责声明:由于我们缺乏官方支持,这是我目前发现的最有效方法。 安装 go get -u github....
python开发,基于flask-restful 的中小型项目,restful风格API接口开发实例,以mongodb作为数据库 python开发,基于flask-restful 的中小型项目,restful风格API接口开发实例,以mongodb作为数据库python开发,基于...
基于node.js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,适合用作毕业设计、课程设计作业等,项目均经过测试,可快速部署运行! 基于node.js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,...
此应用程序将使用nodeJS允许用户以.XML格式上传新的BAC,然后将其获取.xml文件,将xml转换为JSON,然后将这些数据存储在mongoDB集合中。 完成此操作后,它将BACSDirectory/archivedBACS旧的BAC目录并将其放在...
安装npm install @movenium/jsonapi-mongodb --save-dev 或者yarn add @movenium/jsonapi-mongodb 与serverless.com一起使用向您的处理程序中添加两个http事件 events: - ...您需要添加到处理程序中 const apiClass = ...
C#\MongoDB应用开发实战\MongoDB
利用mongodb作为数据库,建立数据表以及定义字段,通过express实现接口,同源策略设置对所有IP开放,实现的一个开放式的接口案例