ITPub博客

首页 > 应用开发 > Java > Spring Boot集成MongoDB实战:从连接到高级查询

Spring Boot集成MongoDB实战:从连接到高级查询

Java 作者:bhluo 时间:2025-11-19 16:16:05 0 删除 编辑

# Spring Boot集成MongoDB实战:从连接到高级查询


MongoDB作为领先的NoSQL数据库,与Spring Boot的集成为Java开发者提供了强大的数据持久化方案。本文将详细介绍Spring Boot集成MongoDB的完整流程,涵盖基础配置、数据操作和高级特性。


## 环境准备与依赖配置


### Maven依赖配置


```xml

<dependencies>

    <!-- Spring Boot Starter Data MongoDB -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-data-mongodb</artifactId>

    </dependency>

    

    <!-- Spring Boot Starter Web -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    

    <!-- Lombok -->

    <dependency>

        <groupId>org.projectlombok</groupId>

        <artifactId>lombok</artifactId>

        <optional>true</optional>

    </dependency>

    

    <!-- 测试依赖 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

    

    <!-- 验证依赖 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-validation</artifactId>

    </dependency>

</dependencies>

<"jjqx.nbazhib.com">

<"xamx.nbazhib.com">

<"kfzf.nbazhib.com">

```


### 应用配置


```yaml

# application.yml

spring:

  data:

    mongodb:

      # 连接字符串方式(推荐)

      uri: mongodb://username:password@localhost:27017/mydatabase

      

      # 或者使用单独参数方式

      host: localhost

      port: 27017

      database: mydatabase

      username: username

      password: password

      authentication-database: admin  # 认证数据库

      

  # 可选配置

  jackson:

    default-property-inclusion: NON_NULL  # 不序列化null值


# 自定义MongoDB配置

app:

  mongodb:

    connection-timeout: 5000

    socket-timeout: 30000

    max-connection-idle-time: 60000

    min-connections: 10

    max-connections: 100

```


## 实体类设计与注解


### 基础实体类


```java

import org.springframework.data.annotation.Id;

import org.springframework.data.mongodb.core.mapping.Document;

import org.springframework.data.mongodb.core.mapping.Field;


import javax.validation.constraints.NotBlank;

import javax.validation.constraints.Email;

import java.time.LocalDateTime;

import java.util.List;


/**

 * 用户实体类

 */

@Document(collection = "users")  // 指定集合名称

@Data

@NoArgsConstructor

@AllArgsConstructor

@Builder

<"lfca.nbazhib.com">

<"xpmx.nbazhib.com">

<"pfyr.nbazhib.com">

public class User {

    

    @Id

    private String id;  // MongoDB使用String类型的ID

    

    @NotBlank(message = "用户名不能为空")

    @Field("username")  // 指定字段名称

    private String username;

    

    @Email(message = "邮箱格式不正确")

    @Field("email")

    private String email;

    

    @Field("age")

    private Integer age;

    

    @Field("created_date")

    private LocalDateTime createdDate;

    

    @Field("updated_date")

    private LocalDateTime updatedDate;

    

    @Field("profile")

    private Profile profile;  // 嵌入文档

    

    @Field("addresses")

    private List<Address> addresses;  // 数组类型

    

    @Field("status")

    private UserStatus status;

    

    // 索引字段示例

    @Field("tags")

    private List<String> tags;

    

    public enum UserStatus {

        ACTIVE, INACTIVE, SUSPENDED

    }

    

    /**

     * 嵌入文档 - 用户档案

     */

    @Data

    @NoArgsConstructor

    @AllArgsConstructor

    @Builder

    public static class Profile {

        @Field("first_name")

        private String firstName;

        

        @Field("last_name")

        private String lastName;

        

        @Field("bio")

        private String bio;

        

        @Field("avatar_url")

        private String avatarUrl;

    }

    

    /**

     * 嵌入文档 - 地址

     */

    @Data

    @NoArgsConstructor

    @AllArgsConstructor

    @Builder

<"fbzj.nbazhib.com">

<"iutv.nbazhib.com">

<"qmsj.nbazhib.com">

    public static class Address {

        @Field("type")

        private AddressType type;

        

        @Field("street")

        private String street;

        

        @Field("city")

        private String city;

        

        @Field("country")

        private String country;

        

        @Field("postal_code")

        private String postalCode;

        

        public enum AddressType {

            HOME, WORK, OTHER

        }

    }

    

    /**

     * 生命周期回调方法

     */

    @PrePersist

    protected void onCreate() {

        this.createdDate = LocalDateTime.now();

        this.updatedDate = LocalDateTime.now();

        if (this.status == null) {

            this.status = UserStatus.ACTIVE;

        }

    }

    

    @PreUpdate

    protected void onUpdate() {

        this.updatedDate = LocalDateTime.now();

    }

}

```


### 复杂实体类示例


```java

/**

 * 博客文章实体类 - 展示复杂文档结构

 */

@Document(collection = "articles")

@Data

@NoArgsConstructor

@AllArgsConstructor

@Builder

<"nhwd.nbazhib.com">

<"zzhe.nbazhib.com">

<"umui.nbazhib.com">

public class Article {

    

    @Id

    private String id;

    

    @NotBlank(message = "标题不能为空")

    @Field("title")

    private String title;

    

    @Field("content")

    private String content;

    

    @Field("author_id")

    private String authorId;

    

    @Field("tags")

    private List<String> tags;

    

    @Field("categories")

    private List<String> categories;

    

    @Field("metadata")

    private ArticleMetadata metadata;

    

    @Field("comments")

    private List<Comment> comments;

    

    @Field("view_count")

    private Long viewCount = 0L;

    

    @Field("like_count")

    private Long likeCount = 0L;

    

    @Field("status")

    private ArticleStatus status;

    

    @Field("created_at")

    private LocalDateTime createdAt;

    

    @Field("updated_at")

    private LocalDateTime updatedAt;

    

    @Field("published_at")

    private LocalDateTime publishedAt;

    

    public enum ArticleStatus {

        DRAFT, PUBLISHED, ARCHIVED

    }

    

    /**

     * 文章元数据

     */

    @Data

    @NoArgsConstructor

    @AllArgsConstructor

    @Builder

    public static class ArticleMetadata {

        @Field("word_count")

        private Integer wordCount;

        

        @Field("read_time")

        private Integer readTime;  // 阅读时间(分钟)

        

        @Field("featured_image")

        private String featuredImage;

        

        @Field("seo_description")

        private String seoDescription;

        

        @Field("seo_keywords")

        private List<String> seoKeywords;

    }

    

    /**

     * 评论嵌入文档

     */

    @Data

    @NoArgsConstructor

    @AllArgsConstructor

    @Builder

<"hzdy.nbazhib.com">

<"wltn.nbazhib.com">

<"sdar.nbazhib.com">

    public static class Comment {

        @Field("id")

        private String id;

        

        @Field("user_id")

        private String userId;

        

        @Field("user_name")

        private String userName;

        

        @Field("content")

        private String content;

        

        @Field("created_at")

        private LocalDateTime createdAt;

        

        @Field("like_count")

        private Integer likeCount = 0;

        

        @Field("replies")

        private List<Comment> replies;  // 嵌套回复

    }

}

```


## Repository数据访问层


### 基础Repository接口


```java

/**

 * 用户Repository - 继承MongoRepository获得基础CRUD能力

 */

@Repository

public interface UserRepository extends MongoRepository<User, String> {

    

    // 根据用户名查询

    Optional<User> findByUsername(String username);

    

    // 根据邮箱查询

    Optional<User> findByEmail(String email);

    

    // 根据状态查询用户列表

    List<User> findByStatus(User.UserStatus status);

    

    // 根据年龄范围查询

    List<User> findByAgeBetween(Integer minAge, Integer maxAge);

    

    // 根据城市查询(嵌套文档查询)

    List<User> findByAddressesCity(String city);

    

    // 根据标签包含查询

    List<User> findByTagsContaining(String tag);

    

    // 根据用户名模糊查询

    List<User> findByUsernameContainingIgnoreCase(String username);

    

    // 统计状态为活跃的用户数量

    Long countByStatus(User.UserStatus status);

    

    // 根据状态删除用户

    void deleteByStatus(User.UserStatus status);

    

    // 根据用户名和状态查询

    Optional<User> findByUsernameAndStatus(String username, User.UserStatus status);

    

    // 根据邮箱或用户名查询

    List<User> findByEmailOrUsername(String email, String username);

    

    // 根据年龄排序查询

    List<User> findByAgeGreaterThanOrderByAgeDesc(Integer age);

}


/**

 * 自定义User Repository - 扩展复杂查询

 */

public interface CustomUserRepository {

    

    List<User> findActiveUsersWithPagination(int page, int size);

    

    List<User> searchUsers(String keyword, List<String> fields);

    

    void updateUserStatus(String userId, User.UserStatus status);

    

    List<User> findUsersByGeoNear(double longitude, double latitude, double maxDistance);

}


/**

 * 自定义Repository实现

 */

@Slf4j

<"kpnr.nbazhib.com">

<"gqol.nbazhib.com">

<"eeeo.nbazhib.com">

public class CustomUserRepositoryImpl implements CustomUserRepository {

    

    @Autowired

    private MongoTemplate mongoTemplate;

    

    @Override

    public List<User> findActiveUsersWithPagination(int page, int size) {

        Query query = new Query()

                .with(Sort.by(Sort.Direction.DESC, "createdDate"))

                .with(PageRequest.of(page, size));

        

        query.addCriteria(Criteria.where("status").is(User.UserStatus.ACTIVE));

        

        return mongoTemplate.find(query, User.class);

    }

    

    @Override

    public List<User> searchUsers(String keyword, List<String> fields) {

        TextCriteria criteria = TextCriteria.forDefaultLanguage()

                .matchingAny(keyword);

        

        Query query = TextQuery.queryText(criteria)

                .sortByScore()

                .with(Sort.by(Sort.Direction.DESC, "createdDate"));

        

        return mongoTemplate.find(query, User.class);

    }

    

    @Override

    public void updateUserStatus(String userId, User.UserStatus status) {

        Query query = new Query(Criteria.where("id").is(userId));

        Update update = new Update().set("status", status)

                                  .set("updatedDate", LocalDateTime.now());

        

        UpdateResult result = mongoTemplate.updateFirst(query, update, User.class);

        log.info("更新用户状态影响记录数: {}", result.getModifiedCount());

    }

    

    @Override

    public List<User> findUsersByGeoNear(double longitude, double latitude, double maxDistance) {

        // 地理空间查询实现

        Point location = new Point(longitude, latitude);

        NearQuery nearQuery = NearQuery.near(location)

                .maxDistance(new Distance(maxDistance, Metrics.KILOMETERS));

        

        return mongoTemplate.geoNear(nearQuery, User.class).getContent()

                .stream()

                .map(GeoResult::getContent)

                .collect(Collectors.toList());

    }

}


// 扩展的Repository接口

public interface ExtendedUserRepository extends UserRepository, CustomUserRepository {

    // 组合基础Repository和自定义Repository

}

```


### 文章Repository示例


```java

/**

 * 文章Repository - 复杂查询示例

 */

@Repository

public interface ArticleRepository extends MongoRepository<Article, String> {

    

    // 根据作者ID查询

    List<Article> findByAuthorId(String authorId);

    

    // 根据状态查询

    List<Article> findByStatus(Article.ArticleStatus status);

    

    // 根据标签查询

    List<Article> findByTagsContaining(String tag);

    

    // 根据分类查询并按发布时间排序

    List<Article> findByCategoriesContainingOrderByPublishedAtDesc(String category);

    

    // 统计作者的文章数量

    Long countByAuthorId(String authorId);

    

    // 根据作者ID和状态查询

    List<Article> findByAuthorIdAndStatus(String authorId, Article.ArticleStatus status);

    

    // 根据发布时间范围查询

    List<Article> findByPublishedAtBetween(LocalDateTime start, LocalDateTime end);

    

    // 根据浏览量排序查询热门文章

    List<Article> findByStatusOrderByViewCountDesc(Article.ArticleStatus status, Pageable pageable);

    

    // 使用@Query注解自定义查询

    @Query("{ 'tags': { $in: ?0 }, 'status': 'PUBLISHED' }")

    List<Article> findPublishedArticlesByTags(List<String> tags);

    

    @Query("{ 'metadata.wordCount': { $gt: ?0, $lt: ?1 } }")

    List<Article> findByWordCountRange(Integer minWords, Integer maxWords);

    

    @Query(value = "{ 'authorId': ?0 }", fields = "{ 'title': 1, 'publishedAt': 1 }")

    List<Article> findArticleTitlesByAuthor(String authorId);

    

    // 聚合查询示例

    @Aggregation(pipeline = {

        "{ $match: { 'status': 'PUBLISHED' } }",

        "{ $group: { _id: '$authorId', totalViews: { $sum: '$viewCount' } } }",

        "{ $sort: { totalViews: -1 } }",

        "{ $limit: 10 }"

    })

    List<AuthorViews> findTopAuthorsByViews();

    

    interface AuthorViews {

        String get_id();  // authorId

        Long getTotalViews();

    }

}

```


## Service业务逻辑层


### 用户服务实现


```java

@Service

@Slf4j

<"jtui.nbazhib.com">

<"wvks.nbazhib.com">

<"gydu.nbazhib.com">

public class UserService {

    

    @Autowired

    private ExtendedUserRepository userRepository;

    

    @Autowired

    private MongoTemplate mongoTemplate;

    

    /**

     * 创建用户

     */

    public User createUser(User user) {

        // 检查用户名是否已存在

        if (userRepository.findByUsername(user.getUsername()).isPresent()) {

            throw new BusinessException("用户名已存在");

        }

        

        // 检查邮箱是否已存在

        if (user.getEmail() != null && 

            userRepository.findByEmail(user.getEmail()).isPresent()) {

            throw new BusinessException("邮箱已被注册");

        }

        

        User savedUser = userRepository.save(user);

        log.info("用户创建成功: {}", savedUser.getUsername());

        

        return savedUser;

    }

    

    /**

     * 根据ID查询用户

     */

    public User getUserById(String id) {

        return userRepository.findById(id)

                .orElseThrow(() -> new BusinessException("用户不存在"));

    }

    

    /**

     * 更新用户信息

     */

    public User updateUser(String id, UserUpdateRequest request) {

        User existingUser = getUserById(id);

        

        // 更新允许修改的字段

        if (request.getEmail() != null) {

            // 检查邮箱是否被其他用户使用

            userRepository.findByEmail(request.getEmail())

                    .ifPresent(user -> {

                        if (!user.getId().equals(id)) {

                            throw new BusinessException("邮箱已被其他用户使用");

                        }

                    });

            existingUser.setEmail(request.getEmail());

        }

        

        if (request.getAge() != null) {

            existingUser.setAge(request.getAge());

        }

        

        if (request.getProfile() != null) {

            if (existingUser.getProfile() == null) {

                existingUser.setProfile(new User.Profile());

            }

            // 更新档案信息

            if (request.getProfile().getFirstName() != null) {

                existingUser.getProfile().setFirstName(request.getProfile().getFirstName());

            }

            if (request.getProfile().getLastName() != null) {

                existingUser.getProfile().setLastName(request.getProfile().getLastName());

            }

            if (request.getProfile().getBio() != null) {

                existingUser.getProfile().setBio(request.getProfile().getBio());

            }

        }

        

        User updatedUser = userRepository.save(existingUser);

        log.info("用户信息更新成功: {}", updatedUser.getUsername());

        

        return updatedUser;

    }

    

    /**

     * 分页查询用户列表

     */

    public Page<User> getUsers(UserQuery query, Pageable pageable) {

        Query mongoQuery = buildUserQuery(query);

        

        long total = mongoTemplate.count(mongoQuery, User.class);

        List<User> users = mongoTemplate.find(

            mongoQuery.with(pageable).with(Sort.by(Sort.Direction.DESC, "createdDate")), 

            User.class

        );

        

        return new PageImpl<>(users, pageable, total);

    }

    

    /**

     * 构建查询条件

     */

    private Query buildUserQuery(UserQuery query) {

        Query mongoQuery = new Query();

        List<Criteria> criteriaList = new ArrayList<>();

        

        if (StringUtils.hasText(query.getUsername())) {

            criteriaList.add(Criteria.where("username").regex(query.getUsername(), "i"));

        }

        

        if (StringUtils.hasText(query.getEmail())) {

            criteriaList.add(Criteria.where("email").regex(query.getEmail(), "i"));

        }

        

        if (query.getMinAge() != null) {

            criteriaList.add(Criteria.where("age").gte(query.getMinAge()));

        }

        

        if (query.getMaxAge() != null) {

            criteriaList.add(Criteria.where("age").lte(query.getMaxAge()));

        }

        

        if (query.getStatus() != null) {

            criteriaList.add(Criteria.where("status").is(query.getStatus()));

        }

        

        if (CollectionUtils.isNotEmpty(query.getTags())) {

            criteriaList.add(Criteria.where("tags").in(query.getTags()));

        }

        

        if (!criteriaList.isEmpty()) {

            mongoQuery.addCriteria(new Criteria().andOperator(

                criteriaList.toArray(new Criteria[0])

            ));

        }

        

        return mongoQuery;

    }

    

    /**

     * 搜索用户

     */

    public List<User> searchUsers(String keyword) {

        return userRepository.searchUsers(keyword, 

            Arrays.asList("username", "email", "profile.firstName", "profile.lastName"));

    }

    

    /**

     * 批量更新用户状态

     */

    @Transactional

    public void batchUpdateStatus(List<String> userIds, User.UserStatus status) {

        Query query = new Query(Criteria.where("id").in(userIds));

        Update update = new Update()

                .set("status", status)

                .set("updatedDate", LocalDateTime.now());

        

        UpdateResult result = mongoTemplate.updateMulti(query, update, User.class);

        log.info("批量更新用户状态,影响记录数: {}", result.getModifiedCount());

    }

    

    /**

     * 添加用户标签

     */

<"clxe.nbazhib.com">

<"sozn.nbazhib.com">

<"qmkd.nbazhib.com">

    public void addUserTag(String userId, String tag) {

        Query query = new Query(Criteria.where("id").is(userId));

        Update update = new Update().addToSet("tags", tag);

        

        UpdateResult result = mongoTemplate.updateFirst(query, update, User.class);

        if (result.getModifiedCount() == 0) {

            throw new BusinessException("用户不存在或标签已存在");

        }

    }

}


@Data

class UserUpdateRequest {

    private String email;

    private Integer age;

    private User.Profile profile;

}


@Data

class UserQuery {

    private String username;

    private String email;

    private Integer minAge;

    private Integer maxAge;

    private User.UserStatus status;

    private List<String> tags;

}

```


## 控制器层实现


### REST API控制器


```java

@RestController

@RequestMapping("/api/users")

@Validated

@Slf4j

public class UserController {

    

    @Autowired

    private UserService userService;

    

    /**

     * 创建用户

     */

    @PostMapping

    public ResponseEntity<ApiResponse<User>> createUser(@Valid @RequestBody User user) {

        User createdUser = userService.createUser(user);

        return ResponseEntity.status(HttpStatus.CREATED)

                .body(ApiResponse.success("用户创建成功", createdUser));

    }

    

    /**

     * 根据ID查询用户

     */

    @GetMapping("/{id}")

    public ResponseEntity<ApiResponse<User>> getUser(@PathVariable String id) {

        User user = userService.getUserById(id);

        return ResponseEntity.ok(ApiResponse.success(user));

    }

    

    /**

     * 更新用户信息

     */

    @PutMapping("/{id}")

    public ResponseEntity<ApiResponse<User>> updateUser(

            @PathVariable String id,

            @Valid @RequestBody UserUpdateRequest request) {

        

        User updatedUser = userService.updateUser(id, request);

        return ResponseEntity.ok(ApiResponse.success("用户更新成功", updatedUser));

    }

    

    /**

     * 分页查询用户列表

     */

    @GetMapping

    public ResponseEntity<ApiResponse<Page<User>>> getUsers(

            UserQuery query,

            @RequestParam(defaultValue = "0") int page,

            @RequestParam(defaultValue = "10") int size) {

        

        Pageable pageable = PageRequest.of(page, size, Sort.by("createdDate").descending());

        Page<User> users = userService.getUsers(query, pageable);

        

        return ResponseEntity.ok(ApiResponse.success(users));

    }

    

    /**

     * 搜索用户

     */

    @GetMapping("/search")

    public ResponseEntity<ApiResponse<List<User>>> searchUsers(

            @RequestParam String keyword) {

        

        List<User> users = userService.searchUsers(keyword);

        return ResponseEntity.ok(ApiResponse.success(users));

    }

    

    /**

     * 添加用户标签

     */

    @PostMapping("/{id}/tags")

    public ResponseEntity<ApiResponse<String>> addUserTag(

            @PathVariable String id,

            @RequestParam String tag) {

        

        userService.addUserTag(id, tag);

        return ResponseEntity.ok(ApiResponse.success("标签添加成功"));

    }

    

    /**

     * 批量更新用户状态

     */

    @PostMapping("/batch-update-status")

    public ResponseEntity<ApiResponse<String>> batchUpdateStatus(

            @RequestBody BatchUpdateRequest request) {

        

        userService.batchUpdateStatus(request.getUserIds(), request.getStatus());

        return ResponseEntity.ok(ApiResponse.success("批量更新成功"));

    }

}


@Data

class BatchUpdateRequest {

<"uftb.nbazhib.com">

<"unnv.nbazhib.com">

<"vcsh.nbazhib.com">

    @NotEmpty(message = "用户ID列表不能为空")

    private List<String> userIds;

    

    @NotNull(message = "状态不能为空")

    private User.UserStatus status;

}

```


## 高级特性与配置


### 自定义MongoDB配置


```java

@Configuration

@Slf4j

public class MongoConfig {

    

    @Value("${app.mongodb.connection-timeout:5000}")

    private int connectionTimeout;

    

    @Value("${app.mongodb.socket-timeout:30000}")

    private int socketTimeout;

    

    @Bean

    public MongoClient mongoClient() {

        ConnectionString connectionString = new ConnectionString(

            "mongodb://username:password@localhost:27017/mydatabase"

        );

        

        MongoClientSettings settings = MongoClientSettings.builder()

                .applyConnectionString(connectionString)

                .applyToConnectionPoolSettings(builder -> 

                    builder.maxSize(100)

                           .minSize(10)

                           .maxWaitTime(30000, TimeUnit.MILLISECONDS))

                .applyToSocketSettings(builder -> 

                    builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS)

                           .readTimeout(socketTimeout, TimeUnit.MILLISECONDS))

                .build();

        

        return MongoClients.create(settings);

    }

    

    @Bean

    public MongoTemplate mongoTemplate() {

        return new MongoTemplate(mongoClient(), "mydatabase");

    }

    

    /**

     * 自动创建索引

     */

    @EventListener(ApplicationReadyEvent.class)

    public void initIndices() {

        MongoTemplate mongoTemplate = mongoTemplate();

        

        // 为用户集合创建索引

        IndexOperations indexOps = mongoTemplate.indexOps(User.class);

        

        // 创建唯一索引

        Index usernameIndex = new Index().on("username", Sort.Direction.ASC).unique();

        indexOps.ensureIndex(usernameIndex);

        

        // 创建复合索引

        Index statusCreatedIndex = new Index()

                .on("status", Sort.Direction.ASC)

                .on("createdDate", Sort.Direction.DESC);

        indexOps.ensureIndex(statusCreatedIndex);

        

        // 创建文本索引用于搜索

        Index textIndex = new Index().on("username", Sort.Direction.ASC)

                .on("email", Sort.Direction.ASC)

                .on("profile.firstName", Sort.Direction.ASC)

                .on("profile.lastName", Sort.Direction.ASC);

        indexOps.ensureIndex(textIndex);

        

        log.info("MongoDB索引初始化完成");

    }

}

```


### 事务配置(MongoDB 4.0+)


```java

@Configuration

@EnableMongoAuditing  // 启用审计功能

@EnableMongoRepositories(basePackages = "com.example.repository")

public class TransactionConfig {

    

    /**

     * 配置Mongo事务管理器

     * 注意:需要MongoDB副本集或分片集群支持

     */

    @Bean

    public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {

        return new MongoTransactionManager(dbFactory);

    }

}


// 事务使用示例

@Service

@Slf4j

<"fmzb.nbazhib.com">

<"zmmm.nbazhib.com">

public class TransactionalUserService {

    

    @Autowired

    private UserRepository userRepository;

    

    @Autowired

    private ArticleRepository articleRepository;

    

    /**

     * 事务操作示例

     */

    @Transactional

    public void createUserWithInitialArticle(User user, Article article) {

        try {

            // 保存用户

            User savedUser = userRepository.save(user);

            

            // 设置文章作者

            article.setAuthorId(savedUser.getId());

            article.setStatus(Article.ArticleStatus.PUBLISHED);

            

            // 保存文章

            articleRepository.save(article);

            

            log.info("用户和初始文章创建成功");

            

        } catch (Exception e) {

            log.error("创建用户和文章失败", e);

            throw new BusinessException("创建失败");

        }

    }

}

```


## 测试与验证


### 集成测试


```java

@DataMongoTest

@ExtendWith(SpringExtension.class)

@Slf4j

class UserRepositoryTest {

    

    @Autowired

    private UserRepository userRepository;

    

    @Autowired

    private MongoTemplate mongoTemplate;

    

    @BeforeEach

    void setUp() {

        userRepository.deleteAll();

    }

    

    @Test

    void testSaveAndFindUser() {

        // 准备测试数据

        User user = User.builder()

                .username("testuser")

                .email("test@example.com")

                .age(25)

                .profile(User.Profile.builder()

                        .firstName("张")

                        .lastName("三")

                        .bio("测试用户")

                        .build())

                .tags(Arrays.asList("vip", "tester"))

                .build();

        

        // 保存用户

        User savedUser = userRepository.save(user);

        

        // 验证保存结果

        assertNotNull(savedUser.getId());

        assertEquals("testuser", savedUser.getUsername());

        

        // 查询验证

        Optional<User> foundUser = userRepository.findById(savedUser.getId());

        assertTrue(foundUser.isPresent());

        assertEquals("test@example.com", foundUser.get().getEmail());

    }

    

    @Test

    void testFindByUsername() {

        // 准备测试数据

        User user = User.builder()

                .username("johndoe")

                .email("john@example.com")

                .age(30)

                .build();

        

        userRepository.save(user);

        

        // 查询验证

        Optional<User> foundUser = userRepository.findByUsername("johndoe");

        assertTrue(foundUser.isPresent());

        assertEquals(30, foundUser.get().getAge());

    }

    

    @Test

    void testCustomQuery() {

        // 准备测试数据

        User user1 = User.builder()

                .username("user1")

                .age(25)

                .status(User.UserStatus.ACTIVE)

                .build();

        

        User user2 = User.builder()

                .username("user2")

                .age(35)

                .status(User.UserStatus.ACTIVE)

                .build();

        

        userRepository.saveAll(Arrays.asList(user1, user2));

        

        // 测试自定义查询

        List<User> activeUsers = userRepository.findByStatus(User.UserStatus.ACTIVE);

        assertEquals(2, activeUsers.size());

        

        List<User> usersInAgeRange = userRepository.findByAgeBetween(20, 30);

        assertEquals(1, usersInAgeRange.size());

    }

}


@SpringBootTest

class UserServiceIntegrationTest {

    

    @Autowired

    private UserService userService;

    

    @Autowired

    private UserRepository userRepository;

    

    @BeforeEach

    void setUp() {

        userRepository.deleteAll();

    }

    

    @Test

    void testCreateUser() {

        User user = User.builder()

                .username("newuser")

                .email("new@example.com")

                .age(28)

                .build();

        

        User createdUser = userService.createUser(user);

        

        assertNotNull(createdUser.getId());

        assertEquals("newuser", createdUser.getUsername());

        assertEquals(User.UserStatus.ACTIVE, createdUser.getStatus());

    }

    

    @Test

    void testCreateUserWithDuplicateUsername() {

        User user1 = User.builder()

                .username("duplicate")

                .email("user1@example.com")

                .build();

        

        userService.createUser(user1);

        

        User user2 = User.builder()

                .username("duplicate")

                .email("user2@example.com")

                .build();

        

        assertThrows(BusinessException.class, () -> userService.createUser(user2));

    }

}

```


## 总结


通过本文的详细实现,我们完成了Spring Boot与MongoDB的完整集成,主要涵盖:


1. **环境配置**:依赖配置和连接字符串设置

2. **实体设计**:使用Spring Data MongoDB注解定义文档结构

3. **数据访问**:Repository模式和自定义查询实现

4. **业务逻辑**:Service层封装复杂业务操作

5. **REST API**:完整的控制器层实现

6. **高级特性**:索引管理、事务支持和自定义配置


这套方案为企业级应用提供了稳定可靠的MongoDB集成方案,具有良好的扩展性和维护性。开发者可以根据具体业务需求,在此基础上进行功能扩展和性能优化。


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

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933680