一.简介
今天我们要介绍Java代码实现对MongoDB实现添加和删除操作。
二.添加
Spring Data MongoDB 的MongoTemplate提供了两种存储文档方式,分别是save和insert方法,这两种的区别:
(1)save :我们在新增文档时,如果有一个相同_ID的文档时,会覆盖原来的。
(2)insert:我们在新增文档时,如果有一个相同的_ID时,就会新增失败。
1.接下来我们分别介绍的两种方式的具体语法。
(1)Save方式
方法:
1)void save (Object objectToSave) 保存文档到默认的集合。
2)void save(Object objectToSave, String collectionName) 对指定的集合进行保存。
(2) Insert方式
方法:
1)void insert(Object objectToSave) 保存文档到默认的集合。
2)void insertAll(Object objectsToSave) 批量添加到默认的集合。
3)void insert(Object objectToSave, String collectionName) 对指定的集合进行保存。
2. Spring实现MongoDB的添加操作
我们在上一篇有介绍了,Spring Data MongoDB环境的搭建,这里不在具体介绍,我们直接实战。
(1)介绍接口以及实现方法
第一步:实现一个基础接口,是比较通用的 MongoBase.java类
[java] view plain copy
1. public interface MongoBase<T> {
2. // insert添加
3. public void insert(T object,String collectionName);
4. // save添加
5. public void save(T object,String collectionName);
6. //批量添加
7. public void insertAll(List<T> object);
8. }
第二步:我们实现文档的结构,也是实体类。
我们这边有两个实体类,订单类(Orders.java)和对应订单详情类(Item.java),这里我们实现内嵌文档。如果没有内嵌文档的结构,只要对一个实体类的操作就OK。
1)Orders.Java
[java] view plain copy
1. /**
2. * 订单
3. * @author zhengcy
4. *
5. */
6. public class Orders implements Serializable {
7. /**
8. *
9. */
10. private static final long serialVersionUID = 1L;
11. //ID
12. private String id;
13. //订单号
14. private String onumber;
15. //日期
16. private Date date;
17. //客户名称
18. private String cname;
19. //订单
20. private List<Item> items;
21.
22. public String getId() {
23. return id;
24. }
25. public void setId(String id) {
26. this.id = id;
27. }
28. public Date getDate() {
29. return date;
30. }
31. public void setDate(Date date) {
32. this.date = date;
33. }
34. public String getCname() {
35. return cname;
36. }
37. public void setCname(String cname) {
38. this.cname = cname;
39. }
40. public String getOnumber() {
41. return onumber;
42. }
43. public void setOnumber(String onumber) {
44. this.onumber = onumber;
45. }
46. public List<Item> getItems() {
47. return items;
48. }
49. public void setItems(List<Item> items) {
50. this.items = items;
51. }
52.
53. }
2) Item.java
[java] view plain copy
1. /**
2. * 产品订购表
3. * @author zhengcy
4. *
5. */
6. public class Item {
7.
8. //数量
9. private Integer quantity;
10. //单价
11. private Double price;
12. //产品编码
13. private String pnumber;
14. public Integer getQuantity() {
15. return quantity;
16. }
17. public void setQuantity(Integer quantity) {
18. this.quantity = quantity;
19. }
20. public Double getPrice() {
21. return price;
22. }
23. public void setPrice(Double price) {
24. this.price = price;
25. }
26. public String getPnumber() {
27. return pnumber;
28. }
29. public void setPnumber(String pnumber) {
30. this.pnumber = pnumber;
31. }
32. }
第三步:实现OrdersDao类,就是实现Orders自己操作数据库的接口,这个OrdersDao也继承了MongoBase接口,我们这边OrdersDao没实现其他额外的接口。
[java] view plain copy
1. /**
2. * 订单Dao
3. * @author zhengcy
4. *
5. */
6. public interface OrdersDao extends MongoBase<Orders> {
7.
8.
9. }
第四步:实现OrdersDaoImpl具体类,这边是实际操作数据库。
[java] view plain copy
1. /**
2. * 订单实现
3. * @author zhengcy
4. *
5. */
6. @Repository("ordersDao")
7. public class OrdersDaoImpl implements OrdersDao {
8. @Resource
9. private MongoTemplate mongoTemplate;
10.
11. @Override
12. public void insert(Orders object, String collectionName) {
13. mongoTemplate.insert(object, collectionName);
14.
15. }
16.
17.
18. @Override
19. public void save(Orders object, String collectionName) {
20. mongoTemplate.save(object, collectionName);
21.
22. }
23.
24. @Override
25. public void insertAll(List<Orders> objects) {
26. mongoTemplate.insertAll(objects);
27.
28. }
29. }
(2)实现测试类,我们进行测试
我们这边为了节省时间,就没写服务类,我们直接调用dao就可以了,实现了TestOrders.java类
[java] view plain copy
1. /**
2. * 测试订单
3. * @author zhengcy
4. *
5. */
6. public class TestOrders {
7. private static OrdersDao ordersDao;
8. private static ClassPathXmlApplicationContext app;
9. private static String collectionName;
10. @BeforeClass
11. public static void initSpring() {
12. try {
13. new ClassPathXmlApplicationContext(new String[] { "classpath:applicationContext-mongo.xml",
14. "classpath:spring-dispatcher.xml" });
15. "ordersDao");
16. "orders";
17. catch (Exception e) {
18. e.printStackTrace();
19. }
20. }
21.
22. //测试Save方法添加
23. @Test
24. public void testSave() throws ParseException
25. {
26.
27. }
28. //测试Insert方法添加
29. @Test
30. public void testInsert() throws ParseException
31. {
32.
33. }
34. //测试InsertAll方法添加
35. @Test
36. public void testInsertAll() throws ParseException
37. {
38.
39. }
40. }
1)测试Save方法添加
[java] view plain copy
1. //测试Save方法添加
2. @Test
3. public void testSave() throws ParseException
4. {
5. new SimpleDateFormat("yyyy-mm-dd");
6. //订单
7. new Orders();
8. "001");
9. "2015-07-25"));
10. "zcy");
11. //订单详情
12. new ArrayList<Item>();
13. new Item();
14. "p001");
15. 4.0);
16. 5);
17. items.add(item1);
18. new Item();
19. "p002");
20. 8.0);
21. 6);
22. items.add(item2);
23. order.setItems(items);
24. ordersDao.insert(order,collectionName);
25. }
我们到MongoDB查询时,订单内嵌订单详情的文档,说明我们成功新增文档。
测试Insert方法添加,这边就不在详情的介绍,跟Save方法一样。
2)测试InsertALL方法添加
[java] view plain copy
1. //测试InsertAll方法添加
2. @Test
3. public void testInsertAll() throws ParseException
4. {
5. new ArrayList<Orders>();
6. for(int i=1;i<=10;i++){
7. new SimpleDateFormat("yyyy-mm-dd");
8. //订单
9. new Orders();
10. "00"+i);
11. "2015-07-25"));
12. "zcy"+i);
13. //订单详情
14. new ArrayList<Item>();
15. new Item();
16. "p00"+i);
17. 4.0+i);
18. 5+i);
19. items.add(item1);
20. new Item();
21. "p00"+(i+1));
22. 8.0+i);
23. 6+i);
24. items.add(item2);
25. order.setItems(items);
26. orders.add(order);
27. }
28. ordersDao.insertAll(orders);
29. }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
我们批量添加10条订单内嵌订单详情的文档,我们在MongoDB查询时,有查到数据,说明我们插入成功。
[sql] view plain copy
1. > db.orders.find()
2. "_id" : ObjectId("55b387ebee10f907f1c9d461"), "_class" : "com.mongo.model.Orders", "onumber" : "001", "date" : ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy1", "items" : [ { "quantity" : 6, "price" : 5, "pnumber" : "p001" }, { "quantity" : 7, "price" : 9, "pnumber" : "p002" } ] }
3. "_id" : ObjectId("55b387ebee10f907f1c9d462"), "_class" : "com.mongo.model.Orders", "onumber" : "002", "date" : ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy2", "items" : [ { "quantity" : 7, "price" : 6, "pnumber" : "p002" }, { "quantity" : 8, "price" : 10, "pnumber" : "p003" } ] }
4. "_id" : ObjectId("55b387ebee10f907f1c9d463"), "_class" : "com.mongo.model.Orders", "onumber" : "003", "date" : ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy3", "items" : [ { "quantity" : 8, "price" : 7, "pnumber" : "p003" }, { "quantity" : 9, "price" : 11, "pnumber" : "p004" } ] }
5. { "_id" : ObjectId("55b387ebee10f907f1c9d464"), "_class" : "com.mongo.model.Orders", "onumber" : "004", "date" : ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy4", "items" : [ { "quantity" : 9, "price" : 8, "pnumber" : "p004" }, { "quantity" : 10, "price" : 12, "pnumber" : "p005" } ] }
6. { "_id" : ObjectId("55b387ebee10f907f1c9d465"), "_class" : "com.mongo.model.Orders", "onumber" : "005", "date" : ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy5", "items" : [ { "quantity" : 10, "price" : 9, "pnumber" : "p005" }, { "quantity" : 11, "price" : 13, "pnumber" : "p006" } ] }
7. ...........
8. >
3)如果面对相同的_ID时,我们在使用Save和Insert时,会碰到我们前面介绍的那样?我们测试一下就知道了。
我们在新增文档时,如果不设置_ID属性值,文档添加到MongoDB时,对于objectID的ID属性/字段自动生成一个字符串,带有索引和唯一性。如果我们指定_ID属性值时,速度会很慢,因为_ID默认是有索引的。
[sql] view plain copy
1. > db.orders.find()
2. "_id" : "1", "_class" : "com.mongo.model.Orders", "onumber" : "001", "date" :ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy1", "items" : [ { "quantit y" : 5,"price" : 4, "pnumber" : "p001" }, { "quantity" : 6, "price" : 8, "pnumber" : "p002" } ] }
ObjectId值"_id": "1"已经存在,我们分别对Save和Insert方法新增文档时,指定已经存在"_id": "1"。
1.测试Insert方法添加
[java] view plain copy
1. //测试Insert方法添加
2. @Test
3. public void testInsert() throws ParseException
4. {
5. new SimpleDateFormat("yyyy-mm-dd");
6. //订单
7. new Orders();
8. "1");
9. "002");
10. "2015-07-25"));
11. "zcy2");
12. //订单详情
13. new ArrayList<Item>();
14. new Item();
15. "p003");
16. 4.0);
17. 5);
18. items.add(item1);
19. new Item();
20. "p003");
21. 8.0);
22. 6);
23. items.add(item2);
24. order.setItems(items);
25. ordersDao.insert(order,collectionName);
26. }
我们添加相同的ID时,执行添加文档时,添加出现错误
org.springframework.dao.DuplicateKeyException:insertDocument :: caused by :: 11000 E11000 duplicate key error index:test.orders.$_id_ dup key: { :"1" }; nested exception is com.mongodb.MongoException$DuplicateKey:insertDocument :: caused by :: 11000 E11000 duplicate key error index:test.orders.$_id_ dup key: { :"1" }
调用持久层类的进行保存域更新的时候,主键或唯一性约束冲突。
2.测试Save方法添加
[java] view plain copy
1. //测试Save方法添加
2. @Test
3. public void testSave() throws ParseException
4. {
5. new SimpleDateFormat("yyyy-mm-dd");
6. //订单
7. new Orders();
8. "1");
9. "002");
10. "2015-07-25"));
11. "zcy2");
12. //订单详情
13. new ArrayList<Item>();
14. new Item();
15. "p003");
16. 4.0);
17. 5);
18. items.add(item1);
19. new Item();
20. "p003");
21. 8.0);
22. 6);
23. items.add(item2);
24. order.setItems(items);
25. ordersDao.save(order,collectionName);
26. }
我们添加相同的ID时,如果已经存在,会对相对应的文档进行更新,调用update更新里面的文档。
[sql] view plain copy
1. > db.orders.find()
2. "_id" : "1", "_class" :"com.mongo.model.Orders", "onumber" : "002","date" :ISODate("2015-01-24T16:07:00Z"),"cname" : "zcy2", "items" : [ {"quantity" : 5,"price": 4, "pnumber" : "p003" }, { "quantity" : 6,"price" : 8, "pnumber" : "p003" } ] }
说明:
(1)save :我们在新增文档时,如果有一个相同_ID的文档时,会覆盖原来的。
(2)insert:我们在新增文档时,如果有一个相同的_ID时,就会新增失败。
(3)MongoDB提供了insertAll批量添加,可以一次性插入一个列表,效率比较高,save则需要一个一个的插入文档,效率比较低。
三、删除文档、删除集合
1. 删除文档
Spring Data MongoDB 的MongoTemplate提供删除文档如下几个方法:
1) 我们这边重点根据条件删除文档
第一步:我们在基础接口MongoBase.java类新增一个根据条件删除文档的接口 。
[java] view plain copy
1. //根据条件删除
2. public void remove(String field,String value,String collectionName);
第二步:我们在OrdersDaoImpl类添加一个具体根据条件删除文档的实现方法。
[java] view plain copy
1. @Override
2. ublic void remove(Map<String, Object> params,String collectionName) {
3. mongoTemplate.remove(new Query(Criteria.where("id").is(params.get("id"))),User.class,collectionName);
[sql] view plain copy
1. > db.orders.find()
2. { "_id" : "1", "_class" : "com.mongo.model.Orders", "onumber" : "001", "date" :ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy1", "items" : [ { "quantity" : 5,"price" : 4, "pnumber" : "p001" }, { "quantity" : 6, "price" : 8, "pnumber" : "p002" } ] }
3. { "_id" : "2", "_class" : "com.mongo.model.Orders", "onumber" : "002", "date" :ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy2", "items" : [ { "quantity" : 5,"price" : 4, "pnumber" : "p003" }, { "quantity" : 6, "price" : 8, "pnumber" : "p004" } ] }
4. >
现在查询MongoDB有两条文档
2)实现测试类
[java] view plain copy
1. @Test
2. public void testRemove() throws ParseException
3. {
4. "onumber","002", collectionName);
5. }
我们根据onumber=002条件删除文档
[sql] view plain copy
1. > db.orders.find()
2. "_id" : "1", "_class" : "com.mongo.model.Orders", "onumber" : "001", "date" :ISODate("2015-01-24T16:07:00Z"), "cname" : "zcy1", "items" : [ { "quantity" : 5,"price" : 4, "pnumber" : "p001" }, { "quantity" : 6, "price" : 8, "pnumber" : "p002" } ] }
只剩下onumber=001的文档。
删除orders的数据,集合还存在,索引都还存在,相当与SQ的truncate命令。
2. 删除集合
第一步:我们在基础接口MongoBase.java类新增一个根据条件删除集合的接口。
[java] view plain copy
1. //删除集合
2. public void dropCollection(String collectionName);
第二步:我们在OrdersDaoImpl类添加一个具体根据条件删除集合的实现方法。
[java] view plain copy
1. @Override
2. ublic void dropCollection(String collectionName) {
3. mongoTemplate.dropCollection(collectionName);
集合、索引都不存在了,类型SQL的drop。