Hướng dẫn entity mongodb - thực thể mongodb

Note: Bài viết mang tích chất lưu lại kiến thức để sử dụng sau, do mày mò khắp google nhặt mỗi nơi một tí mới giải quyết được, nếu bạn nào gặp vấn đề tương tự thì có thể tham khảo.

Số là mình bắt đầu thực hiện một dự án mới trên Spring Boot và cần làm việc với NoSQL, cụ thể là Mông Gô Đê Bê (MongoDB), Trước thì mình có đọc và tham khảo qua về SQL và NoSQL rồi, tuy nhiên mình chỉ làm việc với MySQL, SQL, Postgre, Oracle - rặt một đám SQL. Đơn giản thì mình nghĩ chắc connect Mongo cũng thế thôi, vì JPA và Hibernate viết ra để dùng ALL In ONE mà. Cơ mà đâm đầu vào thì nó cũng mệt mỏi vãi đạn.

Những thứ cần chuẩn bị:

1 project Spring Boot maven hay gradle thì tùy, Mình xài gradle

Server Mongo ( Local cũng được)

Mongo Compass( Có cũng dc mà không cũng được)

IDE - tất nhiên ( M xài Intelij, bản 2020 trở lên tool mới hỗ trợ kết nối Mongo nhé)

Trước tiên các bạn cần nhớ bảng trong Mongo không gọi là Table mà

Table = Collection

Row = Documnent ( Cặp key value)

Còn vài thứ nữa các bạn tham khảo bài của bạn này nhé: Hướng dẫn Mongo cơ bản

Ấy thế mà trong entity @Table lại thay bằng @Document chứ không có cái @Collection ) Méo hiểu.

Hướng dẫn entity mongodb - thực thể mongodb
) Méo hiểu.

CỤ thể thì các bước cần làm như sau

1 - Thêm dependencies:

Các bạn cần:

org.springframework.data:spring-data-mongodb
org.mongodb:mongo-java-driver:3.12.11

2 - Config trong file yml

Chắc hẳn các bạn đã quyen với kiểu connect này:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver

Nhưng cụ Mongo thì đi một đường riêng:

spring:
  data:
    mongodb:
      authentication-database: admin
      database: test
      host: localhost
      port: 27017 

Ồ, Good Jobs. Có vẻ ngắn gọn ra phết nhờ

Run cái coi. Lỗi sấp mặt lợn, và sau 10p mò mò à nó k dùng @ Table mà xài @ Document + Repository thì extends MongoRepository thay vì JpaRepository

3 - Entity - Chỉ cần @Id thôi nhé, không cần chỉ định column cũng dc. right

@Entity
@Document(value = "user")
public class UserAccount {
    @Id
    private Integer id;

    private String userName;

4- Repository

@Repository
public interface UserAccountRepository extends MongoRepository<UserAccount,Integer> {

 }

5 - Config Mongo

===> có vẻ ổn nhờ, Run cái nữa nào --- lại lỗi-- Google tiếp. À lại config tiếp:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class , MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})

== chạy thử, hơi giunnnnnn. Lại hẹo. Lần này lỗi có vẻ tường minh tí

Lỗi đây: A component required a bean named 'mongoTemplate' that could not be found.

Có vẻ thiếu Context không kiếm dc cái bean kia. Lại mò GG tiếp Đây rồi, mò mãi mới kiếm được trên GitHub, chắc của mấy anh Ấn thần thánh

@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {

    @Override
    protected String getDatabaseName() {
        return env.getProperty("spring.data.mongodb.database");
    }

}

Run lại cái nào Úi xời mừng rơi nước mắt, chạy rồi )))))))))))

Hướng dẫn entity mongodb - thực thể mongodb
)))))))))))

Đấy, cụ thể là các bạn chú ý mấy cái nghớ nghẩn đó.

Và đặc biệt trong file pom/build không được thiếu thằng này nhé " org.mongodb:mongo-java-driver" , không có nó là cái AbstractMongoClientConfiguration không có đủ client để run và hẹo luôn nha. Còn lại CRUD thì khả năng không khác các loại khác đâu, Query thì nhớ xài PLSQL nhá

Có thể các bạn thấy mình viết đơn giản có ba lần "**Run thử phát xem **" là chạy mượt mà bày vẽ viết cái bài hướng dẫn. Thực tế thì mình mất xừ buổi tối để connect mà chả giải quyết được việc gì khác, " **Run thử **" cũng đâu đấy 10-20 lần nha ))

Hướng dẫn entity mongodb - thực thể mongodb
))

Thank!!!

P/S bạn nào có cách ngắn hơn thì chỉ mình cái nhé

Giới thiệu

Xin chào mọi người, Trong bài viết này mình sẽ giới thiệu cách làm việc với MongoDB trong ASP.NET Core thông qua Repository Pattern. Nếu các bạn đang định làm theo những thứ bên dưới thì bài viết này dành cho bạn.

ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/getting-started/?view=aspnetcore-2.2&tabs=windows

MongoDB: https://www.mongodb.com/

Repository Pattern: https://dev.to/kylegalbraith/getting-familiar-with-the-awesome-repository-pattern--1ao3

Các công cụ cài đặt

MongoDB

Để kết nối được vào MongoDB thì đương nhiên trước tiên phải cài đặt MongoDB. Chúng ta sẽ thực hiện implement trên Windows nên cũng sẽ cài đặt MongoDB trên windows, hãy follow theo những step ở đây https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

MongoDB UI viewer

Để xem dữ liệu ở MongoDB một cách tường minh trên UI, thì bạn nên cài đặt MongoDB Compass hoặc là Robo3T, nói chung thì xài cái nào cũng được. Cài đặt MongoDB Compass ở đây: https://www.mongodb.com/products/compass Cài đặt Robo3T ở đây: https://robomongo.org/

Triển khai

Ở đây mình sẽ triển khai 1 project CRUD đơn giản, với entity là Lesson.

Cấu trúc solution

Solution chia ra làm 4 project nhỏ tương ứng với các chức năng

  • Common: dùng để thực hiện những task common, lưu các biến và enum common.: dùng để thực hiện những task common, lưu các biến và enum common.
  • Data: chính là tầng để thực hiện kết nối đến database, CRUD ở tầng thấp nhất. Chứa các repository tương ứng với mỗi entity: chính là tầng để thực hiện kết nối đến database, CRUD ở tầng thấp nhất. Chứa các repository tương ứng với mỗi entity
  • Service: Sử dụng lại các Repository ở tầng Data để xử lý dữ liệu: Sử dụng lại các Repository ở tầng Data để xử lý dữ liệu
  • Web: chính là tầng trên cùng, gồm các controller để gọi đến tầng service.: chính là tầng trên cùng, gồm các controller để gọi đến tầng service.

Hướng dẫn entity mongodb - thực thể mongodb

Tầng Repository

Đây chính là tầng để giao tiếp trực tiếp với MongoDB. Nên để có thể kết nối được với MongoDB thì chúng ta phải cài đặt package MongoDB.Driver Hãy tìm kiếm package này trên nuget và tiến hành install nó ở tầng Data.MongoDB.Driver Hãy tìm kiếm package này trên nuget và tiến hành install nó ở tầng Data.

Hướng dẫn entity mongodb - thực thể mongodb

Base Entity

public class BaseEntity
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime UpdatedAt { get; set; }
        public DateTime? DeletedAt { get; set; }
    }

Base Entity là class base cho các entity được lưu ở MongoDB. BsonId -> chỉ rõ trường Id chính là key trong table BsonRepresentation(BsonType.ObjectId) -> chỉ rõ Id có kiểu dữ liệu ObjectId trong MongoDB

Entity Lesson

public class Lesson:BaseEntity
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public string Image { get; set; }     
    }

Class này chỉ chứa một số field cần thiết của Lesson bao gồm Title, Description, Image

Generic Repository

public interface IRepository<TEntity> : IDisposable where TEntity : class
    {
        Task<TEntity> Add(TEntity obj);
        Task<TEntity> GetById(string id);
        Task<IEnumerable<TEntity>> GetAll();
        Task<TEntity> Update(string id, TEntity obj);
        Task<bool> Remove(string id);
    }

Interface này chứa các hàm cơ bản cho 1 repository

MongoDbSetting

public class MongoDbSettings : IMongoDbSettings
    {
        public string CollectionName { get; set; }
        public string ConnectionString { get; set; }
        public string DatabaseName { get; set; }
    }

    public interface IMongoDbSettings
    {
        string CollectionName { get; set; }
        string ConnectionString { get; set; }
        string DatabaseName { get; set; }
    }

Chứa các property cần thiết để kết nối đến MongoDB bao gồm collectionName, connectionString và DatabaseName. Những property này nằm trong connectionString được lưu ở appSettings.json

MongoDB context

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
0

Class MongoContext sử dụng MongoDbSetting để kết nối đến database, trả về 1 object Database để repository lấy đi thao tác với các entity.

Base Repository

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
1

Đây chính là class repository base để thực hiện CRUD, sử dụng MongoDbContext. Các repository cụ thể cho các entity sẽ chỉ cần kế thừa class này mà không cần phải đi viết lại các hàm cơ bản CRUD. Có vẻ là đã khá rút gọn code

Hướng dẫn entity mongodb - thực thể mongodb

Lesson Repository

Đến đây thì chỉ cần tạo thêm repository cho lesson. Bạn có thể thấy code nó không có gì, vì toàn bộ các phương thức implement đã được viết ở class base rồi.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
2
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
3

Tầng Service

Implement ở tầng service khá đơn giản, chỉ cần gọi code ở repository. Thực ra vì đây là 1 ứng dụng đơn giản CRUD nên tầng service khá đơn giản, chỉ bao gồm 1 repository tương ứng, với những ứng dụng lớn hơn thì 1 service có thể cần sử dụng nhiều repository để thao tác dữ liệu.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
4
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
5

Controller

Ở đây mình sẽ tạo LessonController và sử dụng LessonService để handle dữ liệu. Có thể thấy là follow code của chúng ta khá rõ ràng. Ở trên web không cần quan tâm đến việc xử lý bên trong (gọi đến database, thao tác các bảng), mọi thứ đã được tầng service ở dưới handle.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
6

Cấu hình DI

Ở trong toàn bộ project thì các bạn thấy là các class chỉ gọi đến và làm việc với các interface chứ không gọi trực tiếp class khác. Điều này làm giảm sự phụ thuộc giữa các class với nhau. Và nó đúng với nguyên lý D trong SOLID. (các bạn có thể đọc nó ở [đây]) (https://toidicodedao.com/2016/06/14/series-solid-cho-thanh-nien-code-cung-dependency-inversion-principle/)

Vì vậy cuối cùng chúng ta phải cấu hình DI để khi gọi interface thì nó sẽ tìm class tương ứng cho chúng ta.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
7

Thêm connection string trong appSetting.json

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloudsigning
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password:
    jpa:
      hibernate:
        ddl-auto: create
        naming:
          implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
          physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyserver
8

Đây chính là đoạn cấu hình chỉ rõ connection đến database test ở localhost, với collection chỉ định là Lesson.

Kết luận

Các bạn hãy thử áp dụng và show kết quả xem nhé. Trên đây là hướng dẫn của mình để hướng dẫn bạn cách làm việc với MongoDB ở ASP.NET Core áp dụng Repository Pattern. Hi vọng bài viết có ích. Rất mong góp ý từ mọi người.

Một số bài viết mình đã tham khảo: https://www.brunobrito.net.br/aspnet-core-mongodb-unit-of-work/ https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-2.2&tabs=visual-studio https://deviq.com/repository-pattern/