CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.
Bài viết blog CFSDN này nói về phát triển cơ sở dữ liệu Spring, được tác giả sưu tầm và biên soạn. Nếu bạn quan tâm tới bài viết này thì nhớ like nhé.
- 1. Mùa xuân JDBC
- Cấu hình JDBC mùa xuân
- 2. Các phương thức phổ biến của Spring JdbcTemplate
- Tóm tắt
GitHub:https://github.com/nateshao/ssm/tree/master/104-spring-jdbc 。
1. Mùa xuân JDBC
Mô-đun Spring JDBC làm gì?
Mô-đun JDBC của Spring chịu trách nhiệm quản lý tài nguyên cơ sở dữ liệu và xử lý lỗi, giúp đơn giản hóa đáng kể các hoạt động của nhà phát triển trên cơ sở dữ liệu, cho phép các nhà phát triển thoát khỏi các hoạt động cơ sở dữ liệu tẻ nhạt và dành nhiều năng lượng hơn để viết logic nghiệp vụ.
Phân tích cú pháp Spring JdbcTemplate.
Đối với các hoạt động cơ sở dữ liệu, khung công tác Spring cung cấp lớp JdbcTemplate, lớp này là nền tảng của lớp trừu tượng hóa dữ liệu của khung công tác Spring. Có thể nói lớp JdbcTemplate là lớp cốt lõi của Spring JDBC.
Cấu trúc kế thừa của lớp JdbcTemplate như sau:
Như có thể thấy từ sơ đồ kế thừa của JdbcTemplate, lớp cha trực tiếp của lớp JdbcTemplate là JdbcAccessor, nó cung cấp cho các lớp con một số thuộc tính công khai được sử dụng khi truy cập cơ sở dữ liệu.
DataSource: Chức năng chính của nó là có được kết nối cơ sở dữ liệu. Nó cũng có thể hỗ trợ vùng đệm và các giao dịch phân tán của các kết nối cơ sở dữ liệu.
SQLExceptionTranslator: Giao diện này chịu trách nhiệm dịch SQLException. Việc lấy các phương thức trong SQLExceptionTranslator thông qua các cài đặt cần thiết cho phép JdbcTemplate ủy thác lớp triển khai của SQLExceptionTranslator để hoàn thành công việc dịch thuật có liên quan khi nó cần xử lý SQLException.
Giao diện JdbcOperations xác định tập hợp các thao tác có thể được sử dụng trong lớp JdbcTemplate, bao gồm các thao tác như thêm, sửa đổi, truy vấn và xóa.
Cấu hình JDBC mùa xuân
Mô-đun Spring JDBC chủ yếu bao gồm bốn gói, đó là core (gói lõi), dataSource (gói nguồn dữ liệu), object (gói đối tượng) và support (gói hỗ trợ).
Như có thể thấy từ bảng trên, các hoạt động của Spring trên cơ sở dữ liệu được gói gọn trong các gói này và nếu muốn sử dụng Spring JDBC, bạn cần phải cấu hình nó.
-
"1.0"mã hóa="UTF-8"?>
-
<>
"http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/sơ đồ/đậu
- http://www.springframework.org/sơ đồ/beans/spring-beans-4.3.xsd">
-
--1Cấu hình nguồn dữ liệu-->
-
<>
"nguồn dữ liệu"
lớp=
- "org.springframework.jdbc.datasource.DriverManagerDataSource">
-
--Trình điều khiển cơ sở dữ liệu-->
-
<>
tên
="TênLớpDriver"giá trị="com.mysql.jdbc.Driver"/>
-
--URL để kết nối với cơ sở dữ liệu-->
-
<>
tên
="url"giá trị="jdbc:mysql://localhost:3306/spring"/>
-
--Tên người dùng để kết nối với cơ sở dữ liệu -->
-
<>
tên
="tên người dùng"giá trị="gốc"/>
-
--Mật khẩu để kết nối với cơ sở dữ liệu -->
-
<>
tên
="mật khẩu"giá trị="123456"/>
-
-
--2Định cấu hình mẫu JDBC-->
-
<>
"Mẫu jdbc"
- lớp="org.springframework.jdbc.core.JdbcTemplate">
-
--Nguồn dữ liệu phải được sử dụng theo mặc định -->
-
<>
tên
="nguồn dữ liệu"tham khảo="nguồn dữ liệu"/>
-
-
-
--Xác định Bean có id là accountDao-->
-
<>
"tài khoảnDao"
lớp="com.nateshao.jdbc.AccountDaoImpl">
-
--Tiêm jdbcTemplate vào phiên bản accountDao -->
-
<>
tên
="Mẫu jdbc"tham khảo="Mẫu jdbc"/>
-
-
-
Mô tả về bốn thuộc tính trong cấu hình dataSource ví dụ trên được hiển thị trong bảng sau:
Lưu ý: Các giá trị thuộc tính trong bảng trên cần được cấu hình phù hợp theo loại cơ sở dữ liệu và cài đặt trong quá trình cấu hình thực tế.
2. Các phương thức phổ biến của Spring JdbcTemplate
"Trong lớp lõi JdbcTemplate, một số lượng lớn các phương thức cập nhật và truy vấn cơ sở dữ liệu được cung cấp. Chúng tôi sử dụng các phương thức này để vận hành cơ sở dữ liệu.
exec(): Phương thức exec(String sql) có thể được sử dụng để thực thi các câu lệnh sql update(): update()) được sử dụng để thực hiện các thao tác chèn, cập nhật và xóa query(): query() được sử dụng để thực hiện các thao tác truy vấn dữ liệu .
thực hiện()
Các bước triển khai để sử dụng phương thức exec(String sql) để tạo bảng như sau:
- Tạo cơ sở dữ liệu có tên mùa xuân trong MySQL;
- Tạo một dự án web và nhập các gói maven có liên quan;
- Tạo các tệp cấu hình Spring, định cấu hình nguồn dữ liệu và các mẫu JDBC;
- Tạo lớp kiểm tra,
- Thủ tục kiểm tra.
Spring.sql 。
- TẠO NÊNCƠ SỞ DỮ LIỆUNẾU NHƯKHÔNGTỒN TẠI`mùa xuân`;
-
- SỬ DỤNG `spring`;
-
- /*Bànkết cấuvìbàn`tài khoản`*/
-
- LÀM RƠIBÀN`Tài khoản` IFEXISTS;
-
- TẠO NÊNBÀN`tài khoản`(
- `mã số`số nguyên(11)KHÔNGVÔ GIÁ TRỊTỰ ĐỘNG TĂNG,
- `tên người dùng`varchar(50)MẶC ĐỊNHVÔ GIÁ TRỊ,
- `cân bằng`gấp đôiMẶC ĐỊNHVÔ GIÁ TRỊ,
- SƠ ĐẲNGCHÌA KHÓA(`mã`)
- )ENGINE=InnoDBAUTO_INCREMENT=6MẶC ĐỊNHBỘ KÝ TỰ=utf8;
-
- /*Dữ liệuvìcáibàn`tài khoản`*/
-
- chènvào trong`tài khoản`(`id`,`tên người dùng`,`số dư`)giá trị(2,'shaotongjie',2222),(3,'1',2222),(4,'Một',2022),(5,'b',2322);
Tài khoản.java 。
- packagecom.nateshao.jdbc;
-
- /**
- *@ngàyTạoquaThiệu Thông KiệtTRÊN2021/10/1515:50
- *@WeChat lập trình viên tài khoản công cộng Qianyu
- *@Trang web cá nhân www.nateshao.cn
- *@Blog https://nateshao.gitee.io
- *@GitHubhttps://github.com/nateshao
- *@Giteehttps://gitee.com/nateshao
- *Sự miêu tả:
- */
- @Dữ liệu
- công cộnglớpTài khoản{
- riêng tưSố nguyênid;//id tài khoản
- PrivateStringusername;//tên người dùng
- riêng tưGấp đôisố dư;//số dư tài khoản
- }
ứng dụngContext.xml 。
-
"1.0"mã hóa="UTF-8"?>
-
<>
"http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/sơ đồ/đậu
- http://www.springframework.org/sơ đồ/beans/spring-beans-4.3.xsd">
-
--1Cấu hình nguồn dữ liệu-->
-
<>
"nguồn dữ liệu"
lớp=
- "org.springframework.jdbc.datasource.DriverManagerDataSource">
-
--Trình điều khiển cơ sở dữ liệu-->
-
<>
tên
="TênLớpDriver"giá trị="com.mysql.jdbc.Driver"/>
-
--URL để kết nối với cơ sở dữ liệu-->
-
<>
tên
="url"giá trị="jdbc:mysql://localhost:3306/spring?useSSL=false"/>
-
--Tên người dùng để kết nối với cơ sở dữ liệu -->
-
<>
tên
="tên người dùng"giá trị="gốc"/>
-
--Mật khẩu để kết nối với cơ sở dữ liệu -->
-
<>
tên
="mật khẩu"giá trị="123456"/>
-
-
--2Định cấu hình mẫu JDBC-->
-
<>
"Mẫu jdbc"
- lớp="org.springframework.jdbc.core.JdbcTemplate">
-
--Nguồn dữ liệu phải được sử dụng theo mặc định -->
-
<>
tên
="nguồn dữ liệu"tham khảo="nguồn dữ liệu"/>
-
-
-
--Xác định Bean có id là accountDao-->
-
<>
"tài khoảnDao"
lớp="com.nateshao.jdbc.AccountDaoImpl">
-
--Tiêm jdbcTemplate vào phiên bản accountDao -->
-
<>
tên
="Mẫu jdbc"tham khảo="Mẫu jdbc"/>
-
-
-
AccountDao.java 。
- packagecom.nateshao.jdbc;
-
- importjava.util.List;
-
- /**
- *@ngàyTạoquaThiệu Thông KiệtTRÊN2021/10/1515:50
- *@WeChat lập trình viên tài khoản công cộng Qianyu
- *@Trang web cá nhân www.nateshao.cn
- *@Blog https://nateshao.gitee.io
- *@GitHubhttps://github.com/nateshao
- *@Giteehttps://gitee.com/nateshao
- *Sự miêu tả:
- */
- công cộnggiao diệnTài khoảnDao{
- // Thêm vào
- công cộngsố nguyênaddAccount(Tài khoảntài khoản);
-
- // gia hạn
- công cộngsố nguyênupdateAccount(Tài khoảntài khoản);
-
- //xóa bỏ
- công cộngsố nguyênxóaTài khoản(số nguyênnhận dạng);
-
- //Truy vấn theo id
- công cộngsố nguyêntruy vấnTài khoảnTheoId(số nguyênnhận dạng);
- //Truy vấn tất cả các tài khoản
- công cộngLiệt kê findAllAccount();
-
- Tài khoảntìm kiếmTài khoảnTheoId(số nguyênTôi);
- }
AccountDaoImpl.java 。
- packagecom.nateshao.jdbc;
-
- importorg.springframework.jdbc.core.BeanPropertyRowMapper;
- importorg.springframework.jdbc.core.JdbcTemplate;
- importorg.springframework.jdbc.core.RowMapper;
- importjava.util.List;
-
- /**
- *@ngàyTạoquaThiệu Thông KiệtTRÊN2021/10/1515:55
- *@WeChat lập trình viên tài khoản công cộng Qianyu
- *@Trang web cá nhân www.nateshao.cn
- *@Blog https://nateshao.gitee.io
- *@GitHubhttps://github.com/nateshao
- *@Giteehttps://gitee.com/nateshao
- *Sự miêu tả:
- */
- công cộngclassAccountDaoImplimplementsAccountDao{
- //Khai báo các thuộc tính JdbcTemplate và các phương thức setter của chúng
- Bản mẫu Jdbc riêng tư
-
- công cộngvoidsetJdbcTemplate(JdbcTemplatejdbcTemplate){
- jdbcTemplate=jdbcTemplate;
- }
-
- /**
- *Thêm tài khoản
- *@paramaccount
- *@trở lại
- */
- công cộngsố nguyênaddAccount(Tài khoảntài khoản){
- //Định nghĩa SQL
- Chuỗi SQL="insertintoaccount(tên người dùng,số dư)giá trị(?,?)";
- //Định nghĩa một mảng để lưu trữ tham số trong câu lệnh SQL
- Đối tượng[]obj=đối tượng mới[]{
- tài khoản.getUsername(),
- tài khoản.getBalance()
- };
- //Thực hiện thao tác thêm và trả về số lượng bản ghi bị ảnh hưởng bởi câu lệnh SQL
- số nguyênnum=this.jdbcTemplate.cập nhật(sql, đối tượng);
- trở lạisố;
- }
-
- /**
- *Cập nhật tài khoản
- *@paramaccount
- *@trở lại
- */
- công cộngsố nguyênupdateAccount(Tài khoảntài khoản){
- //Định nghĩa SQL
- Chuỗi SQL="cập nhật tài khoản, đặt tên người dùng =?, số dư =? id ở đâu =?";
- //Định nghĩa một mảng để lưu trữ tham số trong câu lệnh SQL
- Đối tượng[]tham số=đối tượng mới[]{
- tài khoản.getUsername(),
- tài khoản.getBalance(),
- tài khoản.getId()
- };
- //Thực hiện thao tác thêm và trả về số lượng bản ghi bị ảnh hưởng bởi câu lệnh SQL
- số nguyênnum=this.jdbcTemplate.cập nhật(sql, tham số);
- trở lạisố;
- }
-
- /**
- *Xóa tài khoản
- *@paramid
- *@trở lại
- */
- công cộngsố nguyênxóaTài khoản(số nguyênnhận dạng){
- //Định nghĩa SQL
- Chuỗi SQL="xóa khỏi tài khoản nơi id =?";
- //Thực hiện thao tác thêm và trả về số lượng bản ghi bị ảnh hưởng bởi câu lệnh SQL
- số nguyênnum=this.jdbcTemplate.cập nhật(sql, id);
- trở lạisố;
- }
-
- @Ghi đè
- công cộngsố nguyêntruy vấnTài khoảnTheoId(số nguyênnhận dạng){
- trở lại0;
- }
-
- /**
- *Truy vấn thông tin dữ liệu tài khoản theo ID
- *@paramid
- *@trở lại
- */
- công cộngTài khoảntìm kiếmTài khoảnTheoId(số nguyênnhận dạng){
- //Định nghĩa câu lệnh SQL
- Chuỗi SQL="chọn*từtàikhoảnnơiid=?";
- //Tạo một đối tượng BeanPropertyRowMapper mới
- RowMapper rowMapper=
- newBeanPropertyRowMapper (Lớp tài khoản);
- // Liên kết id với câu lệnh SQL và trả về một bản ghi hàng đơn loại Object thông qua RowMapper
- trở lạithis.jdbcTemplate.queryForObject(sql,rowMapper,id);
- }
-
- /**
- *Truy vấn mọi thông tin tài khoản
- *@trở lại
- */
- công cộngLiệt kê findAllAccount(){
- //Định nghĩa câu lệnh SQL
- Chuỗi SQL="chọn*từtài khoản";
- //Tạo một đối tượng BeanPropertyRowMapper mới
- RowMapper rowMapper=
- newBeanPropertyRowMapper (Lớp tài khoản);
- //Thực thi truy vấn SQL tĩnh và trả về kết quả thông qua RowMapper
- trở lạithis.jdbcTemplate.query(sql,rowMapper);
- }
-
- }
Lớp kiểm tra JdbcTemplateTest.java.
- packagecom.nateshao.jdbc;
-
- importorg.junit.jupiter.api.Test;
- importorg.springframework.context.ApplicationContext;
- importorg.springframework.context.support.ClassPathXmlApplicationContext;
- importorg.springframework.jdbc.core.JdbcTemplate;
- importjava.util.List;
-
- /**
- *@ngàyTạoquaThiệu Thông KiệtTRÊN2021/10/1515:57
- *@WeChat lập trình viên tài khoản công cộng Qianyu
- *@Trang web cá nhân www.nateshao.cn
- *@Blog https://nateshao.gitee.io
- *@GitHubhttps://github.com/nateshao
- *@Giteehttps://gitee.com/nateshao
- *Sự miêu tả:
- */
- công cộnglớpJdbcTemplateTest{
- /**
- *sử dụngthực hiện() phương thức tạo bảng
- */
- //công cộngtĩnhvoidmain(Chuỗi[]đối số){
- ////Tải file cấu hình
- //Bối cảnh ứng dụngBối cảnh ứng dụng=
- //newClassPathXmlApplicationContext("applicationContext.xml");
- ////Lấy phiên bản JdbcTemplate
- //Mẫu JdbcjdTemplate=
- //(JdbcTemplate)applicationContext.getBean("Mẫu jdbc");
- ////sử dụngthực hiện() phương thức thực thi các câu lệnh SQL và tạo tài khoản bảng quản lý tài khoản người dùng
- //Mẫu jd.thực hiện("createtableaccount("+
- //"idintprimarykeyauto_increment,"+
- //"tên người dùng varchar(50)"+
- //"cân bằng gấp đôi)");
- //Hệ thống.ngoài.println("Tài khoản bảng tài khoản đã được tạo thành công!");
- //
- @Bài kiểm tra
- công cộngvoidmainTest() {
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản JdbcTemplate
- Mẫu Jdbc
- (JdbcTemplate)applicationContext.getBean("Mẫu jdbc");
- //sử dụngthực hiện() phương thức thực thi các câu lệnh SQL và tạo tài khoản bảng quản lý tài khoản người dùng
- Mẫu jd.thực hiện("createtableaccount("+
- "idintprimarykeyauto_increment,"+
- "tên người dùng varchar(50)"+
- "cân bằng gấp đôi)");
- Hệ thống.ngoài.println("Tài khoản bảng tài khoản đã được tạo thành công!");
- }
-
- @Bài kiểm tra
- công cộngvoidaddAccountTest(){
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản AccountDao
- Tài khoảnDaotài khoảnDao=
- (Tài khoảnDao)applicationContext.getBean("tài khoảnDao");
- //Tạo đối tượng Account và thêm dữ liệu vào đối tượng Account
- Tài khoảnaccount=tài khoản mới();
- tài khoản.setTên người dùng("Qianyu");
- tài khoản.setBalance(1000,00);
- //Thực thi phương thức addAccount() và nhận kết quả trả về
- số nguyênnum=accountDao.addAccount(tài khoản);
- nếu(số>0){
- Hệ thống.ngoài.println("Đã chèn thành công"+số+"Dữ liệu!");
- }khác{
- Hệ thống.ngoài.println("Thao tác chèn không thành công!");
- }
- }
-
- @Bài kiểm tra
- công cộngvoidupdateKiểm tra tài khoản()
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản AccountDao
- Tài khoảnDaotài khoảnDao=
- (Tài khoảnDao)applicationContext.getBean("tài khoảnDao");
- //Tạo đối tượng Account và thêm dữ liệu vào đối tượng Account
- Tài khoảnaccount=tài khoản mới();
- tài khoản.setId(1);
- tài khoản.setTên người dùng("tom");
- tài khoản.setBalance(2000.00);
- //Thực thi phương thức updateAccount() và nhận kết quả trả về
- số nguyênnum=accountDao.updateAccount(tài khoản);
- nếu(số>0){
- Hệ thống.ngoài.println("Đã sửa đổi thành công"+số+"Dữ liệu!");
- }khác{
- Hệ thống.ngoài.println("Hoạt động sửa đổi thất bại!");
- }
- }
-
- @Bài kiểm tra
- công cộngvoiddeleteTài khoảnKiểm tra(){
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản AccountDao
- Tài khoảnDaotài khoảnDao=
- (Tài khoảnDao)applicationContext.getBean("tài khoảnDao");
- //Thực thi phương thức deleteAccount() và nhận kết quả trả về
- số nguyênnum=accountDao.deleteAccount(1);
- nếu(số>0){
- Hệ thống.ngoài.println("Xóa thành công"+số+"Dữ liệu!");
- }khác{
- Hệ thống.ngoài.println("Thao tác xóa không thành công!");
- }
- }
-
- @Bài kiểm tra
- công cộngvoidfindTài khoảnTheoIdKiểm tra(){
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản AccountDao
- Tài khoảnDaotài khoảnDao=
- (Tài khoảnDao)applicationContext.getBean("tài khoảnDao");
- //Thực thi phương thức findAccountById()
- Tài khoảnaccount=accountDao.findAccountById(1);
- Hệ thống.ngoài.println(tài khoản);
- }
-
- @Bài kiểm tra
- công cộngvoidfindAllAccountTest() {
- //Tải tập tin cấu hình
- ApplicationContextapplicationContext=
- newClassPathXmlApplicationContext("applicationContext.xml");
- // Lấy phiên bản AccountDao
- Tài khoảnDaotài khoảnDao=
- (Tài khoảnDao)applicationContext.getBean("tài khoảnDao");
- //Thực thi phương thức findAllAccount() để lấy tập hợp các đối tượng Account
- Liệt kê tài khoản=accountDao.findAllAccount();
- //Lặp qua các đối tượng trong bộ sưu tập
- vì(Tài khoản:tài khoản){
- Hệ thống.ngoài.println(hành động);
- }
- }
- }
Tìm hiểu thêm một thủ thuật: sử dụng thử nghiệm đơn vị JUnit.
Sau khi quá trình phát triển giao diện hoàn tất, thông thường cần phải viết một bài kiểm tra đơn vị hoặc sử dụng PostMan để kiểm tra hoặc kết nối dự án front-end và gỡ lỗi với nhau.
Trong quá trình phát triển, công việc thử nghiệm tương ứng là bắt buộc. Theo các mục đích kiểm thử khác nhau, kiểm thử phần mềm có thể được chia thành kiểm thử đơn vị, kiểm thử tích hợp, kiểm thử xác nhận và kiểm thử hệ thống. Trong số đó, kiểm thử đơn vị là kiểm thử cấp độ thấp nhất trong giai đoạn phát triển phần mềm, dễ dàng tìm ra và giải quyết vấn đề kịp thời. JUnit là một khung mã nguồn mở để thử nghiệm đơn vị Dưới đây là một ví dụ để tìm hiểu cách sử dụng khung thử nghiệm đơn vị JUnit4.
cập nhật() .
Phương thức update() có thể hoàn thành các thao tác chèn, cập nhật và xóa dữ liệu. Trong lớp JdbcTemplate, một loạt các phương thức update() được cung cấp. Các phương thức thường được sử dụng như trong bảng sau:
truy vấn() 。
"Lớp JdbcTemplate cũng cung cấp một số lượng lớn các phương thức query() để xử lý các hoạt động truy vấn khác nhau trên các bảng cơ sở dữ liệu. Trong số đó, một số phương thức query() thường được sử dụng được hiển thị trong bảng sau:
Tóm tắt
Bài viết này chủ yếu giải thích chi tiết các kiến thức sử dụng JDBC cho các thao tác dữ liệu trong Spring framework.
Đầu tiên, nó giải thích các lớp cốt lõi trong Spring JDBC và cách cấu hình JDBC trong Spring.
Sau đó việc sử dụng các phương thức phổ biến trong lớp lõi JdbcTemplate của Spring JDBC sẽ được giải thích thông qua các trường hợp.
Khi nghiên cứu bài viết này, bạn có thể tìm hiểu cách sử dụng Spring framework để phát triển cơ sở dữ liệu và đánh giá sâu sắc sức mạnh của Spring framework.
Liên kết gốc: https://mp.weixin.qq.com/s/BvOzzcc2L9PUb4oXl4mxkw.
Cuối cùng, bài viết về trò chuyện về phát triển cơ sở dữ liệu Spring này kết thúc tại đây. Nếu bạn muốn biết thêm về trò chuyện về phát triển cơ sở dữ liệu Spring, vui lòng tìm kiếm các bài viết về CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!