1. Giới thiệu
Trong quá trình phát triển ứng dụng, việc làm việc với nhiều cơ sở dữ liệu có thể là một yêu cầu thường gặp. Ví dụ, bạn có thể muốn lưu trữ dữ liệu bài viết trong MySQL và dữ liệu khách hàng trong PostgreSQL. Trong bài viết này, chúng ta sẽ tìm hiểu cách kết nối đến cả MySQL và PostgreSQL trong một ứng dụng Spring Boot sử dụng JPA. Chúng ta cũng sẽ sử dụng Docker Compose để quản lý môi trường phát triển, giúp dễ dàng triển khai cơ sở dữ liệu.
2. Cài đặt databases
Cài đặt Docker và Docker Compose
Trước khi bắt đầu, bạn cần cài đặt Docker và Docker Compose.
- Docker là một nền tảng cho phép bạn đóng gói và triển khai ứng dụng trong các container độc lập. Hãy cài đặt Docker bằng cách làm theo hướng dẫn tại đây.
- Docker Compose là một công cụ cho phép bạn định nghĩa và quản lý một nhóm các container Docker sử dụng một tệp cấu hình duy nhất. Hãy cài đặt Docker Compose theo hướng dẫn tại đây.
Tạo tệp docker-compose.yml
Chúng ta sẽ sử dụng Docker Compose để quản lý các container cho cơ sở dữ liệu. Dưới đây là một tệp docker-compose.yml
mẫu:
version: '3'
services:
mysql-db:
image: mysql:latest
container_name: mysql-container
environment:
MYSQL_ROOT_PASSWORD: 123
ports:
- "3306:3306"
networks:
- db-network
volumes:
- mysql-data:/var/lib/mysql
postgres-db:
image: postgres:latest
container_name: postgres-container
environment:
POSTGRES_PASSWORD: 123
ports:
- "5432:5432"
networks:
- db-network
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
db-network:
driver: bridge
volumes:
mysql-data:
postgres-data:
Trong ví dụ trên, chúng ta định nghĩa hai container: một cho MySQL và một cho PostgreSQL, và cấu hình các biến môi trường cần thiết.
3. Thiết Lập Ứng Dụng Spring Boot
Cấu trúc folder của ứng dụng
.
├── HELP.md
├── docker-compose.yml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
│ └── demo
│ ├── DemoMutilpleDatabaseApplication.java
│ ├── config
│ │ ├── DB1Config.java
│ │ └── DB2Config.java
│ ├── db1
│ │ ├── Post.java
│ │ └── PostRepository.java
│ └── db2
│ ├── Customer.java
│ └── CustomerRepository.java
└── resources
└── application.properties
Tạo Các Entity
Trong phần này, chúng ta sẽ tạo các Entity cho MySQL và PostgreSQL.
Entity cho MySQL
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@Table(name = "post")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "name")
private String title;
public Post(String title) {
this.title = title;
}
}
Post.java
Entity cho PostgreSQL
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@Table(name = "customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "name")
private String name;
public Customer(String name) {
this.name = name;
}
}
Customer.java
4. Tạo Repository
Bạn có thể sử dụng các repository để thao tác với cơ sở dữ liệu.
Tạo Repository cho MySQL
public interface PostRepository extends JpaRepository<Post, Integer> {
}
PostRepository.java
Tạo Repository cho PostgreSQL
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
}
CustomerRepository.java
5. Cấu Hình Multiple Data Sources
Cấu hình application.properties
Trong tệp application.properties
, bạn cần cấu hình các thuộc tính kết nối cơ sở dữ liệu cho MySQL và PostgreSQL:
# MySQL Configuration
post.datasource.url=jdbc:mysql://localhost:3306/dbpost
post.datasource.username=root
post.datasource.password=123
post.datasource.driverClassName=com.mysql.cj.jdbc.Driver
# PostgreSQL Configuration
customer.datasource.url=jdbc:postgresql://localhost:5432/dbcustomer
customer.datasource.username=postgres
customer.datasource.password=123
customer.datasource.driverClassName=org.postgresql.Driver
Cấu hình Data Source
Bây giờ chúng ta sẽ đến phần cấu hình cho Database. Chúng ta sẽ thiết lập 2 lớp cấu hình - một Post và một Customer.
Trong mỗi lớp cấu hình, chúng ta cần định nghĩa các thành phần sau:
- DataSource
- EntityManagerFactory
- TransactionManager
Trước tiên, chúng ta cấu hình database Mysql cho entity Post
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "postEntityManagerFactory",
basePackages = {"com.example.demo.db1"},
transactionManagerRef = "postTransactionManager"
)
public class DB1Config {
private final Environment env;
public DB1Config(Environment env) {
this.env = env;
}
@Primary
@Bean(name= "postDataSource")
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(env.getProperty("post.datasource.url"));
ds.setUsername(env.getProperty("post.datasource.username"));
ds.setPassword(env.getProperty("post.datasource.password"));
ds.setDriverClassName(env.getProperty("post.datasource.driverClassName"));
return ds;
}
@Primary
@Bean(name= "postEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManager() {
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setDataSource(dataSource());
JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
bean.setJpaVendorAdapter(adapter);
HashMap<String,Object> properties = new HashMap<>();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
bean.setJpaPropertyMap(properties);
bean.setPackagesToScan("com.example.demo.db1");
return bean;
}
@Primary
@Bean("postTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("postEntityManagerFactory") EntityManagerFactory entityManagerFactory ) {
return new JpaTransactionManager(entityManagerFactory);
}
}
DB1Config.java
Tiếp theo chúng ta tiến hành cấu hình tương tự với database Postgresql cho entity Customer
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "customerEntityManagerFactory",
basePackages = {"com.example.demo.db2"},
transactionManagerRef = "customerTransactionManager"
)
public class DB2Config {
private final Environment env;
public DB2Config(Environment env) {
this.env = env;
}
@Primary
@Bean(name= "customerDataSource")
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(env.getProperty("customer.datasource.url"));
ds.setUsername(env.getProperty("customer.datasource.username"));
ds.setPassword(env.getProperty("customer.datasource.password"));
ds.setDriverClassName(env.getProperty("customer.datasource.driverClassName"));
return ds;
}
@Primary
@Bean(name= "customerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManager() {
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setDataSource(dataSource());
JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
bean.setJpaVendorAdapter(adapter);
HashMap<String,Object> properties = new HashMap<>();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
bean.setJpaPropertyMap(properties);
bean.setPackagesToScan("com.example.demo.db2");
return bean;
}
@Primary
@Bean("customerTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("customerEntityManagerFactory") EntityManagerFactory entityManagerFactory ) {
return new JpaTransactionManager(entityManagerFactory);
}
}
DB2Config.java
6. Kiểm Tra Kết Nối và Thử Nghiệm
Trong phần này, bạn có thể thực hiện các thao tác CRUD với cơ sở dữ liệu MySQL và PostgreSQL sử dụng repository.
@SpringBootApplication
public class DemoMutilpleDatabaseApplication implements CommandLineRunner {
private final PostRepository postRepository;
private final CustomerRepository customerRepository;
public DemoMutilpleDatabaseApplication(PostRepository postRepository, CustomerRepository customerRepository) {
this.postRepository = postRepository;
this.customerRepository = customerRepository;
}
public static void main(String[] args) {
SpringApplication.run(DemoMutilpleDatabaseApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// Lưu Post - MySQL
Post post = new Post("Kết Nối Nhiều Cơ Sở Dữ Liệu trong JPA");
postRepository.save(post);
// Lưu Customer - Postgresql
Customer customer = new Customer("Nguyễn Văn A");
customerRepository.save(customer);
// Thông tin Post
List<Post> postList = postRepository.findAll();
System.out.println("Danh sách Post");
postList.forEach(System.out::println);
// Thông tin customer
List<Customer> customerList = customerRepository.findAll();
System.out.println("Danh sách Customer");
customerList.forEach(System.out::println);
}
}
Kết quả in ra trong màn hình terminal
7. Kết Luận
Trong bài viết này, chúng ta đã thảo luận về cách kết nối nhiều cơ sở dữ liệu trong ứng dụng Spring Boot sử dụng JPA và Docker Compose. Chúng ta đã tạo cấu hình, entity, repository và thực hiện thao tác CRUD với cả MySQL và PostgreSQL.
Lợi Ích của Việc Kết Nối Nhiều Cơ Sở Dữ Liệu
- Khả năng sử dụng nhiều cơ sở dữ liệu trong một ứng dụng.
- Tích hợp dữ liệu từ các nguồn khác nhau.
- Tối ưu hóa hiệu suất và quản lý dữ liệu hiệu quả.
8. Tài Liệu Tham Khảo
Link source code github : https://github.com/buihien0109/springboot-course/tree/main/demo-mutilple-database
Tài Liệu Tham Khảo
Lưu ý: Trong ví dụ này, mình đã sử dụng các giá trị cụ thể cho tên người dùng, mật khẩu và các thông số kết nối cơ sở dữ liệu. Bạn nên thay đổi chúng để phù hợp với môi trường của bạn.
Bình luận
Bài viết hay quá