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结合时,它们能够共同支持快速、敏捷的接口开发。 在接口开发中,MongoDB可以作为后端数据存储,提供对非关系型数据的强大支持。它的灵活性允许快速创建和查询复杂的文档结构,而无需预先定义...
利用MongoDB与Jackson JSON框架结合实现快速开发应用接口的例子,详情参见文章:http://blog.csdn.net/chaijunkun/article/details/7263804。
总之,这些文件展示了如何在Java中通过自定义的接口和实现类与MongoDB交互。`IMongoJDBCUtilCJB.java`定义了基本的CRUD操作,`IMongoDBJDBCImp.java`实现了这些操作,而`IMongoDBJDBC.java`可能扩展了更多的功能。这...
mongodb创建库以及基本使用脚本说明.
在实际开发中,这样的设计可以帮助开发者利用已有的JDBC经验快速上手MongoDB,并且通过自定义接口可以灵活地切换不同的MongoDB操作实现,比如更换不同版本的MongoDB驱动或者引入其他的MongoDB操作工具。 总结来说,...
Java作为后端开发的重要语言,提供了丰富的库来处理XML数据,并与MongoDB进行交互。本篇将详细介绍如何使用Java解析XML,将数据存入MongoDB,并返回org.json JSON包。 首先,解析XML通常有两种主要方法:DOM...
MongoDB练习文件
MongoDB的C#开发接口是用于在C#应用程序中与MongoDB数据库进行交互的重要工具,它使得.NET开发者能够轻松地存取、管理以及操作MongoDB数据。MongoDB是一款流行的开源文档型数据库,以其灵活的数据模型、高性能和高...
总的来说,MongoDB的开发结合NIO技术,可以构建出高性能、高并发的数据库应用。开发者不仅需要深入理解MongoDB的数据模型和操作,还要熟练掌握Java NIO的原理和实践,才能充分发挥两者的优势。在实际项目中,可以...
将MongoDB与Helma结合使用,可以创建出高效的Web开发解决方案。MongoDB作为数据存储后端,负责处理和存储大量的数据,而Helma则作为前端服务器,负责处理HTTP请求,执行业务逻辑,并通过模板引擎生成响应。 在使用...
将MongoDB与D3.js结合,可以实现高效的数据展示和分析,尤其在大数据量的场景下。 MongoDB的核心特性包括其NoSQL的数据模型,支持JSON格式的文档存储,这使得数据的读写操作更为便捷。它的查询语言MQL(MongoDB ...
MongoDB、Gin和WebSocket是...综上所述,这个项目展示了如何结合MongoDB、Gin和WebSocket构建一个实时的Web通信系统,涵盖了数据存储、后端API开发和实时通信的核心技术,对于学习和实践Web开发有着很高的参考价值。
在现代Web应用开发中,Spring Boot和MongoDB的结合是一个非常流行的选择,因为Spring Boot提供了强大的框架支持,而MongoDB则作为一个高效的文档型数据库,能够处理大量非结构化数据。本教程将深入探讨如何将Spring ...
MongoDB可以轻松地与各种开发框架和工具集成,如Express.js(MEAN stack的一部分)、Spring Boot、Django等,为开发人员提供便利。 通过深入学习这两本"MongoDB开发精要",你将掌握MongoDB的核心技术和最佳实践,...
此外,可以使用Spring Data MongoDB来简化CRUD操作,通过定义Repository接口,Spring会自动生成实现。 **问题与兼容性**: 在实际开发中,Spring和MongoDB版本之间的兼容性是常见的问题。不同版本的Spring框架可能...
现在,我们有了访问MongoDB数据的接口,可以通过JSP页面来实现数据的读取和展示。JSP是一种动态网页技术,它允许我们在HTML页面中嵌入Java代码。在JSP中,我们可以通过JavaBean或DAO(数据访问对象)来封装与MongoDB...
总的来说,"C#\MongoDB应用开发实战"课程将带你逐步掌握使用C#与MongoDB进行交互的各项技能,无论你是初学者还是有经验的开发者,都能从中受益,提升你的MongoDB开发能力。通过实际项目练习和理论知识的结合,你将...
[奥莱理] Node.js 应用程序开发 (MongoDB 及 Backbone 实现) (英文版) [奥莱理] Building Node Applications with MongoDB and Backbone (E-Book) ☆ 出版信息:☆ [作者信息] Mike Wilson [出版机构] 奥莱理 ...
python开发,基于flask-restful 的中小型项目,restful风格API接口开发实例,以mongodb作为数据库 python开发,基于flask-restful 的中小型项目,restful风格API接口开发实例,以mongodb作为数据库python开发,基于...