MongoDB学习笔记(十三):SpringData-Mongodb

最完整原版教程:http://docs.spring.io/spring-data/data-mongo/docs/1.4.0.RELEASE/reference/html/mongo.core.html 
范例中的MetaDBMongoFactory是我自己写的,你也可以通过Spring配置文件获得。如下 
http://www.blogjava.net/wangxinsh55/archive/2012/03/29/372987.html 

1.单表增删查改 
@Id - 文档的唯一标识,在mongodb中为ObjectId,它是唯一的,通过时间戳+机器标识+进程ID+自增计数器(确保同一秒内产生的Id不会冲突)构成。 
@Document - 把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。 
@DBRef - 声明类似于关系数据库的关联关系。ps:暂不支持级联的保存功能,当你在本实例中修改了DERef对象里面的值时,单独保存本实例并不能保存DERef引用的对象,它要另外保存,如下面例子的Person和Account。 
@Indexed - 声明该字段需要索引,建索引可以大大的提高查询效率。 
@CompoundIndex - 复合索引的声明,建复合索引可以有效地提高多字段的查询效率。 
@GeoSpatialIndexed - 声明该字段为地理信息的索引。 
@Transient - 映射忽略的字段,该字段不会保存到mongodb。 
@PersistenceConstructor - 声明构造函数,作用是把从数据库取出的数据实例化为对象。该构造函数传入的值为从DBObject中取出的数据。 
文档版本: @Version (建议用Long) 

范例: 
新建实体:

01. public class User
02. {
03. @Id  
04. private ObjectId id;  
05. @Indexed(unique = true)  
06. private String ssn;
07. @Indexed  
08. private String userName;  
09. private String password;
10. private Integer age;  
11. @Transient  
12. private Integer accountTotal;  
13. //其它set,get略......
14. }

增删查改

01. public void testCurd()
02. {
03. MongoTemplate template = MetaDBMongoFactory.getInstance().getMongoTemplate();
04. User user = new User();        
05. user.setSsn(...);//唯一性内容
06. user.setPassword("123456");
07. user.setUsername("张三");
08.  
09. //增加
10. template.save(user);
11. System.out.println("1. user : " + user);
12.  
13. //查询
14. Query searchUserQuery = new Query(Criteria.where("username").is("张三"));
15. User savedUser = template.findOne(searchUserQuery, User.class);
16. System.out.println("2. find - savedUser : " + savedUser);
17.  
18. //修改
19. template.updateFirst(searchUserQuery, Update.update("password", "45678"), User.class);
20. User updatedUser = template.findOne(searchUserQuery, User.class);
21. System.out.println("3. updatedUser : " + updatedUser);
22.  
23. //删除
24. template.remove(searchUserQuery, User.class);
25. List<User> listUser = template.findAll(User.class);
26. System.out.println("4. Number of user = " + listUser.size());
27. }

在看个更多功能的实体类

01. @Document(collection="person")  
02. @CompoundIndexes({  //组合索引
03. @CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")  
04. })  
05. public class sample {  
06.  
07. @Id  
08. private String id;  
09. @Indexed(unique = true)  
10. private Integer ssn;  
11. private String firstName;  
12. @Indexed  
13. private String lastName;  
14. private Integer age;  
15. @Transient  
16. private Integer accountTotal;  
17. @DBRef  
18. private List<Account> accounts;  
19.  
20. .....set and get
21. }

 

2.关联方式1:DBRef 一对一,一对多 
多对多就是对方表也放个list一起保存呗 

User.java

01. public class User
02. {
03. @Id
04. private ObjectId id;
05. @Indexed
06. private String name;
07. private Integer age;
08. @DBRef
09. private Weapon weapon;//一对一
10. @DBRef
11. private List<Item> items;//一对多
12. //set,get略......
13. }

Weapon.java

1. public class Weapon
2. {
3. @Id
4. private ObjectId id;
5. private String name;
6. private int power;
7. //set,get略......
8. }

Item.java

1. public class Item
2. {
3. @Id
4. private ObjectId id;
5. private String name;
6. private String desc;
7. //set,get略......
8. }

添加:

01. private voidsave()
02. {
03. MongoTemplate template = MetaDBMongoFactory.getInstance().getMongoTemplate();
04.  
05. User user = new User();
06. user.setName("张三");
07. user.setAge(30);
08.  
09. List<Item> items = new ArrayList<Item>();
10. for (int i = 0; i < 10; i++)
11. {
12. Item item = new Item();
13. item.setName("道具" + i);
14. item.setDesc("描述");
15. template.save(item);
16. items.add(item);
17. }
18.  
19. Weapon weapon = new Weapon();
20. weapon.setName("武器");
21. weapon.setPower(99);
22. template.save(weapon);
23.  
24. user.setWeapon(weapon);
25. user.setItems(items);
26. template.save(user);
27. }

查询 
一对多的对象会全部拿出来,所以如果关联的对象特别多超过几千,请用lazy=true的方式,懒惰加载

1. User user = template.findOne(new Query(Criteria.where("id").is(id)), User.class);

DBRef查询

1. ObjectId id = user.getId();Weapon myWeapon = template.findOne(new Query(Criteria.where("name").is("武器1")),Weapon.class);
2. Query query = new Query(Criteria.where("id").is(id).and("myWeapon").is(myWeapon));
3. User queryResult = template.findOne(query, User.class);

DBRef原生查询

1. Query query = new BasicQuery("{'id':'"+id.toString()+"', 'weapon' : {'$ref':'weapon','$id':{'$oid':'52e9affffad134ac3ee2e02a'}} }");
2. User queryResult = template.findOne(query, User.class);

排序

1. Query query = new Query(Criteria.where("id").is(id));
2. query.with(new Sort(Sort.Direction.DESC, "name"));
3. ......

分页,表示每页最多10条,从第3页开始

1. Query query = new Query(Criteria.where("id").is(id));
2. query.limit(10);
3. query.skip(20);

懒惰加载(1.4.0新功能,棒极了,大大提高效率)

1. @DBRef(lazy = true)
2. private List<Item> myItems;//一对多

 

3.关联方式2:集合属性 
比起DBRef模式的好处在于通过elemMatch能查询过滤。但缺点就是数据冗余。 
表字段性除了基本属性,还可以是任何对象,Map,List,这点是关系数据库做不到的。 

范例是获取用户信息,并且只取出名字是道具1的道具,如果道具特别多,这种写法可以有效加强性能

01. public class User
02. {
03. @Id
04. private ObjectId id;
05. @Indexed
06. private String name;
07. private Integer age;
08. private List<Item> items;
09. }

查询:

1. Query query = new Query(Criteria.where("id").is(id));
2. query.fields().include("items").include("name").elemMatch("items",Criteria.where("name").is("道具1"));
3. User user = template.findOne(query, User.class);

.include("items").include("name")表示查询结果集只需要这2列数据,这种做法可以减少读取的io字节大小 
elemMatch是过滤返回的items是一部分而不需要全部

 

4.聚合查询 

1).分组Group

1. GroupByResults<XObject> results =  template.group("user", GroupBy.key("age").initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class);

最后结果集里,比如看到,但最多只能处理2万条数据 
"retval":[{"age":13.0,"count":2.0},{"age":14.0,"count":1.0},{"age":30.0,"count":33.0}],"count":36.0 


2).MapReduce统计

1. MapReduceResults<User> asd = template.mapReduce("user", "function(){emit( this.id , { count : 1 } )}",
2. "function(key, values){var total=0;values.forEach(function(val){total += val.count;});return {count : total};}", User.class);

3).Aggregation 
范例是统计User每个用户多少条记录,类似于oracle的group

1. class UserStats {
2. String id;
3. Integer totalCount;
4. //其它set get
5. }
1. import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
2. Aggregation agg = newAggregation(
3. User.class,
4. group("name").count().as("totalCount"),
5. sort(Sort.Direction.ASC, previousOperation(), "totalCount"),
6. match(new Criteria(.....))//过滤条件
7. );
8. AggregationResults<UserStats> aggregateResult = template.aggregate(agg, "user", UserStats.class);

结果集: 
"mappedResults":[{"id":"方佳玮","totalCount":12}]

 

5.副本集群模式下,读写分离 

统一配置:

1. template.setReadPreference(ReadPreference.nearest());
2. Weapon myWeapon = template.findOne(new Query(Criteria.where("name").is("武器1"))

原生Api

1. DBObject dbObject = coll.findOne(object, null , preference);

说明: 
primary:默认参数,只从主节点上进行读取操作; 
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。 
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。 
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据; 
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。

 

 

 

6.文件读写(Gridfs)

 

01. public void save(File file, String fileName) throws FileNotFoundException
02. {
03. GridFsTemplate gridFsTemplate = MetaDBMongoFactory.getInstance().getGridFsTemplate();
04. MongoTemplate template = MetaDBMongoFactory.getInstance().getMongoTemplate();
05. SinitekFiles sinitekFiles = new SinitekFiles();
06. sinitekFiles.setDesc("描述");
07. gridFsTemplate.store(new FileInputStream(file), fileName,sinitekFiles);
08. }
09.  
10. public GridFSDBFile query(String fileName) throws FileNotFoundException
11. {
12. GridFsTemplate gridFsTemplate = MetaDBMongoFactory.getInstance().getGridFsTemplate();
13. return gridFsTemplate.findOne(Query.query(Criteria.where("filename").is(fileName)));
14. }
下面是原生api方式
1. DB db = mongoDbFactory.getDb();  
保存文件(其中FS_NAME相当于gridfs文件系统的表名,可以有多个)
01. public boolean saveFile(File file, String fileName, String contentType,
02. DBObject metaData) {
03.  
04. GridFSInputFile gfsInput;
05. try {   
06. gfsInput = new GridFS(db, FS_NAME).createFile(file);
07. gfsInput.setFilename(fileName);
08. gfsInput.setContentType(contentType);
09. gfsInput.setMetaData(metaData);
10. gfsInput.save();
11. } catch (IOException e) {
12. log.error(e, e);
13. return false;
14. }
15. return true;
16. }
通过文件名读取文件
01. public GridFSDBFile findFileByName(String fileName){
02. GridFSDBFile gfsFile ;
03. try {      
04. gfsFile = new GridFS(db, FS_NAME).findOne(fileName);
05. } catch (Exception e) {
06. log.error(e, e);
07. return null;
08. }
09. return gfsFile;
10. }
通过id读取文件
01. public GridFSDBFile findFileById(String id){
02. GridFSDBFile gfsFile ;
03. try {      
04. gfsFile = new GridFS(db, FS_NAME).find(new ObjectId(id));
05. } catch (Exception e) {
06. log.error(e, e);
07. return null;
08. }
09. return gfsFile;
10. }
输出文件到OutputStream
01. private boolean writeToOutputStream(OutputStream out, GridFSDBFile gfsFile) {
02. try {     
03. gfsFile.writeTo(out);
04. } catch (IOException e) {
05. log.error(e, e);
06. return false;
07. }
08. return true;
09. }

 

 

 

 

 

7.文件读写(Document)

 

我偷懒范例选自网络,用的原生api,估计spring momgodb也差不多  

保存:
01. public static void main(String[] args) {
02. try {
03. Mongo mongo = new Mongo();
04. DB db = mongo.getDB("company");
05. DBCollection collection = db.getCollection("userinfo");
06. BasicDBObject employees = new BasicDBObject();
07. File file = new File("d://shuimohua01.jpg");
08. FileInputStream input = new FileInputStream(file);
09. byte[] files = new byte[input.available()];
10. while (input.read(files)>0) {
11. input.read(files);
12. }
13. input.close();
14. employees.put("no", "1015");
15. collection.remove(employees);
16. employees.put("member", files);
17. employees.put("filename", file.getName());
18. System.out.println(files.length);
19. collection.insert(employees);
20. } catch (UnknownHostException e) {
21. // TODO Auto-generated catch block
22. e.printStackTrace();
23. } catch (MongoException e) {
24. // TODO Auto-generated catch block
25. e.printStackTrace();
26. } catch (FileNotFoundException e) {
27. // TODO Auto-generated catch block
28. e.printStackTrace();
29. } catch (IOException e) {
30. // TODO Auto-generated catch block
31. e.printStackTrace();
32. }
33. }
34. }
读取:
01. public static void main(String[] args) {
02. try {
03. Mongo mongo = new Mongo();
04. DB db = mongo.getDB("company");
05. DBCollection collection = db.getCollection("userinfo");
06. DBObject employees = new BasicDBObject();
07. employees.put("no", "1015");
08. employees = collection.findOne(employees);
09. byte[] files = (byte[]) employees.get("member");
10. ByteArrayInputStream input = new ByteArrayInputStream(files);
11. File f = new File("e://" + employees.get("filename"));
12. FileOutputStream output = new FileOutputStream(f);
13. byte[] b=new byte[input.available()];
14. while (input.read(b)>0) {
15. input.read(b);
16. output.write(files);
17. }
18. input.close();
19. output.close();
20. } catch (UnknownHostException e) {
21. // TODO Auto-generated catch block
22. e.printStackTrace();
23. } catch (MongoException e) {
24. // TODO Auto-generated catch block
25. e.printStackTrace();
26. } catch (IOException e) {
27. // TODO Auto-generated catch block
28. e.printStackTrace();
29. }
30. }
31. }

 

1.了解Spring 2.了解NoSQL和文档数据库 3.要求 4.其他帮助资源 4.1。支持 4.1.1。社区论坛 4.1.2。专业支持 4.2。发展之后 5.新&值得注意的 5.1。Spring Data MongoDB 2.1中的新特性 5.2。Spring Data MongoDB 2.0中的新特性 5.3。Spring Data MongoDB 1.10中的新特性 5.4。Spring Data MongoDB 1.9中的新特性 5.5。Spring Data MongoDB 1.8中的新特性 5.6。Spring Data MongoDB 1.7中有什么新功能 6.依赖 6.1。Spring Boot的依赖管理 6.2。Spring框架 7.使用Spring Data Repositories 7.1。核心概念 7.2。查询方法 7.3。定义存储库接口 7.3.1。微调储存库定义 7.3.2。空处理存储库方法 7.3.3。将存储库与多个Spring Data模块一起使用 7.4。定义查询方法 7.4.1。查询查询策略 7.4.2。查询创建 7.4.3。属性表达式 7.4.4。特殊参数处理 7.4.5。限制查询结果 7.4.6。流式查询结果 7.4.7。异步查询结果 7.5。创建存储库实例 7.5.1。XML配置 7.5.2。JavaConfig 7.5.3。独立使用 7.6。Spring Data存储库的自定义实现 7.6.1。定制个人存储库 7.6.2。自定义基础存储库 7.7。从聚合根发布事件 7.8。Spring数据扩展 7.8.1。Querydsl扩展 7.8.2。Web支持 7.8.3。存储库填充程序 7.8.4。传统网络支持 参考文档 8.介绍 8.1。文档结构 9. MongoDB支持 9.1。入门 9.2。示例存储库 9.3。用Spring连接到MongoDB 9.3.1。使用基于Java的元数据注册Mongo实例 9.3.2。使用基于XML的元数据注册Mongo实例 9.3.3。MongoDbFactory接口 9.3.4。使用基于Java的元数据注册MongoDbFactory实例 9.3.5。使用基于XML的元数据注册MongoDbFactory实例 9.4。MongoTemplate简介 9.4.1。实例化MongoTemplate 9.4.2。WriteResultChecking策略 9.4.3。WriteConcern 9.4.4。WriteConcernResolver 9.5。保存,更新和删除文档 9.5.1。如何_id在映射图层中处理该字段 9.5.2。类型映射 9.5.3。保存和插入文件的方法 9.5.4。更新集合中的文档 9.5.5。在集合中插入文档 9.5.6。在集合中查找和插入文档 9.5.7。删除文件的方法 9.5.8。乐观锁定 9.6。查询文件 9.6.1。查询集合中的文档 9.6.2。查询文件的方法 9.6.3。查询不同的值 9.6.4。地理空间查询 9.6.5。GeoJSON支持 9.6.6。全文查询 9.6.7。排序规则 9.6.8。JSON模式 9.6.9。流利的模板API 9.7。按实例查询 9.7.1。介绍 9.7.2。用法 9.7.3。示例匹配器 9.7.4。执行一个例子 9.7.5。无类型示例 9.8。减少地图操作 9.8.1。使用示例 9.9。脚本操作 9.9.1。使用示例 9.10。集团运营 9.10.1。使用示例 9.11。聚合框架支持 9.11.1。基本概念 9.11.2。支持的聚合操作 9.11.3。投影表达式 9.11.4。分面分类 9.12。用自定义转换器覆盖默认映射 9.12.1。使用已注册的Spring Converter进行保存 9.12.2。使用Spring转换器读取 9.12.3。使用MongoConverter注册Spring转换器 9.12.4。转换器消除歧义 9.13。索引和集合管理 9.13.1。创建索引的方法 9.13.2。访问索引信息 9.13.3。使用集合的方法 9.14。执行命令 9.14.1。执行命令的方法 9.15。生命周期事件 9.16。例外翻译 9.17。执行回调 9.18。GridFS支持 9.19。更改流 9.19.1。使用MessageListener更改流 9.19.2。更改流 - 无效 10.反应性的MongoDB支持 10.1。入门 10.2。使用Spring和Reactive Streams Driver连接到MongoDB 10.2.1。使用基于Java的元数据注册MongoClient实例 10.2.2。ReactiveMongoDatabaseFactory接口 10.2.3。使用基于
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值