Java使用MongoDB数据库

前言

不支持用JDBC操作

除了通过启动 MongoDB进程进如 Shell 环境访问数据库外,MongoDB 还提供了其他基于编程语言的访问数据库方法。

MongoDB 官方提供了 Java 语言的驱动包,利用这些驱动包可使用多种编程方法来连接并操作 MongoDB 数据库。

MongoDB安装

添加配置文件

1
vi /etc/yum.repos.d/mongodb-org-4.0.repo

内容如下

1
2
3
4
5
[mngodb-org]
name=MongoDB Repository
baseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodb-org/4.0/x86_64/
gpgcheck=0
enabled=1

安装

1
yum -y install mongodb-org

启动

1
service mongod restart

开机启动

1
2
3
chkconfig mongod on
// 或者
systemctl enable mongod.service

查看数据文件位置

1
vi /etc/mongod.conf

允许远程连接

1
2
3
net:
port: 27017
bindIp: 127.0.0.1

修改为

1
2
3
net:
port: 27017
bindIp: 0.0.0.0

重启

1
service mongod restart

Shell 下测试

当你进入mongoDB后台后,它默认会链接到 test 文档(数据库):

1
2
3
> mongo
MongoDB shell version: 3.0.6
connecting to: test

由于它是一个JavaScript shell,您可以运行一些简单的算术运算:

1
2
> 2 + 2
4

db 命令用于查看当前操作的文档(数据库):

1
2
> db
test

库操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看当前服务器上的数据库
show dbs;
show databases;

# 选择名为zdb的数据库(如果没有则创建)
use zdb;

# 查看当前使用的数据库
db;

# 查看当前数据库的统计信息
db.stats();

# 查看当前数据库的操作信息
db.currentOp();

# 删除当前数据库
db.dropDatabase();

创建数据库

1
2
3
4
5
6
7
8
# 创建数据库
# use 使用数据库,如果这个数据库不存在就创建
use zdb;

# 2. 查看数据库名
show databases;
# 缩写
show dbs;

集合/表操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看当前数据库中的集合
show collections;
show tables;

# 创建一个名为zdb_user的集合
db.createCollection("zdb_user");

# 重命名zdb_user集合,新集合名叫zdb_user_new
db.zdb_user.renameCollection("zdb_user_new")

# 清空一个zdb_user_new的集合
db.zdb_user_new.remove({});

# 删除一个zdb_user_new的集合
db.zdb_user_new.drop();

数据插入

insert() 方法

注意:db.collection中,collection为你要操作的集合的名称

1
2
3
4
db.collection.insert(
<document or array of documents>,
{multi: false}
)

insertOne() 方法

添加一条文档记录

1
2
3
db.collection.insertOne(
<document>{}
)

insertMany() 方法

添加多条文档记录 ([]方括号表示数组)

1
2
3
db.collection.insertMany(
[ <document 1> {} , <document 2> {}, ... ] --jsonArray
)

示例

1
2
db.zdb_user_new.insert({"name":"xiao ming", "age":12});
db.zdb_user_new.insertOne({"name":"xiao hong", "age":18});

数据查询

字符串查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
db.zdb_user_new.find();

// 将查询结果"漂亮化"
db.zdb_user_new.find().pretty();

// 查询集合mycollection中键为name, 值为xiao ming的文档记录
db.zdb_user_new.find( {"name" : "xiao ming"} );

// 将查询条件写入文档对象ceriteria查询
var criteria = { "name" : "xiao ming" };
db.zdb_user_new.find(criteria);

// 使用内嵌对象的字段值查询
db.zdb_user_new.find({"name":"xiao ming"})

数值查询

操作 操作符 范例 SQL的类似语句
等于 : db.zdb_user_new.find({"age":10}) where age = 10
小于 less than $lt: db.zdb_user_new.find({"age":{$lt:15}}) where age < 15
小于或等于less than / equal $lte: db.zdb_user_new.find({"age":{$lte:15}}) where age <= 15
大于greater than $gt: db.zdb_user_new.find({"age":{$gt:15}}) where age > 15
大于或等于greater than / equal $gte: db.zdb_user_new.find({"age":{$gte:15}}) where age >= 15
不等于 not equal $ne: db.zdb_user_new.find({"age":{$ne:15}}) where age != 15

逻辑操作符and、or/in、not、exists

exists

1
2
3
4
// 文档中包含name属性的结果
db.zdb_user_new.find( { "name": { $exists: true } } );
// 文档中不包含name属性的结果
db.zdb_user_new.find( { "name": { $exists: false } } );

or

1
db.zdb_user_new.find({$or:[{"age":18},{"name":"xiao ming"}]});

in

1
db.zdb_user_new.find({"age":{$in:[12,18]}});

count统计

1
2
db.zdb_user_new.count();
db.zdb_user_new.count({"age":{$in:[12,15]}});

distinct不重复的值

语法

1
db.zdb_user_new.distinct(取值字段,查询条件)

示例:

返回满足条件字段的结果数组

第一个参数必须是字符串

1
db.zdb_user_new.distinct("name",{"age":{$in:[12,18]}});

结果

1
[ "xiao hong", "xiao ming" ]

用户

如出现找不到MongoDB shell为可执行文件,位于MongoDB安装路径下的/bin文件夹中。

用户设置

1
2
3
4
5
6
7
8
9
use admin; 
db.createUser({
user: 'admin', // 用户名
pwd: '123456', // 密码
roles:[{
role: 'root', // 角色---超级管理员才可以使用该角色
db: 'admin' // 数据库
}]
})

2、设置完成,可以输入 show users 查看是否设置成功—超级管理员需要先登录才可以查看

1
show users

3、开启验证

找到 MongoDB 安装目录,打开 mongod.cfg文件,

1
vi /etc/mongod.conf

找到以下这句:

1
#security:

修改为:

1
2
security:
authorization: enabled

重启就可以了。

1
service mongod restart

4、当设置账号密码成功后,我们对mongodb的数据库操作都有了限制,这时需要我们输入账号密码登录。

1
2
3
4
5
6
// 方式一
mongo
use admin
db.auth('admin', '123456')
// 方式二
mongo admin -u admin -p 123456

添加其他数据库用户

我们除了可以设置数据库的超级管理员以外,还可以给每个数据库设置单独的管理员。其只有操作单独数据的一定权限。

1
2
3
4
5
6
7
8
9
use zdb;  // 跳转到需要添加用户的数据库
db.createUser({
user: 'psvmc', // 用户名
pwd: '123456', // 密码
roles:[{
role: 'readWrite', // 角色
db: 'zdb' // 数据库名
}]
});

查看用户

1
2
use zdb;
show users;

登录

方式1

1
2
3
mongo
use zdb;
db.auth('psvmc', '123456');

方式2

1
mongo zdb -u psvmc -p 123456

常用命令

1
2
3
4
5
use zdb;
show users; // 查看当前库下的用户
db.dropUser('psvmc'); // 删除用户
db.updateUser('psvmc', {pwd: '654321'}); // 修改用户密码
db.auth('psvmc', '654321'); // 密码认证

添加依赖

不支持用JDBC操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
<version>3.12.11</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.12.11</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>3.12.11</version>
</dependency>

Java操作

连接

注意这两种方式对应的MongoClient在不同的包下。

另外认证库和连接的数据库可以不一样。

方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.google.common.collect.Lists;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.*;
import org.bson.BsonDocument;
import org.bson.BsonInt64;
import org.bson.Document;
import org.bson.conversions.Bson;

public class Test {
public static void main(String[] args) {
ServerAddress serverAddress = new ServerAddress("192.168.7.101", 27017);
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
// 若有多个服务器,创建多个ServerAddress即可
.applyToClusterSettings(builder -> builder.hosts(Lists.newArrayList(serverAddress)))
// 若存在权限验证,加上以下内容
.credential(MongoCredential.createCredential("psvmc", "zdb", "123456".toCharArray()))
.build();
MongoClient mongoClient = MongoClients.create(mongoClientSettings);
MongoDatabase mongoDatabase = mongoClient.getDatabase("zdb");
Bson command = new BsonDocument("ping", new BsonInt64(1));
Document commandResult = mongoDatabase.runCommand(command);
System.out.println(commandResult);
mongoClient.close();
}
}

方式2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

public class Test {
public static void main(String[] args) {
String url = "mongodb://psvmc:123456@192.168.7.101:27017/zdb?authSource=zdb";
MongoClient mongoClient = new MongoClient(new MongoClientURI(url));
MongoDatabase mongoDatabase = mongoClient.getDatabase("zdb");
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("zdb_user_new");
mongoCollection.insertOne(new Document().append("name", "张剑").append("age", 28));
// 查询方法
FindIterable<Document> documents = mongoCollection.find();
for (Document document : documents) {
System.out.println(document);
}
mongoClient.close();
}
}

查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.google.common.collect.Lists;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.*;
import org.bson.Document;

public class Test {
public static void main(String[] args) {
ServerAddress serverAddress = new ServerAddress("192.168.7.101", 27017);
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
// 若有多个服务器,创建多个ServerAddress即可
.applyToClusterSettings(builder -> builder.hosts(Lists.newArrayList(serverAddress)))
// 若存在权限验证,加上以下内容
.credential(MongoCredential.createCredential("psvmc", "zdb", "123456".toCharArray()))
.build();
MongoClient mongoClient = MongoClients.create(mongoClientSettings);
MongoDatabase mongoDatabase = mongoClient.getDatabase("zdb");
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("zdb_user_new");
// 查询方法
FindIterable<Document> documents = mongoCollection.find();
for (Document document : documents) {
System.out.println(document);
}
mongoClient.close();
}
}

设置每批数量

设置每批数量并不会影响查询的结果。

假如数据是100条,我们如果设置每批是10条,依旧在for循环中能查询到100条记录。

batchSize() 方法可用于限制每次查询返回的文档数量,从而提高查询性能和减少内存使用。

然而,需要注意的是,在某些情况下,使用 batchSize() 方法可能会导致查询性能下降,因此需要根据具体情况进行选择。

1
2
3
4
FindIterable<Document> documents = mongoCollection.find().batchSize(1000);
for (Document document : documents) {
System.out.println(document);
}

插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import com.google.common.collect.Lists;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.*;
import org.bson.Document;


public class Test {

public static void main(String[] args) {
ServerAddress serverAddress = new ServerAddress("192.168.7.101", 27017);
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
// 若有多个服务器,创建多个ServerAddress即可
.applyToClusterSettings(builder -> builder.hosts(Lists.newArrayList(serverAddress)))
// 若存在权限验证,加上以下内容
.credential(MongoCredential.createCredential("psvmc", "zdb", "123456".toCharArray()))
.build();
MongoClient mongoClient = MongoClients.create(mongoClientSettings);
MongoDatabase mongoDatabase = mongoClient.getDatabase("zdb");
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("zdb_user_new");
mongoCollection.insertOne(new Document().append("name", "张剑").append("age", 28));
// 查询方法
FindIterable<Document> documents = mongoCollection.find();
for (Document document : documents) {
System.out.println(document);
}
mongoClient.close();
}
}

其他

1
2
3
4
5
6
7
8
9
// 插入单条/多条方法
mongoCollection.insertOne()
mongoCollection.insertMany()
// 修改单条/多条方法
mongoCollection.updateOne();
mongoCollection.updateMany();
// 删除单条/多条方法
mongoCollection.deleteOne();
mongoCollection.deleteMany();

取值

默认方式

1
2
3
4
5
document.getString(name);
document.getLong(name);
document.getInteger(name);
document.getDate(name);
document.getDouble(name);

但是不推荐这样使用,原因是通过上面的方法获取的时候要求数据格式必须和获取的格式完全一样才行。

比如自动生成的主键_id,我们觉得它是字符串,使用getString获取,但是这样获取就报错了。

得使用下面的方式获取

1
document.getObjectId("_id").toString();

推荐方式

1
String strV = document.get(name).toString();

要取Long值的话,建议使用

1
(long) Double.parseDouble(document.get(name).toString());

原因是如果值是浮点的话使用Long.parseLong()也会报错

Double

1
Double.parseDouble(document.get(name).toString());