0
点赞
收藏
分享

微信扫一扫

Springboot MongoDB CRUD(一)

概述

  • MongoDB 安装[Mac brew & Docker 方式]
  • MongoDB 基础概述
  • MongoDB Shell CRUD

版本信息:

  • Java JDK 版本:1.8

  • SpringBoot 版本:2.4.5.RELEASE

  • MongoDB 版本:community-4.4

参考地址:

示例项目地址:

项目实战

项目构建等忽略, gradle 构建,配置文件:

plugins {
id 'org.springframework.boot' version '2.4.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}

group = 'com.xjxxxc.mongodb.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'com.google.guava:guava:30.1.1-jre'
implementation 'org.apache.commons:commons-lang3'
implementation 'com.alibaba:fastjson:1.2.76'

compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'

testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.projectlombok:lombok'
}

test {
useJUnitPlatform()
}

包说明:

├── com
│ └── xjxxxc
│ └── mongodb
│ └── demo
│ ├── MongodbDemoApplication.java # 启动类
│ ├── config # 配置类,如数据源
│ ├── listener # 监听器,如 MongoEvent
│ ├── model # 模型
│ │ └── entity # 实体,JPA 使用
│ ├── repository # JPA repository
│ ├── service # *服务层,提供 MongoDB 特性。
│ └── template # MongoDB 模板类使用 DEMO

项目基本配置

application.properties

server.port=8866
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=test
spring.data.mongodb.username=test
spring.data.mongodb.password=123456

MongoDBDataSourceConfig

@Configuration
@EnableMongoRepositories(basePackages = {"com.xjxxxc.mongodb.demo.*"})
public class MongoDBDataSourceConfig extends AbstractMongoClientConfiguration {
@Value(value = "${spring.data.mongodb.host:127.0.0.1}")
private String host;

@Value(value = "${spring.data.mongodb.port:27017}")
private Integer port;

@Value(value = "${spring.data.mongodb.database:test}")
private String database;

@Value(value = "${spring.data.mongodb.username:test}")
private String username;

@Value(value = "${spring.data.mongodb.password:123456}")
private String password;

@Override
public MongoClient mongoClient() {
MongoClient mongoClient = MongoClients.create(
MongoClientSettings.builder()
// 集群设置
.applyToClusterSettings(builder ->
builder.hosts(Arrays.asList(new ServerAddress(host, port))))
// 凭据
.credential(
MongoCredential
.createCredential(username, database, password.toCharArray()))
.build());
return mongoClient;
}


/**
* Return the name of the database to connect to.
*
* @return must not be {@literal null}.
*/

@Override
protected String getDatabaseName() {
return database;
}

/**
* 去除 _class
* @param databaseFactory
* @param customConversions
* @param mappingContext
* @return MappingMongoConverter
*/

@Override
public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory, MongoCustomConversions customConversions, MongoMappingContext mappingContext) {

DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
converter.setCustomConversions(customConversions());
converter.setCodecRegistryProvider(mongoDbFactory());
// Don't save _class to mongo
converter.setTypeMapper(new DefaultMongoTypeMapper(null));

return converter;
}


}

Repositories

@CustomerId [自定义 ID 生成策略]

/**
* 自定义 ID
*/

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomerId {
}

SaveEventListener


/**
* MongoDB 监听器
*/

@Slf4j
@Component
public class SaveEventListener extends AbstractMongoEventListener {

/**
* 在将Document插入或保存在数据库中之前,在 insert,insertList和save操作中调用。
* @param event
*/

@Override
public void onBeforeSave(BeforeSaveEvent event) {
super.onBeforeSave(event);
Object source = event.getSource();
ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (!field.isAnnotationPresent(CustomerId.class)) {
return;
}
// 如果字段添加了我们自定义的 @CustomerId 注解
Object object = field.get(source);
// 需根据是否有值进行主键生成,save 操作时存在 update 与 insert ,会导致更新时变成 insert 。
if(Objects.nonNull(object) && !StringUtils.isNotEmpty(object.toString())){
try {
// 剔除 Id >= OL 的情况 不注入
Long tmp = Long.parseLong(object.toString());
if(tmp.longValue() > 0L){
return;
}
}catch (Exception e){
// 非法 ID
log.info("自动注入 ID 有异常,{}", e.getMessage());
}
}
// 具体业务使用其他方式
field.set(source, RandomUtils.nextLong());
}
});

if(log.isDebugEnabled()){
log.debug("onBeforeSave -> {}", event);
}
}

/**
* 在 object 被MongoConverter转换为Document之前,在MongoTemplate insert,insertList和save操作中调用。
* @param event
*/

@Override
public void onBeforeConvert(BeforeConvertEvent event) {
Object source = event.getSource();
ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (!field.isAnnotationPresent(CustomerId.class)) {
return;
}
// 如果字段添加了我们自定义的 @CustomerId 注解
Object object = field.get(source);
// 需根据是否有值进行主键生成,save 操作时存在 update 与 insert ,会导致更新时变成 insert 。
if(Objects.nonNull(object) && !StringUtils.isNotEmpty(object.toString())){
try {
// 剔除 Id >= OL 的情况 不注入
Long tmp = Long.parseLong(object.toString());
if(tmp.longValue() > 0L){
return;
}
}catch (Exception e){
// 非法 ID
log.info("自动注入 ID 有异常,{}", e.getMessage());
}
}
// 具体业务使用其他方式
field.set(source, RandomUtils.nextLong());
}
});
if(log.isDebugEnabled()){
log.debug("onBeforeConvert -> {}", event);
}
}
}

BaseEntity

/**
* 基础 Entity ,抽出公用字段
*/

@Getter
@Setter
@SuperBuilder
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity implements Serializable {

/**
* 使用自定义 ID
*/

@Id
@CustomerId
private Long id;

@Field("saas_id")
@Indexed
protected Long saasId;

@Field("del_status")
protected Integer delStatus;

@CreatedBy
@Field("create_user")
protected String createUser;

@LastModifiedBy
@Field("update_user")
protected String updateUser;

@CreatedDate
@Field("create_time")
protected Date createTime;

@LastModifiedDate
@Field("update_time")
protected Date updateTime;

/**
* 创建基础字段默认值
*/

public void initBaseProperties() {
if (this.delStatus == null) {
this.delStatus = 1;
}
if (createUser == null) {
this.createUser = "SYSTEM";
}
if (updateUser == null) {
this.updateUser = "SYSTEM";
}
if (createTime == null) {
this.createTime = new Date(System.currentTimeMillis());
}
if (updateTime == null) {
this.updateTime = new Date(System.currentTimeMillis());
}
}
}

Post

/**
* Post entity
*/

@Data
@SuperBuilder
@Document(collection = "post")
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper=false)
public class Post extends BaseEntity {
private String title;

private String content;

private String remark;

private List<Integer> testList;

}

PostRepository

/**
* Post Repository
*/

@Repository
public interface PostRepository extends MongoRepository<Post, String> {
}

PostRepositoryTest

/**
* PostRepository 测试
*/

@SpringBootTest
class PostRepositoryTest {

@Autowired
private PostRepository postRepository;

/**
* 测试 Post 实例
*/

Post post = Post.builder()
.content("conten of " + Math.random() * 10000)
.title("conten of " + Math.random() * 10000)
.remark("")
.build();

/**
* 测试 Repository insert
*/

void insert(){
Post insertPost = postRepository.insert(post);
Assert.notNull(insertPost,"PostRepository insert -> error");
}


/**
* 测试 Repository save
*/

void save(){
// save 方法会根据主键来确定是 insert or update
Post insertPost = postRepository.save(post);
Assert.notNull(insertPost,"PostRepository save -> insert error");

insertPost.setRemark("update");
Post updatePost = postRepository.save(insertPost);
Assert.isTrue("update".equals(updatePost.getRemark()),"PostRepository save -> update error");

}

/**
* 测试 Repository findAll
*/

void findAll(){
List<Post> postList = postRepository.findAll();

Assert.notEmpty(postList,"PostRepository findAll -> error");
}

/**
* 测试 Repository findAll
*/

void findById(){
Post insertPost = postRepository.save(post);
Assert.notNull(insertPost,"PostRepository findAll -> insert error");

Optional<Post> queryPost = postRepository.findById(String.valueOf(insertPost.getId()));
Assert.isTrue(queryPost.isPresent(),"PostRepository findById -> error");
}

/**
* 测试 Repository findAll
*/

void findOne(){
post.setRemark("findOne");
Post insertPost = postRepository.save(post);
Assert.notNull(insertPost,"PostRepository findAll -> insert error");

Post queryCondition = Post.builder().remark("findOne").build();
Example<Post> postExample= Example.of(queryCondition);
Optional<Post> queryPost = postRepository.findOne(postExample);
Assert.isTrue(queryPost.isPresent(),"PostRepository findOne -> error");
}

/**
* 测试 Repository delete
*/

void delete(){
// 先插入数据
post.setRemark("delete");
Post insertPost = postRepository.save(post);

postRepository.delete(insertPost);

Optional<Post> queryPost = postRepository.findById(String.valueOf(insertPost.getId()));
Assert.isTrue(!queryPost.isPresent(),"PostRepository delete -> error");
}

}

MongoTemplate

这里使用 Spring Data MongoDB 封装的 MongoDB 官方 Java 驱动 MongoTemplate 对 MongoDB 进行操作。

举报

相关推荐

0 条评论