MongoDB是目前热门的非关系数据库,广泛的应用于国内外的互联网公司。
MongoDB(来自于英文单词Humongous,含义为「庞大」),可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库,基于分布式文件存储的数据库。C++语言编写,旨在为web应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似Json的bjson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是支持的查询语言非常强大,语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
传统的关系数据库一般由数据库(DataBase)、表(Table)、记录(Record)三个层次概念组成;MongoDB是由数据库(DataBase)、集合(Collection)、文档对象(Document)三个层次组成。MongoDB对应关系型数据库里的表,但是集合中没有列、行和关系概念。
MongoDB中的一条记录就是一个文档,是一个数据结构,由字段和值对组成。MongoDB文档与Json对象类似。字段的值有可能包括其他文档、数组及文档数组。MongoDB支持几乎所有主流操作系统,并提供了Java、Python、PHP及C++等编程语言的驱动程序。
MongoDB适合对大量或者无固定格式的数据进行存储,如日志、缓存等。对事物支持较弱,不适用复杂的多文档(多表)的级联查询。
订单系统使用了MongoDB,刚好可以通过Spring Boot进行学习,确认了订单系统使用的版本是3.4.2,官网已经是4.x版本,这里还是跟公司环境保持一致。
Download:https://www.mongodb.org/dl/linux/x86_64-rhel62
# 下载解压二进制文件
wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.2.tgz
tar -vxzf mongodb-linux-x86_64-rhel62-3.4.2.tgz
mv mongodb-linux-x86_64-rhel62-3.4.2 /usr/local/mongodb-3.4.2
# 创建data和log目录
mkdir -p /data01/mongodata /data01/mongolog
# 增加环境变量
vim /etc/profile
export PATH=/usr/local/mongodb-3.4.2/bin:$PATH
source /etc/profile
# 增加conf配置
vim mongo.conf
bind_ip = 10.255.242.129
port = 27017
#fork = true
## MongoDB Data path
dbpath=/data01/mongodata
## Log path
logpath=/data01/mongolog/mongodb.log
## is log Rotate mongoDB 3.0
logappend = true
#logRotate = true
## is Open journal log
journal = true
## use small files for develop
smallfiles = true
# 设置启动脚本
vim mongo.sh
#!/bin/bash
mongod -fork -config /usr/local/mongodb-3.4.2/mongo.conf
chmod 755 mongo.sh
# 启动MongoDB
sh mongo.sh通过进程、telnet、以及日志,都能确认MongoDB已经成功启动。

关于MongoDB集群、配置、运维等总结,以后有机会再进行。这里还是安装后,使用Spring Boot进行操作。
Spring Data是Spring为了简化数据库操作而封装的一个组件包,提供了操作多种数据库的支持,API简洁、调用方便。
spring-boot-starter-data-mongodb是Spring Data的一个子模块。目标是为MongoDB提供一个相近的、一致的、基于Spring的编程模型。spring-boot-starter-data-mongodb核心功能是映射POJO到MongoDB的DBCollection中的文档,并且提供Repository风格数据访问层。除继承Spring Data的通用功能外,针对MongoDB的特性开发了很多定制的功能,使得Spring Boot操作MongoDB更加简便。
MongoDB有两种比较流行的使用方法,一种是直接将MongoTemplate直接注入到Dao中使用;另一种是继承MongoRepository,MongoRepository内置了很多方法可直接使用(类似JPA的Repository)。
A、MongoTemplate使用
1、相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>2、application.properties
# spring.data.mongodb.uri=mongodb://name:pass@localhost:27017/test
spring.data.mongodb.uri=mongodb://10.255.242.129:27017/test多IP集群配置:
spring.data.mongodb.uri=mongodb://user:pwd@ip1:port1,ip2:port2/databasePS:MongoDB 3.0,Java驱动不支持spring.data.mongodb.host和spring.data.mongodb.port,需要在spring.data.mongodb.uri提供全部的配置信息。
3、创建数据实体
@Getter
@Setter
public class User
{
private Long id;
private String username;
private String password;
}4、Dao层增删改查
public interface UserDao
{
void save(User user);
User findUserByUsername(String username);
long update(User user);
void deleteById(Long id);
}
@Service
public class UserDaoImpl implements UserDao
{
@Autowired
private MongoTemplate mongoTemplate;
@Override
public void save(User user)
{
mongoTemplate.save(user);
}
@Override
public User findUserByUsername(String username)
{
Query query = new Query(Criteria.where("username").is(username));
User user = mongoTemplate.findOne(query, User.class);
return user;
}
@Override
public long update(User user)
{
Query query = new Query(Criteria.where("id").is(user.getId()));
Update update = new Update().set("username", user.getUsername()).set("password", user.getPassword());
// 更新查询返回结果集的第一条
UpdateResult result = mongoTemplate.updateFirst(query, update, User.class);
// 更新查询返回结果集的所有
// mongoTemplate.updateMulti(query,update,UserEntity.class);
if (result != null)
{
return result.getMatchedCount();
}
else
{
return ;
}
}
@Override
public void deleteById(Long id)
{
Query query = new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query, User.class);
}
}5、测试
@Slf4j
public class UserDaoTest extends MongodbTemplateApplicationTests
{
@Autowired
private UserDao userDao;
@Test
public void save()
{
User user = new User();
user.setId(1L);
user.setUsername("isisiwish");
user.setPassword("pass");
userDao.save(user);
}
@Test
public void findUserByUsername()
{
User user = userDao.findUserByUsername("isisiwish");
log.info("{}", JSON.toJSONString(user));
}
@Test
public void update()
{
User user = new User();
user.setId(1L);
user.setUsername("isisiwish");
user.setPassword("password");
userDao.update(user);
}
@Test
public void deleteById()
{
userDao.deleteById(1L);
}
}6、查看验证结果
使用工具Studio 3T来连接后直接图形化展示查看。

也可以登录服务器用命令来查看:

B、MongoRepository的使用
MongoRepository的使用方式和之前项目结构类似,只有Dao层的代码有所变化。
1、Repository
新建UserRepository需要继承MongoRepository,这样就可直接使用MongoRepository的内置方法。对于分页需要在UserRepository加入一个空方法,不需要自己实现。
public interface UserRepository extends MongoRepository<User, Long>
{
User findByUsername(String username);
@Override
Page<User> findAll(Pageable pageable);
}2、测试
UserRepository已经自动实现了常用的数据库操作,不用像使用MongoTemplate那样需要手动来实现。
@Slf4j
public class UserRepositoryTest extends MongodbRepositoryApplicationTests
{
@Autowired
private UserRepository userRepository;
@Test
public void save()
{
User user = new User();
user.setId(2L);
user.setUsername("isisiwish");
user.setPassword("pass");
userRepository.save(user);
}
@Test
public void findUserByUsername()
{
User user = userRepository.findByUsername("isisiwish");
log.info("{}", JSON.toJSONString(user));
}
@Test
public void update()
{
User user = new User();
user.setId(2L);
user.setUsername("isisiwish");
user.setPassword("password");
userRepository.save(user);
}
@Test
public void deleteById()
{
userRepository.deleteById(2L);
}
@Test
public void testPage()
{
for (long i = ; i < 100; i++)
{
User user = new User();
user.setId(i);
user.setUsername("isisiwish:" + i);
user.setPassword("pass");
userRepository.save(user);
}
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(, 5, sort);
Page<User> page = userRepository.findAll(pageable);
List<User> userList = page.getContent();
for (User user : userList)
{
log.info("{}", JSON.toJSONString(user));
}
}
}Repository的方式和Spring Boot JPA非常相似,spring-boot-starter-data-mongodb和spring-boot-starter-data-jpa都来自于Spring Data家族,实现原理基本一致,因此使用Repository完全可以参考JPA用法。
C、MongoDB多数据源
1、添加配置
首先在配置文件添加不同的数据源。
mongodb.primary.uri=mongodb://192.168.0.1:27017
mongodb.primary.database=primary
mongodb.secondary.uri=mongodb://192.168.0.1:27017
mongodb.secondary.database=secondary2、配置两个库的数据源
封装读取以mongodb开头的两个配置文件。
@Getter
@Setter
@ConfigurationProperties(prefix = "mongodb")
public class MultipleMongoProperties
{
private MongoProperties primary = new MongoProperties();
private MongoProperties secondary = new MongoProperties();
}配置不同包路径下使用不同的数据源。
@Configuration
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "top.cfish.mongodbmulti.repository.primary", mongoTemplateRef = "primaryMongoTemplate")
public class PrimaryMongoConfig
{}
@Configuration
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "top.cfish.mongodbmulti.repository.secondary", mongoTemplateRef = "secondaryMongoTemplate")
public class SecondaryMongoConfig
{
}读取配置信息封装为Properties,根据Properties信息构建Factory,再由Factory构建出最后需要使用的MongoTemplate,MongoTemplate在根据包路径配置注入到对应的包下。
@Configuration
public class MultipleMongoConfig
{
@Autowired
private MultipleMongoProperties mongoProperties;
@Primary
@Bean(name = "primaryMongoTemplate")
public MongoTemplate primaryMongoTemplate() throws Exception
{
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
@Bean
@Qualifier("secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() throws Exception
{
return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary()));
}
@Bean
@Primary
public MongoDbFactory primaryFactory(MongoProperties mongo) throws Exception
{
MongoClient client = new MongoClient(new MongoClientURI(mongoProperties.getPrimary().getUri()));
return new SimpleMongoDbFactory(client, mongoProperties.getPrimary().getDatabase());
}
@Bean
public MongoDbFactory secondaryFactory(MongoProperties mongo) throws Exception
{
MongoClient client = new MongoClient(new MongoClientURI(mongoProperties.getSecondary().getUri()));
return new SimpleMongoDbFactory(client, mongoProperties.getSecondary().getDatabase());
}
}3、创建对象和两个库分别对应的Repository
@Getter
@Setter
@AllArgsConstructor
public class User
{
private Long id;
private String username;
private String password;
}
public interface UserPrimaryRepository extends MongoRepository<User, Long>
{
}
public interface UserSecondaryRepository extends MongoRepository<User, Long>
{
}4、测试
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class MongodbMultiApplicationTests
{
@Autowired
UserPrimaryRepository userPrimaryRepository;
@Autowired
UserSecondaryRepository userSecondaryRepository;
@Test
public void TestMulti()
{
this.userPrimaryRepository.save(new User(1L,"isisiwish-frist", "123456"));
this.userSecondaryRepository.save(new User(1L,"isisiwish-sec", "654321"));
List<User> primaries = this.userPrimaryRepository.findAll();
for (User primary : primaries)
{
log.info("{}", JSON.toJSONString(primary));
}
List<User> secondaries = this.userSecondaryRepository.findAll();
for (User secondary : secondaries)
{
log.info("{}", JSON.toJSONString(secondary));
}
}
}输出内容如下:
2019-05-17 14:41:36.153 INFO 44440 --- {"id":1,"password":"123456","username":"isisiwish-frist"}
2019-05-17 14:41:36.182 INFO 44440 --- {"id":1,"password":"654321","username":"isisiwish-sec"}使用Studio 3T分别查看两个库的数据,均已经有对应的user 对象,多数据源使用测试成功。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3127657/ ,如需转载,请注明出处,否则将追究法律责任。