Để mở rộng ứng dụng hội nghị của mình, chúng ta cần tạo lại ứng dụng đó từ Phần 1. Bạn có thể
làm theo các hướng dẫn trước hoặc sử dụng lệnh script (tạo kịch bản lệnh) của Roo. Lệnh
script thực hiện tất cả các lệnh đã quy định trong một tệp tài nguyên. Nếu bạn đã làm theo
Phần 1, bạn đã nhận thấy rằng Roo đã tạo ra một tệp tên là log.roo, có tất cả các lệnh thực hiện
trên trình vỏ Roo. Chúng ta sẽ thực hiện tệp log.roo đó và tạo lại ứng dụng này.
12 trang |
Chia sẻ: lylyngoc | Lượt xem: 1599 | Lượt tải: 1
Bạn đang xem nội dung tài liệu Giới thiệu Spring Roo, Phần 2: Phát triển một ứng dụng bằng Spring Roo, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Giới thiệu Spring Roo, Phần 2: Phát triển một ứng
dụng bằng Spring Roo
Để mở rộng ứng dụng hội nghị của mình, chúng ta cần tạo lại ứng dụng đó từ Phần 1. Bạn có thể
làm theo các hướng dẫn trước hoặc sử dụng lệnh script (tạo kịch bản lệnh) của Roo. Lệnh
script thực hiện tất cả các lệnh đã quy định trong một tệp tài nguyên. Nếu bạn đã làm theo
Phần 1, bạn đã nhận thấy rằng Roo đã tạo ra một tệp tên là log.roo, có tất cả các lệnh thực hiện
trên trình vỏ Roo. Chúng ta sẽ thực hiện tệp log.roo đó và tạo lại ứng dụng này.
1. Tệp này được bao gồm trong mã mẫu. Bạn có thể đổi tên nó là conference.roo.
2. Tạo một thư mục mới có tên là conference và sao chép conference.roo vào thư mục đó.
3. Mở trình vỏ dòng lệnh của hệ điều hành của bạn.
4. Chuyển đến thư mục conference mà bạn vừa tạo ra.
5. Thực hiện lệnh script --file conference.roo.
Lệnh script sẽ tạo lại ứng dụng trong một vài giây nếu bạn có các JAR cần thiết trong kho lưu
trữ Maven của mình. Nếu không, sẽ mất nhiều thời gian hơn vì nó phải tải về tất cả các JAR.
Lệnh script rất có ích theo cách bạn có thể sử dụng nó như một khuôn mẫu để tạo ra các dự án
do Spring quản lý.
Trước khi chúng ta tiến lên, hãy nhập khẩu dự án Maven bằng STS. STS có đóng gói sẵn với
trình cắm thêm Eclipse Maven. Bạn nên nhập khẩu dự án này bằng cách chọn File > Import >
Maven > Existing Maven Projects (Các dự án Maven hiện có), sau đó chọn thư mục của dự án.
Chúng ta sẽ nhập khẩu dự án này bằng STS khi chúng ta sẽ viết một số mã tùy chỉnh sau.
Ứng dụng web mà chúng ta đã tạo ra cho đến nay vẫn hoạt động và chúng ta có thể kiểm tra nó
bằng thủ công nhờ tạo, đọc, cập nhật và xóa các thực thể Speaker (Người nói) và Talk (Cuộc
thảo luận). Nhưng nó sẽ không còn thú vị nữa phải không nếu chúng ta đã có thể tự động hoá
quá trình này?
Về đầu trang
Kiểm tra web được tự động hóa
Ở đây có kèm tính năng tiếp theo của Spring Roo là: hỗ trợ kiểm tra Selen. Selen là một tập các
công cụ rất mạnh hỗ trợ sự phát triển nhanh về tự động hóa kiểm tra cho các ứng dụng dựa trên
web. Để bổ sung hỗ trợ kiểm tra Selen vào ứng dụng của bạn, hãy thực hiện các lệnh sau:
selenium test --controller ~.web.SpeakerController
selenium test --controller ~.web.TalkController
Lệnh selenium test sẽ tạo ra bài kiểm tra Selen cho các bộ điều khiển Speaker và Talk. Lệnh
này có một thuộc tính bắt buộc tên là controller (bộ điều khiển) để chỉ rõ tên của bộ điều khiển
để tạo ra bài kiểm tra Selen. Lệnh này cũng có hai thuộc tính tuỳ chọn tên là name và serverUrl
để chỉ rõ tên của bài kiểm tra Selen và máy chủ nơi ứng dụng web có sẵn. Spring Roo cũng sẽ bổ
sung trình cắm thêm Selenium Maven khi bạn thực hiện lệnh selenium test.
Ở trên, chúng ta đã tạo ra các trường hợp kiểm tra Selen cho bộ điều khiển của mình, nhưng
trước khi chạy chúng, chúng ta cần phải sửa chữa một lỗi nhỏ trong bộ kiểm tra Selen do Spring
Roo tạo ra. Chúng ta đã thêm một ràng buộc trong thực thể Speaker của mình là tuổi nên ở giữa
25 và 60, nhưng bộ kiểm tra này không lưu tâm đến ràng buộc đó. Nó đã sử dụng một giá trị tuổi
là 1, do đó, việc kiểm tra sẽ thất bại. Chúng ta cần sửa đổi một tệp có tên là test-speaker.xhtml và
cập nhật tệp này như trong Liệt kê 1.
Liệt kê 1. Sửa đổi tệp test-speaker.xhtml
type
_age_id
1
thành
type
_age_id
26
Lỗi này sẽ được sửa chữa trong một bản phát hành sau này của Spring Roo.
Để chạy các trường hợp kiểm tra Selen, chúng ta cần khởi động máy chủ Tomcat. Bạn có thể
khởi động nó bằng cách sử dụng lệnh Maven là mvn tomcat:run. Theo mặc định, tất cả các ứng
dụng web được tạo ra bằng cách sử dụng Roo đều có các trình cắm thêm Maven cho các máy
chủ web Tomcat và Jetty. Để chạy selenium test, hãy thực hiện lệnh Maven mvn
selenium:selenese.
Lệnh này sẽ khởi động một trình duyệt Firefox để chạy các trường hợp kiểm tra Selen. Trong
quá trình thực hiện các bài kiểm tra này, bạn sẽ thấy một hình ảnh tương tự như Hình 1.
Hình 1. Các bài kiểm tra Selen
Hiện nay, bất cứ ai cũng có thể truy cập ứng dụng của chúng ta và thực hiện tạo, cập nhật và xóa
Speaker và Talk. Trong một ứng dụng thời gian thực, có vấn đề bảo mật đối với những người có
thể thực hiện hoạt động như vậy.
Về đầu trang
Bảo mật ứng dụng web
Roo sử dụng Spring Security (Bảo mật Spring) để bổ sung bảo mật vào ứng dụng của bạn trong
một dòng. Spring Security là một xác thực tùy chỉnh rất cao và mạnh mẽ và là một khung công
tác kiểm soát truy cập. Nó là tiêu chuẩn trên thực tế để bảo mật các ứng dụng dựa trên Spring.
Bổ sung Spring Security
Để thêm Spring Security, hãy gõ lệnh sau: security setup (thiết lập bảo mật).
Lệnh này sẽ thêm tất cả các tệp JAR của Spring Security cần thiết và sẽ thiết lập bảo mật cơ bản
cho ứng dụng của bạn. Lệnh này cũng tạo ra các tệp khác, nhưng có một tệp quan trọng là tệp
applicationContext security.xml, có tất cả các định nghĩa bean liên quan đến bảo mật. Ngữ cảnh
của tệp applicationContext-security.xml trông giống như nội dung trong Liệt kê 2. Tôi đã thay
thế mật khẩu được băm nhỏ với các dấu chấm chấm để làm cho nó dễ đọc hơn.
Liệt kê 2. Ngữ cảnh của applicationContext-security.xml
<beans:beans xmlns=""
xmlns:beans=""
xmlns:xsi=""
xsi:schemaLocation=" \
\
">
<form-login login-processing-url="/resources/j_spring_security_check"
\
login-page="/login" authentication-failure-url="/login?login_error=t"/>
<!-- SHA-256 values can be produced using \
'echo -n your_desired_password | sha256sum' \
(using normal *nix environments) -->
<user name="admin" password="..."
authorities="ROLE_ADMIN"/>
<user name="user" password="..."
authorities="ROLE_USER"/>
Bảo mật được Roo cấu hình là tổng quát và không có tài liệu tham khảo nào cho ứng dụng của
chúng ta. Hãy nhớ rằng Roo trợ giúp về thiết lập hoặc cấu hình một ứng dụng để khởi đầu nhanh
chóng, nhưng trách nhiệm của nhà phát triển là tùy chỉnh sản phẩm cuối cùng. Trong trường hợp
này, Roo đã chỉ cung cấp một khuôn mẫu cho Spring Security và trách nhiệm của chúng ta là tùy
chỉnh nó theo nhu cầu của mình.
Tùy chỉnh Spring Security
Trong ứng dụng của chúng ta, bất kỳ ai cũng có thể tạo ra một Speaker, nhưng chỉ có một
Speaker có thể tạo ra một Talk. Chúng ta cần sửa đổi tệp applicationContext-security.xml như
dưới đây. Liệt kê 3 chỉ cho thấy một phần của XML cần sửa đổi.
Liệt kê 3. Sửa đổi tệp applicationContext-security.xml
<form-login login-processing-url="/resources/j_spring_security_check"
\
login-page="/login" authentication-failure-url="/login?login_error=t"/>
Tôi đã cập nhật intercept-url sao cho chỉ những người dùng có vai trò người dùng mới có thể
tạo ra một Talk và tất cả người dùng được phép tự đăng ký là Speaker.
Spring Security do Roo-tạo ra đã hiển thị ở trên sử dụng một trình cung cấp xác thực trong bộ
nhớ được cấu hình trong thẻ . Kể từ khi ứng dụng của chúng ta quản lý các thực
thể Speaker, chúng ta nên xây dựng một trình cung cấp xác thực tùy chỉnh, sử dụng dữ liệu
Speaker. Để xác thực, chúng ta sẽ sử dụng email Speaker làm tên người dùng và thêm một
trường mật khẩu cho thực thể Speaker, mà chúng ta sẽ sử dụng làm một mật khẩu xác thực.
Một lần nữa, tôi sử dụng trình vỏ Roo để thêm trường password (mật khẩu) cho thực thể
Speaker:
field string --class ~.domain.Speaker --fieldName password --notNull
--sizeMin 6 –sizeMax 10
Tôi cũng đã thêm ràng buộc là mật khẩu nên không rỗng và mật khẩu phải có chiều dài từ 6 đến
10 ký tự.
Do chúng ta đang sử dụng email và mật khẩu làm các tham số xác thực, chúng ta muốn tìm một
Speaker với một email và mật khẩu cụ thể. Spring Roo cung cấp một phương tiện để tạo ra các
finder (bộ dò tìm) cho các ứng dụng của bạn khi sử dụng lệnh finder add (thêm bộ dò tìm):
finder add --finderName findSpeakersByEmailAndPasswordEquals --class
~.domain.Speaker
Bạn có thể tìm thấy tất cả các bộ dò tìm cho một thực thể bằng cách sử dụng lệnh finder list
(liệt kê bộ dò tìm). Lệnh finder add (thêm bộ dò tìm) viết mã bộ dò tìm trong tệp
Speaker_Roo_Finder.aj và viết một số tệp có liên quan đến khung nhìn. Điều này cho phép bạn
tìm kiếm những người nói-Speaker từ giao diện đồ họa (GUI).
Viết AuthenticationProvider tùy chỉnh
Chúng ta sẽ viết một trình cung cấp xác thực (Authentication provider) tùy chỉnh bằng cách mở
rộng một lớp tên là AbstractUserDetailsAuthenticationProvider, làm việc với tên người
dùng/mật khẩu giống như xác thực. Các lớp mở rộng
AbstractUserDetailsAuthenticationProvider phải cung cấp công cụ cho hai phương thức
trừu tượng của nó: additionalAuthenticationChecks và retrieveUser. Trình cung cấp gọi
phương thức retrieveUser để xác thực Speaker bằng cách sử dụng email và mật khẩu đã nhập
vào. Việc tra cứu cơ sở dữ liệu cho Speaker được thực hiện khi sử dụng bộ dò tìm do chúng ta đã
tạo ra ở trên. Nếu tìm thấy Speaker, thì GrantedAuthority ROLE_USER sẽ được gán cho
Speaker đó. Phương thức này cuối cùng trả về một đối tượng UserDetails đã điền vào nếu đăng
nhập thành công hay nếu không sẽ đưa ra một BadCredentialsException với thông báo phù
hợp (xem Liệt kê 4).
Liệt kê 4. Xác thực tuỳ chỉnh
package com.dw.roo.conference.security;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityNotFoundException;
import javax.persistence.NonUniqueResultException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.security.authentication.BadCredentialsException;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationTok
en;
import org.springframework.security.authentication.\
dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import com.dw.roo.conference.domain.Speaker;
public class ConferenceAuthenticationProvider extends \
AbstractUserDetailsAuthenticationProvider {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, \
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
// TODO Auto-generated method stub
}
@Override
protected UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken \
authentication) throws AuthenticationException {
String password = (String) authentication.getCredentials();
if (!StringUtils.hasText(password)) {
throw new BadCredentialsException("Please enter password");
}
List authorities = new
ArrayList();
try {
Speaker speaker =
Speaker.findSpeakersByEmailAndPasswordEquals(username, \
password).getSingleResult();
authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
} catch (EmptyResultDataAccessException e) {
throw new BadCredentialsException("Invalid username or
password");
} catch (EntityNotFoundException e) {
throw new BadCredentialsException("Invalid user");
} catch (NonUniqueResultException e) {
throw new BadCredentialsException("Non-unique user, contact
administrator");
}
return new User(username, password, true, // enabled
true, // account not expired
true, // credentials not expired
true, // account not locked
authorities);
}
}
Trong tệp applicationContext-security.xml, chúng ta phải định nghĩa bean
conferenceAuthenticationProvider (trình cung cấp xác thực hội nghị) và thay thế trình cung
cấp xác thực trong bộ nhớ do Roo tạo ra bằng conferenceAuthenticationProvider của chúng
ta như trong Liệt kê 5.
Liệt kê 5. conferenceAuthenticationProvider
<beans:bean name="conferenceAuthenticationProvider"
class="com.dw.roo.conference.security.ConferenceAuthenticationProvider">
Bây giờ nếu bạn khởi động máy chủ và cố gắng tạo ra một Talk, một màn hình đăng nhập sẽ mở
ra trước bạn, ở đó bạn phải nhập email và mật khẩu của Speaker mà bạn đã tạo ra. Mục đích của
việc xây dựng trình cung cấp xác thực tùy chỉnh là không phải để xây dựng một trình cung cấp
xác thực lý tưởng mà để cho bạn thấy những gì Roo làm và những gì bạn phải tự làm.
Về đầu trang
Thông báo email
Trong ứng dụng của chúng ta, các Speaker sẽ nhận được một email khi họ tạo ra Talk, vì vậy hãy
thêm sự hỗ trợ email cho ứng dụng của chúng ta. Chúng ta sẽ sử dụng Gmail làm máy chủ
SMTP của mình để tập trung vào việc gửi email khi sử dụng Roo. Việc thêm sự hỗ trợ cho một
ứng dụng được thực hiện bằng lệnh sau:
email sender setup --hostServer smtp.gmail.com --username \
--password --port 587 --protocol
SMTP
Lệnh email sender (người gửi email) cài đặt một JavaMailSender (Người gửi email Java) của
Spring trong dự án của bạn. Bạn có thể thay đổi các đặc tính liên quan đến email trong tệp
email.properties.
Sau khi đã tạo ra Talk, chúng ta cần gửi một email. Để làm việc đó, chúng ta cần thêm một
trường email trong TalkController (Bộ điều khiển cuộc thảo luận). Để thêm một trường email,
hãy gõ:
field email template --class ~.web.TalkController
Lệnh này sẽ thêm một khuôn mẫu MailSender và một phương thức sendMessage (Gửi thông
báo) tới TalkController. Bây giờ chúng ta cần khởi động phương thức sendMessage sau khi
một Talk được lưu giữ lâu bền trong cơ sở dữ liệu. Khi tất cả mã dùng cho TalkController tồn
tại trong tệp TalkController_Roo_Controller.aj, cách dễ nhất để thực hiện nhiệm vụ này là tạo ra
một phương thức encodeUrlPathSegment từ tệp .aj cho lớp TalkController và thêm một cuộc
gọi đến phương thức sendMessage sau dòng talk.persist(), như trong Liệt kê 6.
Liệt kê 6. Tạo ra một phương thức encodeUrlPathSegment từ tệp .aj cho lớp
TalkController
public class TalkController {
@Autowired
private transient MailSender mailTemplate;
public void sendMessage(String mailFrom, String subject, String
mailTo,
String message) {
org.springframework.mail.SimpleMailMessage \
simpleMailMessage = new org.springframework.mail.SimpleMailMessage();
simpleMailMessage.setFrom(mailFrom);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setTo(mailTo);
simpleMailMessage.setText(message);
mailTemplate.send(simpleMailMessage);
}
@RequestMapping(method = RequestMethod.POST)
public String create(@Valid Talk talk, BindingResult result, Model
model,
HttpServletRequest request) {
if (result.hasErrors()) {
model.addAttribute("talk", talk);
return "talks/create";
}
talk.persist();
sendMessage("spring.roo.playground@gmail.com", "Your talk is
created",
talk.getSpeaker().getEmail(), \
"Congrats your talk is created");
return "redirect:/talks/"
+ encodeUrlPathSegment(talk.getId().toString(),
request);
}
private String encodeUrlPathSegment(String pathSegment,
HttpServletRequest request) {
String enc = request.getCharacterEncoding();
if (enc == null) {
enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
}
try {
pathSegment = UriUtils.encodePathSegment(pathSegment,
enc);
} catch (UnsupportedEncodingException uee) {
}
return pathSegment;
}
}
Sau đây, các Speaker sẽ nhận được một email trong tài khoản đã định của mình sau khi Talk
được tạo ra.
Về đầu trang
Hỗ trợ quốc tế
Khi chúng ta đang xây dựng một ứng dụng web dựa trên Internet, điều quan trọng là hỗ trợ các
ngôn ngữ khác nhau sao cho những người dùng từ khu vực địa lý khác nhau có thể sử dụng ứng
dụng của chúng ta. Spring Roo bổ sung sự hỗ trợ quốc tế bằng lệnh web mvc install
language, cài đặt một ngôn ngữ mới trong ứng dụng của bạn. Ví dụ, các lệnh cho ngôn ngữ Tây
Ban Nha và Ý là:
web mvc install language --code es
web mvc install language --code it
Roo hiện hỗ trợ sáu ngôn ngữ và bạn có thể viết một ngôn ngữ bổ sung cho những ngôn ngữ
khác theo sự lựa chọn của bạn. Bây giờ khi chạy ứng dụng này, 2 lá cờ (của Italy và Tây Ban
Nha) được hiển thị, cùng với lá cờ Anh. Nếu bạn nhấn chuột vào bất kỳ lá cờ nào trong các lá cờ
đó, bạn sẽ xem ứng dụng web theo ngôn ngữ tương ứng với lá cờ đó.
Về đầu trang
Xã hội hóa ứng dụng web của bạn
Đây là một kỷ nguyên phương tiện truyền thông xã hội và các tính năng xã hội thường được
thêm vào các ứng dụng hiện tại. Để thêm đoạn video của các Talk thường rất có ý nghĩa. Roo
cung cấp sự hỗ trợ để nhúng đoạn video được tải lên YouTube, Vimeo, Viddler và Google
Video, v.v.. Để nhúng một đoạn video, hãy sử dụng lệnh sau:
web mvc embed video --provider VIMEO --videoId 16069687
Nếu bạn khởi động máy chủ và khởi chạy ứng dụng của mình trong một trình duyệt, bạn sẽ có
thể xem đoạn video đã nhúng nói trên. Tương tự như vậy, bạn có thể thêm vào các đoạn video
YouTube hoặc Viddler.
Roo cũng cung cấp cho bạn một tùy chọn để nhúng các thông báo Twitter, các tài liệu, các ticker,
các bản đồ, các bức ảnh và các luồng video trong ứng dụng của bạn. Các lệnh khác nhau trong
Liệt kê 7.
Liệt kê 7. Các lệnh nhúng
web mvc embed document
web mvc embed finances
web mvc embed map
web mvc embed photos
web mvc embed stream video
web mvc embed twitter
web mvc embed video
Về đầu trang
Kỹ thuật đảo ngược cơ sở dữ liệu
Kỹ thuật đảo ngược cơ sở dữ liệu (DBRE) cho phép bạn tự xem xét một cơ sở dữ liệu hiện có và
trưng nó ra như một ứng dụng. Để hiển thị cách DBRE làm việc, tôi sẽ tạo ra một ứng dụng liên
hệ ngược từ một lược đồ liên hệ ngược hiện có. Tôi sẽ sử dụng MySQL làm một cơ sở dữ liệu.
Trước khi chúng ta khởi chạy Roo, chúng ta phải tạo ra một lược đồ trong bản cài đặt MySQL
của mình. Chạy kịch bản SQL trong Liệt kê 8 để tạo ra một lược đồ liên hệ ngược trong cơ sở dữ
liệu MySQL của bạn.
Liệt kê 8. Kịch bản lệnh SQL để tạo ra lược đồ liên hệ ngược
create database feedback_schema;
use feedback_schema;
CREATE TABLE feedback (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
TalkTitle VARCHAR(45) NOT NULL,
SpeakerName VARCHAR(45) NOT NULL,
Feedback VARCHAR(4000) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = InnoDB;
Đây là một lược đồ đơn giản có một bảng và không có bất kỳ mối quan hệ nào, nhưng Roo có
thể thực hiện thành công kỹ thuật-đảo ngược một lược đồ phức tạp có nhiều bảng và các mối
quan hệ.
Sau khi bạn đã chạy kịch bản lệnh SQL ở trên và đã tạo ra lược đồ của mình, hãy tạo ra một ứng
dụng liên hệ ngược:
1. Tạo một thư mục gọi là feedback (liên hệ ngược).
2. Từ dòng lệnh hệ điều hành của bạn, hãy vào thư mục feedback.
3. Mở trình vỏ Roo bằng cách gõ lệnh roo.
4. Gõ project --topLevelPackage com.dw.roo.feedback để tạo ra một dự án Maven
mới.
5. Trong ứng dụng này, chúng ta sẽ sử dụng MySQL làm cơ sở dữ liệu của mình. Để thiết
lập sự tồn tại lâu bền cho ứng dụng của bạn, hãy sử dụng:
persistence setup --provider HIBERNATE
--database MYSQL --databaseName feedback_schema
--userName root --password password
6.
7. Khi tôi đã tạo ra lược đồ với người dùng chủ, tôi sẽ sử dụng root làm tên người dùng của
mình. Xin hãy nhập tên người dùng và mật khẩu mà bạn đã dùng chúng để tạo ra lược đồ
của mình. Lệnh này cũng sẽ thêm tất cả các JAR cần thiết cho sự tồn tại lâu bền.
8. Bạn có thể tự xem xét lược đồ cơ sở dữ liệu bằng lệnh database introspect --schema
feedback_schema. Lệnh database introspect (tự xem xét cơ sở dữ liệu) cho thấy siêu
dữ liệu liên quan đến lược đồ cơ sở dữ liệu. Lệnh này sẽ cho bạn thấy siêu dữ liệu cho
lược đồ của bạn trên giao diện điều khiển trình vỏ Roo. Bạn cũng có thể xuất khẩu xml
siêu dữ liệu vào một tệp khi sử dụng lệnh --file attribute.
9. Khi bạn đã hoàn thành việc tự xem xét cho lược đồ cơ sở dữ liệu của mình, bạn có thể sử
dụng kỹ thuật-đảo ngược lược đồ đó bằng cách sử dụng lệnh database reverse
engineer --schema feedback