1. 程式人生 > >Spring Data MongoDB 二:新增、刪除操作

Spring Data MongoDB 二:新增、刪除操作

一.簡介

   Spring  Data  MongoDB 專案提供與MongoDB文件資料庫的整合,Spring與Hibernate整合時,Spring提供了org.springframework.orm.hibernate3.HibernateTemplate實現了對資料的CRUD操作, Spring Data  MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate對MongoDB的CRUD的操作,包括對整合的物件對映檔案和POJO之間的CRUD的操作。

   今天我們要介紹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的新增操作

    (1)介紹介面以及實現方法

       第一步:實現一個基礎介面,是比較通用的 MongoBase.java類

      public interface MongoBase<T> {
	// insert新增
	public void insert(T object,String collectionName); 
	// save新增
	public void save(T object,String collectionName); 
	//批量新增
	public void insertAll(List<T> object); 
      }
        

     第二步:我們實現文件的結構,也是實體類。

      我們這邊有兩個實體類,訂單類(Orders.java)和對應訂單詳情類(Item.java),這裡我們實現內嵌文件。如果沒有內嵌文件的結構,只要對一個實體類的操作就OK。

         1)Orders.Java

/**
 * 訂單
 * @author zhengcy
 *
 */
public class Orders implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	//ID
	private String id;
	//訂單號
	private String onumber;
	//日期
	private Date date;
	//客戶名稱
	private String cname;
	//訂單
    private List<Item> items;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
	public String getOnumber() {
		return onumber;
	}
	public void setOnumber(String onumber) {
		this.onumber = onumber;
	}
	public List<Item> getItems() {
		return items;
	}
	public void setItems(List<Item> items) {
		this.items = items;
	}

}

        2) Item.java  
/**
 * 產品訂購表
 * @author zhengcy
 *
 */
public class Item {
	
	//數量
	private Integer quantity;
	//單價
	private Double price;
	//產品編碼
	private String pnumber;
	public Integer getQuantity() {
		return quantity;
	}
	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}
	public Double getPrice() {
		return price;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	public String getPnumber() {
		return pnumber;
	}
	public void setPnumber(String pnumber) {
		this.pnumber = pnumber;
	}
}

       第三步:實現OrdersDao類,就是實現Orders自己操作資料庫的介面,這個OrdersDao也繼承了MongoBase介面,我們這邊OrdersDao沒實現其他額外的介面。

         
/**
 * 訂單Dao
 * @author zhengcy
 *
 */
public interface OrdersDao extends MongoBase<Orders> {


}

  第四步:實現OrdersDaoImpl具體類,這邊是實際操作資料庫。

 /**
 * 訂單實現
 * @author zhengcy
 *
 */
@Repository("ordersDao")
public class OrdersDaoImpl implements OrdersDao {
	@Resource
	private MongoTemplate mongoTemplate;

	@Override
	public void insert(Orders object, String collectionName) {
		mongoTemplate.insert(object, collectionName);
		
	}
	
	
	@Override
	public void save(Orders object, String collectionName) {
		mongoTemplate.save(object, collectionName);
		
	}
	
	@Override
	public void insertAll(List<Orders> objects) {
		mongoTemplate.insertAll(objects);
		
	}
}
    

(2)實現測試類,我們進行測試

      我們這邊為了節省時間,就沒寫服務類,我們直接呼叫dao就可以了,實現了TestOrders.java類

/**
 * 測試訂單
 * @author zhengcy
 *
 */
public class TestOrders {
	private static OrdersDao ordersDao;
	private static  ClassPathXmlApplicationContext  app;
	private static String collectionName;
	@BeforeClass  
        public static void initSpring() { 
		try {
	     app = new ClassPathXmlApplicationContext(new String[] { "classpath:applicationContext-mongo.xml",  
                "classpath:spring-dispatcher.xml" });  
	     ordersDao = (OrdersDao) app.getBean("ordersDao"); 
        collectionName ="orders";
		} catch (Exception e) {
			e.printStackTrace();
		}
         } 
	
	//測試Save方法新增
	@Test 
	public void testSave() throws ParseException
	{
		
	}
	//測試Insert方法新增
	@Test 
	public void testInsert() throws ParseException
	{
		
	}
	//測試InsertAll方法新增
	@Test 
	public void testInsertAll() throws ParseException
	{
		
	}
}
   

      1)測試Save方法新增

            
        //測試Save方法新增
	@Test 
	public void testSave() throws ParseException
	{
		 SimpleDateFormat form=new SimpleDateFormat("yyyy-mm-dd");
			//訂單
		    Orders order =new Orders();
			order.setOnumber("001");
			order.setDate(form.parse("2015-07-25"));
			order.setCname("zcy");
			//訂單詳情
			List<Item> items=new ArrayList<Item>();
			Item item1=new Item();
			item1.setPnumber("p001");
			item1.setPrice(4.0);
			item1.setQuantity(5);
			items.add(item1);
			Item item2=new Item();
			item2.setPnumber("p002");
			item2.setPrice(8.0);
			item2.setQuantity(6);
			items.add(item2);
			order.setItems(items);
			ordersDao.insert(order,collectionName);
	}
          

        我們到MongoDB查詢時,訂單內嵌訂單詳情的文件,說明我們成功新增文件。

         測試Insert方法新增,這邊就不在詳情的介紹,跟Save方法一樣。

        2)測試InsertALL方法新增

       //測試InsertAll方法新增
	@Test 
	public void testInsertAll() throws ParseException
	{
		List<Orders> orders=new ArrayList<Orders>();
		for(int i=1;i<=10;i++){
			SimpleDateFormat form=new SimpleDateFormat("yyyy-mm-dd");
			//訂單
		    Orders order =new Orders();
			order.setOnumber("00"+i);
			order.setDate(form.parse("2015-07-25"));
			order.setCname("zcy"+i);
			//訂單詳情
			List<Item> items=new ArrayList<Item>();
			Item item1=new Item();
			item1.setPnumber("p00"+i);
			item1.setPrice(4.0+i);
			item1.setQuantity(5+i);
			items.add(item1);
			Item item2=new Item();
			item2.setPnumber("p00"+(i+1));
			item2.setPrice(8.0+i);
			item2.setQuantity(6+i);
			items.add(item2);
			order.setItems(items);
			orders.add(order);
		}
		ordersDao.insertAll(orders);
	}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

        我們批量新增10條訂單內嵌訂單詳情的文件,我們在MongoDB查詢時,有查到資料,說明我們插入成功。


      
> db.orders.find()
  { "_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" } ] }
  { "_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" } ] }
 { "_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" } ] }
{ "_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" } ] }
{ "_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" } ] }
...........
>

    

    3)如果面對相同的_ID時,我們在使用Save和Insert時,會碰到我們前面介紹的那樣?我們測試一下就知道了。

          我們在新增文件時,如果不設定_ID屬性值,文件新增到MongoDB時,對於objectID的ID屬性/欄位自動生成一個字串,帶有索引和唯一性。如果我們指定_ID屬性值時,速度會很慢,因為_ID預設是有索引的。

           
   > db.orders.find()
    { "_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方法新增

       //測試Insert方法新增
	@Test 
	public void testInsert() throws ParseException
	{
		 SimpleDateFormat form=new SimpleDateFormat("yyyy-mm-dd");
		    //訂單
		    Orders order =new Orders();
		    order.setId("1");
			order.setOnumber("002");
			order.setDate(form.parse("2015-07-25"));
			order.setCname("zcy2");
			//訂單詳情
			List<Item> items=new ArrayList<Item>();
			Item item1=new Item();
			item1.setPnumber("p003");
			item1.setPrice(4.0);
			item1.setQuantity(5);
			items.add(item1);
			Item item2=new Item();
			item2.setPnumber("p003");
			item2.setPrice(8.0);
			item2.setQuantity(6);
			items.add(item2);
			order.setItems(items);
			ordersDao.insert(order,collectionName);
	}
   

        我們新增相同的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方法新增

       //測試Save方法新增	
	@Test 
	public void testSave() throws ParseException
	{
		 SimpleDateFormat form=new SimpleDateFormat("yyyy-mm-dd");
			//訂單
		    Orders order =new Orders();
		    order.setId("1");
			order.setOnumber("002");
			order.setDate(form.parse("2015-07-25"));
			order.setCname("zcy2");
			//訂單詳情
			List<Item> items=new ArrayList<Item>();
			Item item1=new Item();
			item1.setPnumber("p003");
			item1.setPrice(4.0);
			item1.setQuantity(5);
			items.add(item1);
			Item item2=new Item();
			item2.setPnumber("p003");
			item2.setPrice(8.0);
			item2.setQuantity(6);
			items.add(item2);
			order.setItems(items);
			ordersDao.save(order,collectionName);
	}
              

     我們新增相同的ID時,如果已經存在,會對相對應的文件進行更新,呼叫update更新裡面的文件。

  > db.orders.find()
     { "_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類新增一個根據條件刪除文件的介面  。    

             //根據條件刪除
             public void remove(String field,String value,String collectionName);
               

              第二步:我們在OrdersDaoImpl類新增一個具體根據條件刪除文件的實現方法。

                      
         @Override
	public void remove(Map<String, Object> params,String collectionName) {
		mongoTemplate.remove(new Query(Criteria.where("id").is(params.get("id"))),User.class,collectionName);
	}

               
> db.orders.find()
{ "_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" } ] }
{ "_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" } ] }
>

   現在查詢MongoDB有兩條文件

       2)實現測試類

                    
        @Test 
	public void testRemove() throws ParseException
	{
		ordersDao.remove("onumber","002", collectionName);
	}
     

        我們根據onumber=002條件刪除文件

    > db.orders.find()
      { "_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類新增一個根據條件刪除集合的介面。       

           //刪除集合
            public void dropCollection(String collectionName);
                   

               第二步:我們在OrdersDaoImpl類新增一個具體根據條件刪除集合的實現方法。

         @Override
	public void dropCollection(String collectionName) {
		mongoTemplate.dropCollection(collectionName);
	}
             

                 集合、索引都不存在了,型別SQL的drop。