最完整原版教程: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 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 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- 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- items =
new
ArrayList- ();
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- 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- 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 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 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 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.
}
1.
DB db = mongoDbFactory.getDb();
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.
}
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.
}
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)
保存:
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.
}