mongodb是一種基於文件類型的高效能nosql資料庫,在高並發下具有優秀的表現,因此,在互連網行業中,mongodb的使用情境將非常廣泛。
當然,mongodb主要對效能關注很多,因而沒有提供類似於關聯式資料庫的事務的功能,對於複雜的業務及嚴格資料一致性要求很高有企業級應用,不建議使用mongodb(網上也有自己去實現事務提交的方案,但實現起來比較繁瑣,類似於我們早期dbase,access檔案型資料庫的事務解決方案)。
其實,也不排除在企業級應用上把某些訪問壓力大的,對事務要求不嚴格的資料儲存到nosql資料庫中。
spring data架構,提供了對mongodb的支援,大家可以到http://mongojack.org/,及http://www.springsource.org/spring-data/mongodb
上瞭解更多資訊mongodb及sprig data for mongodb相關資訊。
下面,我用一個簡單的執行個體,給大家講解mongodb的使用,在這之前,你需要下載mongodb java驅動包,spring data commons, spring data for mongodb這些組件包。
共兩個對象,客戶,客戶訂單,一對多關聯性,單向關聯。
客戶:
@Document
public class Customer {
@Id
private int id;
private String loginCode;
private String name;
private String pwd;
@Version
private long varsion;
private Date birthday = new Date();
private Set<Order> orders = new HashSet<Order>();
訂單:
@Document
public class Order {
@Id
private int id;
private String code;
private String orderName;
spring data的配置:
@Configuration
public class MongoConfiguration {
public @Bean MongoDbFactory mongoDbFactory() throws Exception {
//需要使用者名稱、密碼驗證
UserCredentials userCredentials = new UserCredentials("yq", "123");
return new SimpleMongoDbFactory(new Mongo(), "exam", userCredentials);
//return new SimpleMongoDbFactory(new Mongo(), "exam");
}
public @Bean MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
}
當然,上面這段資訊可以配置在xml中,也可以像我上面一樣用寫在java代碼中。
這裡要建立exam庫,可以在mongodb命令列下,使用 use 命令建立,比如:use exam,然後隨便添點東西在裡面,庫就建好了。另外,如果要啟用認證功能,需要大家通過命令向某個庫中添加使用者(具體如db.addUser(“使用者名稱”,”密碼”)),啟動mongodb時使用-auth參數。
在整合過程中,如果報:
tried to access methodorg.springframework.core.GenericTypeResolver.getTypeVariableMap錯誤,是由於包版本衝突所至,請下載新的spring核心包。
下面給大家舉例說明api的使用:
我們的所有操作只需要一個MongoTemplate
@Resource
private MongoTemplate mt;
(1)檢測一個空間是否存在
mt.collectionExists(Customer.class);
(2)建立新空間
mt.createCollection("myCollection");
(3)統計總記錄條數,其中query可以為null,或一個建好的帶條件查資料的query,如需分頁,請先count,再查分頁資料
mt.count(new Query(), Customer.class);
(4)刪除空間,其中的資料會一併清除
mt.dropCollection("myCollection");
(5)按id號查詢
Customer c = mt.findById(1, Customer.class);
(6)刪除id號為1的客戶
mt.remove(mt.findById(1, Customer.class));
(7)刪除id號小於5的客戶
mt.remove(new Query(Criteria.where("id").lt(5)), Customer.class);
(8)查詢姓名是:張三5,並且密碼是:111的使用者
List<Customer> cc = mt.find(new Query(Criteria.where("name").is("張三5").and("pwd").is("111")), Customer.class);
或List<Customer> cs = mt.find(new Query(Criteria.where("name").is("張三5").andOperator(Criteria.where("pwd").is("111"))), Customer.class);
要注意,一個criteria中只能有一個andOperator,如果要寫並列條件,直接用and就可以了。
(9)查詢姓名是:張三5,或者 密碼是:111的使用者
List<Customer> cs = mt.find(new Query(new Criteria().orOperator(Criteria.where("name").is("張三5"),Criteria.where("pwd").is("111"))), Customer.class);
(10)查詢出生日期小於2013年6月6日的客戶
List<Customer> cs = mt.find(new Query(Criteria.where("birthday").lt(new Date())), Customer.class);
(11)查詢出生日期等於2013年6月6日的客戶
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd-hh:mm:ss");
List<Customer> cs = mt.find(new Query(
Criteria.where("birthday").gte(sf.parse("2013-06-06-00:00:00"))
.andOperator(Criteria.where("birthday").lte(sf.parse("2013-06-09-23:59:59")))
), Customer.class);
(12)查詢定單編號是0015或者0018的客戶
List<Customer> cs = mt.find(new Query(new Criteria()
.where("orders.code").in("0015","0018")
), Customer.class);
請注意,mongodb可以直接針對集合查詢,比如,上面的orders就是一個set集合。
(13)查詢包含四的,並以0結尾的客戶
//(正則表 達式,以XX開頭,請用^,以XX結束,請用$,不寫這兩個,表示任意)
List<Customer> cs = mt.find(new Query(new Criteria()
.where("name").regex("四.*0$")
), Customer.class);
請注意,mongodb不支援在id上的正則查詢。
(14)修改對象屬性名稱,修改後,要同步修改對象中的屬性名稱,否則,此屬性值為null
mt.updateMulti(new Query(), new Update().rename("password", "pwd"), "customer");
(15)批量修改,把id為100的客戶姓名改為tomcat999,密碼改為222
mt.findAndModify(new Query(Criteria.where("id").is(100)),
new Update().set("name", "tomcat999").set("pwd", "222"),
Customer.class);
(16)修改單個對象
Customer cc = mt.findById(100, Customer.class);
cc.setPwd("333");
mt.save(cc);
(17)排序及分頁實現
public Page<Customer> getCustomerByPage(int pageNo, int pageSize, Map params) {
Page<Customer> page = new Page<Customer>(pageNo, pageSize);
//查詢資料
List<Customer>data = mt
.find(
new Query().skip(page.getRowStartIndex())
.limit(pageSize)
.with(new Sort(Sort.Direction.DESC, "_id"))
, Customer.class);
page.setData(data);
//統計總記錄數
long count = mt.count(null, Customer.class);
page.setRowcounts(count);
return page;
}
最後,給出幾個使用mongodb,在對象設計實踐:
對象id最好設計成String類型,在新增時,如果使用者沒有賦值,mongodb會自動產生的,當然你也可以使用UUID自己賦值。
Spring對mongodb的封裝在對象間存在迴圈關聯的情況,在新增及查詢時都會出現堆疊溢位情況,目前的解決辦法是:
A、切斷雙向關聯。比如:一對多雙向關聯,你可以刪除一方的集合屬性,多方對一方的引用採用dbref註解標註。一對多、多對多也如此,儘可能地簡化對象間的關係。
B、對象間關係,最好直接建立成關聯式資料庫中的外鍵形式欄位,即:以非物件導向的方式去建立,這就是“魚和熊掌,不可兼得”,在追求效能效率的同時,放棄更好理解的物件模型。
有嚴格事務要求的業務系統,不要用mongodb。
如有極端的高並發大資料量查詢,請用mongodb,也可以把項目中的部分資料儲存在mongodb中。
一般的並發修改,可以使用樂觀鎖解決,spring mongodb支援@Version登出。
還有,開發中最好準備一個圖型化的mongodb管理工具,比如:MongoCola,隨時查看儲存的資料實況,方便調試。