text:
Hôm nay xem đoạn clip Đoàn Văn Vươn nhận tội ở cơ quan công an Hải Phòng. Thấy tiếng công an thì không rõ, còn tiếng anh Vươn thì rõ ràng.
- Tôi nhận thấy việc mình là sai, xin đảng và nhà nước...
Tự dưng thấy nản, sao người dân nước mình cứ phạm tội gì mà nên báo chí, truyền hình cứ phải xin Đảng sau đó mới đến nhà nước, pháp luật xem xem khoan hồng hay nhẹ tội.
Chả lẽ Đảng có quyền tha tội hay xem xét tội cho ai được nặng hay nhẹ sao?
Người ta bảo có bệnh thì vái tứ phương, thôi thì người dân sa vào tay công an, nhận thức có phần hạn chế, họ cầu xin thế nào cũng có thể chấp nhận. Nhưng những người làm truyền thông, những cán bộ điều tra, những người làm pháp luật trong một chế độ pháp trị, mọi việc từ lớn đến bé đều phải rõ ràng theo luật. Ngay cả vụ anh Vươn các cấp lãnh đạo từ cấp huyện đến chính phủ, thủ tướng còn cũng phải nói là mọi việc sẽ xem xét đúng với pháp luật, ai sai đến đâu xử đó. Có lãnh đạo nào trong các vụ liên quan đến pháp luật nói phải xử theo nghị quyết, theo chỉ đạo cuả Đảng đâu, có vị nào nói Đảng là tòa án đâu...Tại sao người ta cứ để bị can, bị cáo nói khơi khơi cái câu là xin Đảng...xem xét, khoan hồng được.
Để người ta nói như thế, thành ra là làm xấu đi hình ảnh của Đảng, khiến người ta nghĩ Đảng cao hơn cả pháp luật, nhà nước. Mà thực tế thì hầu như những người van xin kiểu như vậy thường chả nhẹ tội đi chút nào, như Lê Công Định, Nguyễn Tiến Trung... cũng mức án như anh Cù Huy Hà Vũ dù anh Vũ không hề xin xỏ Đảng nửa lời. Qua đó chứng tỏ Đảng rất minh bạch, đàng hoàng không hề bao che, hay can thiệp vào pháp luật, thằng nào xin hay không xin đều thế hết, tùy tội mà pháp luật phệt.
Thế mà nhiều người có chức quyền, có trách nhiệm đáng nhẽ phải ý thức được cái chuyện uy tín của Đảng mà ngăn cản, nhắc nhở những bị can, bị cáo là chỉ xin pháp luật, nhân dân xem xét khoan hồng. Đằng này không những không ngăn, mà lại có vẻ rất thích thú khi bị cáo nói thế để đưa lên truyền hình, báo chí cứ như là ta đây đã lập chiến công với Đảng.
Cứ như thế thành thói quen, bọn hiếp dâm, móc túi, cờ bạc cứ phạm tội ra tòa lại xoen xoét cái điệu - xin Đảng và... khoan hồng thì nực cười lắm. Đâu phải cứ phạm tội là lôi Đảng ra mà xin xỏ được. Biết rõ là không xin được vì nhà nước ta là nhà nước pháp quyền, mà cứ để bị can, bị cáo lên ti vi, đài báo xin xỏ như thế khiên người ngoài lại tưởng chế độ ưu việt mà Bác Hồ đã dày công gây dựng cho nhân dân ta tốt đẹp thế lại thành chế độ Đảng trị.
Mong rằng các cán bộ có trách nhiệm nên xem xét, nhắc nhở các bị can, bị cáo đừng xin thế. Và cũng nhắc nhở những người làm truyền thông chớ đưa những đoạn xin xỏ với Đảng của bị can, bị cáo lên cho người ta xem. Nếu không oan cho Đảng quá.
Ở Pháp, Luxembourg, ... tên các thánh bên công giáo thường là tên 12 tông đồ và một số sau này. Các tên thông dụng như Pierre, Jean, Luc, Marc, Jacques, Paul, ... đều là tên các thánh cả.
Đa số các tên thông dụng đều là tên các thánh, do truyền thống dùng lâu năm, người ta không còn chú ý đó là tên thánh hay không và tên này ghi trong CMND (identity card). Nhiều người có tên là Pierre, Paul nhưng họ không làm lễ xác nhận khi 12, 16 tuổi, hầu như chẳng bao giờ đặt chân đến nhà thờ vì theo họ các linh mục giảng ... sai và chúa là ở tại tâm.
Còn người Việt thì dùng tên này là tên thánh, có mục đích tôn giáo cụ thể và không có ghi trong CMND.
Đạo hồi cũng dùng tên thánh Muhammad, Mohammed rất thông dụng cho tên chính thức trong CMND.
mã số 51859 hỏi "Để ý thấy nhiều người Việt theo Công giáo thường xưng tên thánh trước tên cúng cơm của mình. Điều ấy dễ hiểu nếu họ dùng trong phạm vi tôn giáo, nhưng ngay cả trong những hoạt động xã hội bình thường khác họ cũng làm như thế. Bác nào biết người Công giáo các nước khác có như vậy không, hay chỉ đặt biệt cho người VN thôi?"
Trả lời: Vladimia I-lich Le-nin (V.I. Lenin) thì trong đó Vladimia là tên thánh của ông ấy. Tên thật của ông ấy là Vo-lo-di-a , Le-nin là bí danh hoạt động cách mạng.
Để ý thấy nhiều người Việt theo Công giáo thường xưng tên thánh trước tên cúng cơm của mình. Điều ấy dễ hiểu nếu họ dùng trong phạm vi tôn giáo, nhưng ngay cả trong những hoạt động xã hội bình thường khác họ cũng làm như thế.
Bác nào biết người Công giáo các nước khác có như vậy không, hay chỉ đặt biệt cho người VN thôi? Theo thiển ý, như thế có vẻ quá khích. Xin lỗi nếu lời nói có làm xúc phạm vì tôi không theo đạo nên có thể thiếu nhạy cảm.
Không van xin đảng, nhà nước và tòa án cộng sản đã đành; thêm một bước nữa nếu ra trước tòa (nhất là những vụ án mang yếu tố chính trị) thì có cần nhờ luật sư biện hộ không? Xem lại những vụ án đã qua, vai trò của người luật sư đã giúp được bao nhiêu?
Đi theo chiều hướng không van xin, không biện hộ thì có nghĩa nên lặng thinh để phản đối tòa án và bản án. Hoặc hơn nữa như một Gandhi ra trước tòa uy vũ đến độ vị thẩm phán phải đứng dậy chào, nhưng Gandhi đã xác nhận ông không biện hộ gì cả và thách thức tòa cho ông bản án nặng nhất có thể tuyên được. Đó là một phần của phương cách đấu tranh bất bạo động của vị thánh Ấn độ.
(từ phút 11:00 trở đi)
http://www.youtube.com/watch?v=FLadXt5DZ7Y&feature=related
Bác HyVăn,
Có một điểm khác là chuá, thánh, thần thì không ai thấy (đại đa số người VN bây giờ) cho nên dễ có trí tưởng tượng về các việc ban ơn. Dân hồi giáo rất hay tin chuyện này.
Tuy nhiên ngược lại, dân châu Mỹ, Âu, đa số không tin mặc dù họ có thể đi nhà thờ vì truyền thống. Tôi vốn học cấp trung và đại học ở trường công giáo. Các giáo sư, đôi khi là linh mục, họ rất thoáng và luôn yêu cầu tự mình suy nghĩ chứ không bao giờ theo đạo vì bắt buộc. Có vị còn cho rằng tôn chỉ của đạo Phật có nhiều điểm rất hay vì nó tôn trọng tư tưởng của con người. Người công giáo ở Nam Hàn, Phi, VN có vẻ sùng đạo lẫm liệt hơn hẳn dân Pháp, Benelux, Anh, Đức
Cái não trạng Đảng là tất cả này không đổi từ 67 năm nay (từ 1945)- là nhiệm vụ bất khả thi cho toàn thể những người có học thức.Hãy phân tích hành động của 1 người con là nhạc
sĩ tài hoa có ông bố vào hạng Danh Nhân VN bị hành hình
vì bị lãnh tụ Đảng ghen ghét cá nhân, ca ngợi "Đảng đã cho ta một mùa Xuân ", và ca ngợi suốt đời kẻ đó, thậm chí còn mong đạt được giải thưởng mang tên kẻ giết cha mình.Thật bi hài cho các tài năng đất Việt.Nhưng cá nhân tôi thì cho rằng ông nhạc sĩ này không có cái nghĩa bằng 1 con chó.
Xin đảng, xin nhà nước khoan hồng thì cũng tương tự như lạy chúa ban ơn, hệ thống tuyên truyền nhồi nhét đã làm chính quyền thành một thứ tôn giáo mặc định.
"...nhà nước ta là nhà nước pháp quyền, mà cứ để bị can, bị cáo lên ti vi, đài báo xin xỏ như thế khiên người ngoài lại tưởng chế độ ưu việt mà Bác Hồ đã dày công gây dựng cho nhân dân ta tốt đẹp thế lại thành chế độ Đảng trị."
Người Buôn Gió nói bóng nói gió hay lắm. Đúng vậy người ngoài cuộc thì cứ tưởng nhà nước ta là nhà nước pháp quyền nhưng người dân thường thì ai cũng biết nhà nước ta là độc quyền, Đảng trị nên mỗi khi phải xin xỏ thì họ phải xin Đảng trước là thế.
Qua đó chứng tỏ Đảng rất minh bạch, đàng hoàng không hề bao che, hay can thiệp vào pháp luật
Thiệt hông đó bác NBG ?
Vấn đìa nà từ công an điều tra, UBND, công tố viên, hội thẩm, chánh án, thẩm phán đều là đảng viên cả ! Chưa kể những kẻ soạn luật cũng đều là đảng viên
Nếu đảng muốn minh bạch, những người nêu trên phải không là đảng viên
Đừng chờ đợi gì thêm ở anh Vươn.
Phần anh, anh đã góp đủ.
Hơn 8o triệu dân, trừ vài trăm ngàn Đảng Viên thoái hóa, cũng còn ít nhất hơn 79 triệu.
Chỉ cần 1/10 làm theo.
1 hy vọng, mong là không hảo huyền.
Hay phải đợi đến khi hơn 79 triệu ngưới dân VN này không còn gì để mầt như anh Vươn ?
Gửi phản hồi mới (xin gõ tiếng Việt có dấu và tuân thủ Nguyên tắc Dân Luận để được chấp nhận)

markdown:
Hôm nay xem đoạn clip Đoàn Văn Vươn nhận tội ở cơ quan công an Hải Phòng. Thấy tiếng công an thì không rõ, còn tiếng anh Vươn thì rõ ràng.
- Tôi nhận thấy việc mình là sai, xin đảng và nhà nước...
Tự dưng thấy nản, sao người dân nước mình cứ phạm tội gì mà nên báo chí, truyền hình cứ phải xin Đảng sau đó mới đến nhà nước, pháp luật xem xem khoan hồng hay nhẹ tội.
Chả lẽ Đảng có quyền tha tội hay xem xét tội cho ai được nặng hay nhẹ sao?
Người ta bảo có bệnh thì vái tứ phương, thôi thì người dân sa vào tay công an, nhận thức có phần hạn chế, họ cầu xin thế nào cũng có thể chấp nhận. Nhưng những người làm truyền thông, những cán bộ điều tra, những người làm pháp luật trong một chế độ pháp trị, mọi việc từ lớn đến bé đều phải rõ ràng theo luật. Ngay cả vụ anh Vươn các cấp lãnh đạo từ cấp huyện đến chính phủ, thủ tướng còn cũng phải nói là mọi việc sẽ xem xét đúng với pháp luật, ai sai đến đâu xử đó. Có lãnh đạo nào trong các vụ liên quan đến pháp luật nói phải xử theo nghị quyết, theo chỉ đạo cuả Đảng đâu, có vị nào nói Đảng là tòa án đâu...Tại sao người ta cứ để bị can, bị cáo nói khơi khơi cái câu là xin Đảng...xem xét, khoan hồng được.
Để người ta nói như thế, thành ra là làm xấu đi hình ảnh của Đảng, khiến người ta nghĩ Đảng cao hơn cả pháp luật, nhà nước. Mà thực tế thì hầu như những người van xin kiểu như vậy thường chả nhẹ tội đi chút nào, như Lê Công Định, Nguyễn Tiến Trung... cũng mức án như anh Cù Huy Hà Vũ dù anh Vũ không hề xin xỏ Đảng nửa lời. Qua đó chứng tỏ Đảng rất minh bạch, đàng hoàng không hề bao che, hay can thiệp vào pháp luật, thằng nào xin hay không xin đều thế hết, tùy tội mà pháp luật phệt.
Thế mà nhiều người có chức quyền, có trách nhiệm đáng nhẽ phải ý thức được cái chuyện uy tín của Đảng mà ngăn cản, nhắc nhở những bị can, bị cáo là chỉ xin pháp luật, nhân dân xem xét khoan hồng. Đằng này không những không ngăn, mà lại có vẻ rất thích thú khi bị cáo nói thế để đưa lên truyền hình, báo chí cứ như là ta đây đã lập chiến công với Đảng.
Cứ như thế thành thói quen, bọn hiếp dâm, móc túi, cờ bạc cứ phạm tội ra tòa lại xoen xoét cái điệu - xin Đảng và... khoan hồng thì nực cười lắm. Đâu phải cứ phạm tội là lôi Đảng ra mà xin xỏ được. Biết rõ là không xin được vì nhà nước ta là nhà nước pháp quyền, mà cứ để bị can, bị cáo lên ti vi, đài báo xin xỏ như thế khiên người ngoài lại tưởng chế độ ưu việt mà Bác Hồ đã dày công gây dựng cho nhân dân ta tốt đẹp thế lại thành chế độ Đảng trị.
Mong rằng các cán bộ có trách nhiệm nên xem xét, nhắc nhở các bị can, bị cáo đừng xin thế. Và cũng nhắc nhở những người làm truyền thông chớ đưa những đoạn xin xỏ với Đảng của bị can, bị cáo lên cho người ta xem. Nếu không oan cho Đảng quá.
|
|
Hồ Gươm gửi hôm Thứ Ba, 07/02/2012
|
|
Bạn đánh giá bài viết này thế nào?
Dùng tên thánh (khách viếng thăm)gửi lúc 02:52, 09/02/2012 - mã số 51915 Thuận Phong viết:
Ở Pháp, Luxembourg, ... tên các thánh bên công giáo thường là tên 12 tông đồ và một số sau này. Các tên thông dụng như Pierre, Jean, Luc, Marc, Jacques, Paul, ... đều là tên các thánh cả.
Đa số các tên thông dụng đều là tên các thánh, do truyền thống dùng lâu năm, người ta không còn chú ý đó là tên thánh hay không và tên này ghi trong CMND (identity card). Nhiều người có tên là Pierre, Paul nhưng họ không làm lễ xác nhận khi 12, 16 tuổi, hầu như chẳng bao giờ đặt chân đến nhà thờ vì theo họ các linh mục giảng ... sai và chúa là ở tại tâm.
Còn người Việt thì dùng tên này là tên thánh, có mục đích tôn giáo cụ thể và không có ghi trong CMND.
Đạo hồi cũng dùng tên thánh Muhammad, Mohammed rất thông dụng cho tên chính thức trong CMND.
Thuận Phong (khách viếng thăm)gửi lúc 02:16, 09/02/2012 - mã số 51912
mã số 51859 hỏi "Để ý thấy nhiều người Việt theo Công giáo thường xưng tên thánh trước tên cúng cơm của mình. Điều ấy dễ hiểu nếu họ dùng trong phạm vi tôn giáo, nhưng ngay cả trong những hoạt động xã hội bình thường khác họ cũng làm như thế. Bác nào biết người Công giáo các nước khác có như vậy không, hay chỉ đặt biệt cho người VN thôi?"
Trả lời: Vladimia I-lich Le-nin (V.I. Lenin) thì trong đó Vladimia là tên thánh của ông ấy. Tên thật của ông ấy là Vo-lo-di-a , Le-nin là bí danh hoạt động cách mạng.
www (khách viếng thăm)gửi lúc 15:39, 08/02/2012 - mã số 51859
Để ý thấy nhiều người Việt theo Công giáo thường xưng tên thánh trước tên cúng cơm của mình. Điều ấy dễ hiểu nếu họ dùng trong phạm vi tôn giáo, nhưng ngay cả trong những hoạt động xã hội bình thường khác họ cũng làm như thế.
Bác nào biết người Công giáo các nước khác có như vậy không, hay chỉ đặt biệt cho người VN thôi? Theo thiển ý, như thế có vẻ quá khích. Xin lỗi nếu lời nói có làm xúc phạm vì tôi không theo đạo nên có thể thiếu nhạy cảm.
tự-do (khách viếng thăm)gửi lúc 15:30, 08/02/2012 - mã số 51858
Không van xin đảng, nhà nước và tòa án cộng sản đã đành; thêm một bước nữa nếu ra trước tòa (nhất là những vụ án mang yếu tố chính trị) thì có cần nhờ luật sư biện hộ không? Xem lại những vụ án đã qua, vai trò của người luật sư đã giúp được bao nhiêu?
Đi theo chiều hướng không van xin, không biện hộ thì có nghĩa nên lặng thinh để phản đối tòa án và bản án. Hoặc hơn nữa như một Gandhi ra trước tòa uy vũ đến độ vị thẩm phán phải đứng dậy chào, nhưng Gandhi đã xác nhận ông không biện hộ gì cả và thách thức tòa cho ông bản án nặng nhất có thể tuyên được. Đó là một phần của phương cách đấu tranh bất bạo động của vị thánh Ấn độ.
(từ phút 11:00 trở đi)
http://www.youtube.com/watch?v=FLadXt5DZ7Y&feature=related
Ban ơn và xin (khách viếng thăm)gửi lúc 13:16, 08/02/2012 - mã số 51848 HyVăn viết:
Bác HyVăn,
Có một điểm khác là chuá, thánh, thần thì không ai thấy (đại đa số người VN bây giờ) cho nên dễ có trí tưởng tượng về các việc ban ơn. Dân hồi giáo rất hay tin chuyện này.
Tuy nhiên ngược lại, dân châu Mỹ, Âu, đa số không tin mặc dù họ có thể đi nhà thờ vì truyền thống. Tôi vốn học cấp trung và đại học ở trường công giáo. Các giáo sư, đôi khi là linh mục, họ rất thoáng và luôn yêu cầu tự mình suy nghĩ chứ không bao giờ theo đạo vì bắt buộc. Có vị còn cho rằng tôn chỉ của đạo Phật có nhiều điểm rất hay vì nó tôn trọng tư tưởng của con người. Người công giáo ở Nam Hàn, Phi, VN có vẻ sùng đạo lẫm liệt hơn hẳn dân Pháp, Benelux, Anh, Đức
tathanh (khách viếng thăm)gửi lúc 11:19, 08/02/2012 - mã số 51842
Cái não trạng Đảng là tất cả này không đổi từ 67 năm nay (từ 1945)- là nhiệm vụ bất khả thi cho toàn thể những người có học thức.Hãy phân tích hành động của 1 người con là nhạc
sĩ tài hoa có ông bố vào hạng Danh Nhân VN bị hành hình
vì bị lãnh tụ Đảng ghen ghét cá nhân, ca ngợi "Đảng đã cho ta một mùa Xuân ", và ca ngợi suốt đời kẻ đó, thậm chí còn mong đạt được giải thưởng mang tên kẻ giết cha mình.Thật bi hài cho các tài năng đất Việt.Nhưng cá nhân tôi thì cho rằng ông nhạc sĩ này không có cái nghĩa bằng 1 con chó.
HyVăn (khách viếng thăm)gửi lúc 10:28, 08/02/2012 - mã số 51830
Xin đảng, xin nhà nước khoan hồng thì cũng tương tự như lạy chúa ban ơn, hệ thống tuyên truyền nhồi nhét đã làm chính quyền thành một thứ tôn giáo mặc định.
Sáu Liều (khách viếng thăm)gửi lúc 07:43, 08/02/2012 - mã số 51821
"...nhà nước ta là nhà nước pháp quyền, mà cứ để bị can, bị cáo lên ti vi, đài báo xin xỏ như thế khiên người ngoài lại tưởng chế độ ưu việt mà Bác Hồ đã dày công gây dựng cho nhân dân ta tốt đẹp thế lại thành chế độ Đảng trị."
Người Buôn Gió nói bóng nói gió hay lắm. Đúng vậy người ngoài cuộc thì cứ tưởng nhà nước ta là nhà nước pháp quyền nhưng người dân thường thì ai cũng biết nhà nước ta là độc quyền, Đảng trị nên mỗi khi phải xin xỏ thì họ phải xin Đảng trước là thế.
Thiệt hông đó (khách viếng thăm)gửi lúc 03:15, 08/02/2012 - mã số 51812 Qua đó chứng tỏ Đảng rất minh bạch, đàng hoàng không hề bao che, hay can thiệp vào pháp luật
Thiệt hông đó bác NBG ?
Vấn đìa nà từ công an điều tra, UBND, công tố viên, hội thẩm, chánh án, thẩm phán đều là đảng viên cả ! Chưa kể những kẻ soạn luật cũng đều là đảng viên
Nếu đảng muốn minh bạch, những người nêu trên phải không là đảng viên
Tôi thôi (khách viếng thăm)gửi lúc 03:08, 08/02/2012 - mã số 51810
Đừng chờ đợi gì thêm ở anh Vươn.
Phần anh, anh đã góp đủ.
Hơn 8o triệu dân, trừ vài trăm ngàn Đảng Viên thoái hóa, cũng còn ít nhất hơn 79 triệu.
Chỉ cần 1/10 làm theo.
1 hy vọng, mong là không hảo huyền.
Hay phải đợi đến khi hơn 79 triệu ngưới dân VN này không còn gì để mầt như anh Vươn ?
## Gửi phản hồi mới (xin
gõ tiếng Việt có dấuvà tuân thủ Nguyên tắc Dân Luậnđể được chấp nhận)

Server: nginx

X-XSS-Protection: 1; mode=block

X-Content-Options: nosniff

Cache-Control: max-age=0, no-cache


text:
Để tìm máy nhân bản gần nhất (cũng nên là nhanh nhất), xem danh sách máy nhân bản Debian.
Khi tải tập tin xuống một máy nhân bản Debian qua FTP, kiểm tra lại bạn tải về trong chế độ nhị phân (binary), không phải chế độ văn bản (text) hay tự động (automatic).
Các ảnh cài đặt nằm trên mỗi máy nhân bản Debian, trong thư mục debian/dists/wheezy/main/installer-armel/current/images/ — MANIFEST (bản kê khai) liệt kê mọi ảnh và mục đích tương ứng.
Cung cấp cho máy Thecus N2100 một ảnh phần vững sẽ tự động khởi động
debian-installer. Ảnh này có thể được cài đặt dùng quá trình nâng cấp phần vững Thecus. Ảnh phần vững này có thể được lấy từ ảnh
.../images/ixp4xx/network-console/di-nslu2.bin
.
GLAN Tank yêu cầu một hạt nhân và đĩa RAM trên một phân vùng ext2 trên đĩa vào đó bạn định cài đặt Debian. Các ảnh này có thể được lấy từ .../images/iop32x/network-console/glantank/ .
Kurobox Pro yêu cầu một hạt nhân và đĩa RAM trên một phân vùng ext2 trên đĩa vào đó bạn định cài đặt Debian. Các ảnh này có thể được lấy từ .../images/orion5x/network-console/buffalo/kuroboxpro .
Cung cấp cho máy HP mv2120 một ảnh phần vững sẽ tự động khởi động
debian-installer. Ảnh này có thể được cài đặt dùng uphpmvault trên Linux và các hệ thống khác, và dùng tiện ích HP Media Vault Firmware Recovery Utility trên Windows. Ảnh phần vững có thể được lấy từ
.../images/orion5x/network-console/hp/mv2120/netboot.img
.
Những tập tin cài đặt đối với máy QNAP Turbo Station chứa một hạt nhân và một đĩa RAM, cùng với một văn lệnh để ghi các ảnh này vào bộ nhớ flash. Bạn có thể lấy các tập tin cài đặt cho các máy kiểu QNAP TS-11x, TS-21x and TS-41x từ .../images/kirkwood/network-console/qnap/ .
The installation files for plug computers (SheevaPlug, GuruPlug, DreamPlug etc) and OpenRD devices consist of a kernel and initrd for U-Boot. You can obtain these files from .../images/kirkwood/netboot/marvell/ .
The installation files for LaCie NASes (Network Space v2, Network Space Max v2, Internet Space v2, d2 Network v2, 2Big Network v2 and 5Big Network v2) consist of a kernel and initrd for U-Boot. You can obtain these files from .../images/kirkwood/network-console/lacie/ .

markdown:
Để tìm máy nhân bản gần nhất (cũng nên là nhanh nhất), xem
[danh sách máy nhân bản Debian](http://www.debian.org/distrib/ftplist).
Khi tải tập tin xuống một máy nhân bản Debian qua FTP, kiểm tra lại bạn tải về trong chế độ
*nhị phân* (binary), không phải chế độ văn bản (text) hay tự động (automatic).
Các ảnh cài đặt nằm trên mỗi máy nhân bản Debian, trong thư mục
[debian/dists/wheezy/main/installer-armel/current/images/](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images) — [MANIFEST](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/MANIFEST) (bản kê khai) liệt kê mọi ảnh và mục đích tương ứng.
Cung cấp cho máy Thecus N2100 một ảnh phần vững sẽ tự động khởi động
debian-installer. Ảnh này có thể được cài đặt dùng quá trình nâng cấp phần vững Thecus. Ảnh phần vững này có thể được lấy từ ảnh
[.../images/ixp4xx/network-console/di-nslu2.bin](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/ixp4xx/network-console/di-nslu2.bin)
.
GLAN Tank yêu cầu một hạt nhân và đĩa RAM trên một phân vùng ext2 trên đĩa vào đó bạn định cài đặt Debian. Các ảnh này có thể được lấy từ
[.../images/iop32x/network-console/glantank/](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/iop32x/network-console/glantank/)
.
Kurobox Pro yêu cầu một hạt nhân và đĩa RAM trên một phân vùng ext2 trên đĩa vào đó bạn định cài đặt Debian. Các ảnh này có thể được lấy từ
[.../images/orion5x/network-console/buffalo/kuroboxpro](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/orion5x/network-console/buffalo/kuroboxpro)
.
Cung cấp cho máy HP mv2120 một ảnh phần vững sẽ tự động khởi động
debian-installer. Ảnh này có thể được cài đặt dùng uphpmvault trên Linux và các hệ thống khác, và dùng tiện ích HP Media Vault Firmware Recovery Utility trên Windows. Ảnh phần vững có thể được lấy từ
[.../images/orion5x/network-console/hp/mv2120/netboot.img](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/orion5x/network-console/hp/mv2120/netboot.img)
.
Những tập tin cài đặt đối với máy QNAP Turbo Station chứa một hạt nhân và một đĩa RAM, cùng với một văn lệnh để ghi các ảnh này vào bộ nhớ flash. Bạn có thể lấy các tập tin cài đặt cho các máy kiểu QNAP TS-11x, TS-21x and TS-41x từ
[.../images/kirkwood/network-console/qnap/](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/kirkwood/network-console/qnap/)
.
The installation files for plug computers (SheevaPlug, GuruPlug, DreamPlug etc) and OpenRD devices consist of a kernel and initrd for U-Boot. You can obtain these files from
[.../images/kirkwood/netboot/marvell/](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/kirkwood/netboot/marvell/)
.
The installation files for LaCie NASes (Network Space v2, Network Space Max v2, Internet Space v2, d2 Network v2, 2Big Network v2 and 5Big Network v2) consist of a kernel and initrd for U-Boot. You can obtain these files from
[.../images/kirkwood/network-console/lacie/](http://http.us.debian.org/debian/dists/wheezy/main/installer-armel/current/images/kirkwood/network-console/lacie/)
.

WARC-Type: response

Content-Type: application/http; msgtype=response

Server: Apache

Accept-Ranges: bytes

Vary: Accept-Encoding

Content-Encoding: gzip

Connection: close

Content-Type: text/html

Content-Language: vi


text:
Khách sạn Hoa Hồng I Sầm Sơn - Thanh Hóa được tọa lạc trên bãi tắm A, vị trí địa lý thuận lợi, nằm trên trục đường Hồ Xuân Hương giáp Biển Đông.
1. Loại phòng: 105 phòng có máy lạnh, trong đó
- Phòng VIP 05 phòng: Trước 30/5 và sau 20/8 giảm giá từ 15-20%.
- Phòng loại đủ tiêu chuẩn 100 phòng: Trước 30/5 và sau 20/8 giảm giá từ 15-20%.
Tiện nghi phòng:
2. Nhà hàng & Bar:
- Nhà hàng 400 chỗ
3. Tiện nghi và dịch vụ khác:
VUI LÒNG LIÊN HỆ ETV THEO SỐ 04 667 188 12 / 04 3994 3118 ĐỂ BIẾT THÊM CHI TIẾT
- Vui lòng liên hệ với ETV để biết thông tin khuyến mại

WARC-Truncated: length

Content-Type: text/html; charset=utf-8

X-Powered-By: PleskLin


text:
Lý do chung nhất khi sử dụng các giao tác trong một ứng dụng là để duy trì tính toàn vẹn và nhất quán của dữ liệu ở mức cao. Nếu bạn không quan tâm đến chất lượng dữ liệu của mình, thì bạn cũng không cần quan tâm đến các giao tác. Sau hết, việc hỗ trợ giao tác trên nền Java có thể hủy hoại hiệu năng, sinh ra vấn đề về khóa và các vấn đề tương tranh trong cơ sở dữ liệu, và do vậy gây thêm phức tạp cho trình ứng dụng của bạn.
Nhưng những người phát triển lại không bận tâm đến những giao tác gây thiệt hại cho mình như thế. Hầu hết các ứng dụng có liên quan đến kinh doanh đều yêu cầu chất lượng dữ liệu ở mức cao. Chỉ riêng ngành kinh doanh đầu tư tài chính đã mất mười tỉ đô la cho các hoạt động thương mại thất bại, mà dữ liệu tồi là nguyên nhân thứ hai dẫn tới tình trạng này (xem Tài nguyên). Mặc dù việc thiếu các hỗ trợ giao tác chỉ là một tác nhân dẫn đến tình trạng dữ liệu tồi (vẫn là nguyên nhân chính), một kết luận chắc chắn là hàng tỷ đô la đã bị lãng phí chỉ riêng trong lĩnh vực kinh doanh đầu tư tài chính là hậu quả của việc thiếu hụt hoặc không có các hỗ trợ giao tác.
Không biết gì về các hỗ trợ giao tác là nguyên nhân khác của vấn đề. Rất thường xuyên tôi đã nghe những tuyên bố theo kiểu “chúng tôi không cần hỗ trợ giao tác trong các trình ứng dụng của chúng tôi đâu, bởi vì chúng chả bao giờ lỗi cả.” Đúng. Tôi đã từng chứng kiến một số trình ứng dụng trong thực tế cực hiếm hoặc không bao giờ đưa ra các báo lỗi. Những trình ứng dụng ấy trông cậy vào việc có mã lệnh viết rất tốt, có các thủ tục kiểm tra dữ liệu hợp lệ được viết tốt và việc hỗ trợ kiểm soát mã và kiểm thử đầy đủ để giảm chi phí thực thi và những phức tạp liên quan đến xử lý giao tác. Vấn đề của cách suy nghĩ như thế là ở chỗ nó chỉ tính đến một đặc trưng của hỗ trợ giao tác: tính nguyên tử . Tính nguyên tử đảm bảo rằng mọi cập nhật sẽ được xem như một đơn vị công việc duy nhất và, hoặc là tất cả được giao kết hoặc là tất cả bị hủy bỏ. Nhưng sự hủy bỏ hoặc phối hợp các cập nhật không phải là khía cạnh duy nhất của hỗ trợ giao tác. Một khía cạnh khác, sự phân lập, sẽ đảm bảo rằng mỗi đơn vị công việc được tách biệt khỏi các đơn vị khác. Nếu không có sự phân lập giao tác thích hợp, các đơn vị công việc khác có thể truy nhập vào các cập nhật được tạo ra bởi một đơn vị công việc đang chạy, mặc dù đơn vị này chưa hoàn thành xong việc của mình. Và kết quả là các quyết định kinh doanh có thể được đưa ra dựa trên dữ liệu chưa hoàn chỉnh, gây ra những giao dịch kinh doanh thất bại hoặc những hậu quả tiêu cực.
Vậy thì khi đã biết rằng chi phí cao và ảnh hưởng xấu của dữ liệu tồi và các hiểu biết cơ bản về giao tác là quan trọng (và cần thiết), bạn cần sử dụng các giao tác và học cách giải quyết các vấn đề nảy sinh. Bạn gấp rút bổ sung hỗ trợ giao tác vào trình ứng dụng của mình. Và đây chính là chỗ mà các vấn đề thường nảy sinh. Các giao tác hình như thường không hoạt động như hứa hẹn trên nền Java. Bài viết này sẽ khảo sát tỉ mỉ lý do tại sao như thế. Cùng với sự trợ giúp của các đoạn mã ví dụ, tôi sẽ giới thiệu những cạm bẫy phổ biến trong giao tác mà tôi thường thấy và kinh nghiệm trong lĩnh vực này, hầu hết trường hợp là trong các môi trường sản xuất.
Mặc dù hầu hết các đoạn mã ví dụ trong bài viết này sử dụng khung công tác
Spring (Spring Framework) phiên bản 2.5, khái niệm giao tác là tương tự
như trong đặc tả EJB 3.0. Trong đa số các trường hợp, chỉ đơn giản là ta
thay thế lời chú giải
@Transactional của khung
công tác Spring bằng
@TransactionAttribute
trong đặc tả của EJB 3.0. Những chỗ mà hai bộ khung này khác nhau về khái
niệm và kỹ thuật, tôi sẽ đưa ra cả hai ví dụ mã nguồn của khung công tác
Spring và EJB 3.
Những cạm bẫy trong giao tác cục bộ.
Cách tốt nhất để khởi đầu là bằng một kịch bản dễ nhất: việc sử dụng các
giao tác cục bộ, cũng thường được gọi là giao tác cơ sở dữ
liệu. Thời kỳ đầu mới xuất hiện cơ sở dữ liệu bền vững (ví dụ
JDBC), chúng ta thường giao phó việc xử lý giao tác cho cơ sở dữ liệu. Rốt
cuộc thì đây có phải chính là cái mà cơ sở dữ liệu cần phải làm? Các giao
tác cục bộ làm việc tốt với các đơn vị công việc logic (LUW), tức là thực
hiện các câu lệnh đơn như chèn, cập nhật hoặc xóa. Ví dụ, xét đoạn mã lệnh
JDBC đơn giản trong Liệt kê 1, đoạn mã lệnh này thực hiện thao tác chèn
một lệnh mua bán chứng khoán vào bảng
TRADE:
Liệt kê 1. Thao tác chèn đơn giản vào một cơ sở dữ liệu sử dụng JDBC
@Stateless public class TradingServiceImpl implements TradingService { @Resource SessionContext ctx; @Resource(mappedName="java:jdbc/tradingDS") DataSource ds; public long insertTrade(TradeData trade) throws Exception { Connection dbConnection = ds.getConnection(); try { Statement sql = dbConnection.createStatement(); String stmt = "INSERT INTO TRADE (ACCT_ID, SIDE, SYMBOL, SHARES, PRICE, STATE)" + "VALUES (" + trade.getAcct() + "','" + trade.getAction() + "','" + trade.getSymbol() + "'," + trade.getShares() + "," + trade.getPrice() + ",'" + trade.getState() + "')"; sql.executeUpdate(stmt, Statement.RETURN_GENERATED_KEYS); ResultSet rs = sql.getGeneratedKeys(); if (rs.next()) { return rs.getBigDecimal(1).longValue(); } else { throw new Exception("Trade Order Insert Failed"); } } finally { if (dbConnection != null) dbConnection.close(); } } }
Đoạn mã lệnh JDBC trong Liệt kê 1 không có logic giao tác, nó một mực đưa
lệnh mua bán vào bảng
TRADE trong cơ sở dữ
liệu. Trong trường hợp này, cơ sở dữ liệu điều khiển logic giao tác.
Điều này là tốt và hợp lý đối với trường hợp chỉ có một hành động duy trì cơ sở dữ liệu trong đơn vị công việc lô gic (LUW). Nhưng giả sử rằng bạn cần cập nhật số dư tài khoản cùng thời điểm với việc bạn chèn một lệnh mua bán vào cơ sở dữ liệu, như ta thấy trong Liệt kê 2:
Liệt kê 2. Thực hiện nhiều cập nhật bảng trong cùng một phương thức
public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Trong trường hợp này, các phương thức
insertTrade() và
updateAcct() đã
dùng mã lệnh JDBC chuẩn mà không có các giao tác. Một khi phương thức
insertTrade() kết thúc, cơ sở dữ liệu sẽ
khẳng định (và giao kết (commit)) lệnh mua bán. Nếu phương thức
updateAcct() thất bại bởi bất cứ lý do gì, lệnh
mua bán này sẽ vẫn tồn tại trong bảng
TRADE khi
kết thúc phương thức placeTrade(), kết quả là dữ liệu không nhất quán
trong cơ sở dữ liệu. Nếu phương thức
placeTrade() sử dụng các giao tác, cả hai hoạt động này sẽ nằm
trong cùng một LUW và lệnh mua bán này sẽ bị hủy nếu việc cập nhật tài
khoản bị thất bại.
Với sự phổ biến rộng rãi của các khung công tác bền vững của Java như
Hibernate, TopLink và Java Persistence API (JPA) đang phát triển, chúng ta
hiếm khi viết thẳng các đoạn mã lệnh JDBC nữa. Phổ biến hơn là chúng ta
dùng các khung công tác ánh xạ quan hệ - đối tượng (ORM) mới hơn để làm
cho công việc dễ dàng hơn bằng cách thay thế tất cả các đoạn mã lệnh JDBC
khó chịu này bằng một vài lời gọi phương thức đơn giản. Ví dụ, để chèn một
lệnh mua bán từ ví dụ đoạn mã lệnh JDBC trong Liệt kê
1, sử dụng khung công tác Spring với JPA, bạn sẽ ánh xạ đối tượng
TradeData vào bảng
TRADE và thay thế toàn bộ đoạn mã lệnh JDBC này bằng đoạn mã
lệnh JPA trong Liệt kê 3:
Liệt kê 3. Thao tác chèn đơn giản dùng JPA
public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } }
Lưu ý rằng trong Liệt kê 3 ta gọi phương thức
persist() trong
EntityManager để
chèn một lệnh mua bán. Đơn giản quá, đúng không? Không hẳn thế. Đoạn mã
lệnh này sẽ không chèn lệnh mua bán vào bảng
TRADE như ta mong muốn, cũng không sinh ra ngoại lệ. Nó chỉ
đơn giản là trả lại giá trị
0 như là khóa của
lệnh mua bán này mà chẳng biến đổi gì cơ sở dữ liệu cả. Đây là cạm bẫy chủ
yếu đầu tiên của xử lý giao tác: các khung công tác dựa trên nền ORM
yêu cầu phải có một giao tác để kích hoạt một quá trình đồng bộ hóa
giữa đối tượng nhớ sẵn (cache object) và cơ sở dữ liệu. Chính là
thông qua việc giao kết một giao tác mà mã SQL sẽ được sinh ra và tác động
đến cơ sở dữ liệu với các hành động mong muốn (như chèn, cập nhật, xóa).
Không có một giao tác ở đây thì không thể kích hoạt một quá trình trên ORM
để sinh mã lệnh SQL và thực hiện các thay đổi, như vậy phương thức đơn
giản chỉ kết thúc– không có lỗi ngoại lệ, không có cập nhật. Nếu bạn đang
dùng khung công tác dựa trên ORM, bạn phải dùng sử dụng các giao tác. Bạn
không còn có thể dựa vào cơ sở dữ liệu để quản lý các kết nối và hoàn tất
công việc.
Những ví dụ đơn giản này biểu thị rõ ràng rằng giao tác là cần thiết để duy trì dữ liệu toàn vẹn và nhất quán. Nhưng đây mới chỉ là bề ngoài của những rắc rối và những cạm bẫy thường vấp phải khi thực thi các giao tác trên nền Java.
Bẫy chú giải
@Transactionalcủa khung công tác Spring
Như vậy bạn đã kiểm thử mã lệnh trong Liệt kê 3 và
khám phá ra rằng phương thức
persist() không
thực hiện khi thiếu giao tác. Kết quả là bạn thấy vài đường liên kết nhờ
một thao tác tìm kiếm đơn giản trên Internet và biết rằng với khung công
tác Spring, ta cần dùng chú giải
@Transactional. Bởi thế bạn thêm chú giải vào mã lệnh như trong
Liệt kê 4:
Liệt kê 4. Sử dụng chú giải
@Transactional
public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; @Transactional public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } }
Kiểm thử lại mã lệnh và bạn sẽ nhận thấy chương trình vẫn không hoạt động. Vấn đề là bạn phải thông báo với SpringFramework rằng bạn đang sử dụng các chú giải để quản lý giao tác. Trừ phi bạn đang thực hiện kiểm thử đơn vị toàn bộ, đôi khi cái bẫy này khá là khó tìm ra. Thông thường nó dẫn người phát triển đến chỗ chỉ đơn giản thêm vào các logic giao tác trong tệp cấu hình Spring mà không nghĩ tới các chú giải.
Khi sử dụng chú giải
@Transactional trong
Spring, ta phải thêm dòng mã sau vào tệp cấu hình Spring:
<tx:annotation-driven transaction-manager="transactionManager"/>
Thuộc tính
transaction-manager lưu giữ một tham
chiếu đến bean quản lý giao tác được định nghĩa trong tệp cấu hình Spring.
Dòng mã này báo cho Spring sử dụng chú giải
@Transaction khi áp dụng bộ chặn giao tác. Nếu không có đoạn
mã này, chú giải
@Transactional sẽ bị bỏ qua,
kết quả là không có giao tác nào được sử dụng trong mã lệnh.
Việc làm cho chú giải cơ sở
@Transactional có
tác dụng trong mã lệnh ở Liệt kê 4 chỉ là sự khởi đầu. Lưu ý rằng Liệt kê 4 sử dụng chú giải
@Transactional mà không định rõ bất cứ tham số chú giải bổ
sung nào. Tôi nhận thấy nhiều người dùng chú giải
@Transactional mà không bỏ thời gian tìm hiểu đầy đủ xem nó
làm gì. Ví dụ, khi sử dụng chú giải @Transactional không tham số như ta đã
làm trong Liệt kê 4, chế độ lan truyền giao tác sẽ được thiết lập là gì?
Cờ báo chỉ đọc được đặt là gì? Mức phân lập giao tác được đặt là gì? Quan
trọng hơn, khi nào thì giao tác sẽ bị cuộn lùi trở lại? Hiểu chú giải giao
tác được sử dụng như thế nào là rất quan trọng để đảm bảo bạn có mức độ hỗ
trợ giao tác thích hợp trong trình ứng dụng của mình. Và đây là trả lời
những câu hỏi tôi vừa đặt ra: khi sử dụng chú giải
@Transactional không có bất kỳ tham số nào, chế độ lan truyền
được đặt là
REQUIRED, cờ báo chỉ đọc đặt là
false, mức phân lập giao tác đặt giá trị
mặc định của cơ sở dữ liệu (thường là
READ_COMMITTED), và giao tác sẽ không bị cuộn lùi trở lại khi
ngoại lệ đã được kiểm tra.
Bẫy cờ chỉ đọc của chú giải
@Transactional
Một cạm bẫy phổ biến nhất mà tôi thường xuyên gặp là dùng sai cờ chỉ đọc
trong chú giải Spring
@Transactional. Ở đây có
một câu hỏi nhanh dành cho bạn: Khi dùng mã lệnh JDBC chuẩn của Java bền
vững, chú giải
@Transactional trong Liệt kê 5
thực hiện công việc gì khi cờ chỉ đọc được thiết lập giá trị
true và chế độ lan truyền đặt là
SUPPORTS?
Liệt kê 5. Sử dụng cờ chỉ đọc với chế độ lan truyền JDBC là
SUPPORTS.
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) public long insertTrade(TradeData trade) throws Exception { //JDBC Code... }
Khi thi hành phương thức
insertTrade() trong
Liệt kê 5, nó sẽ:
- Đưa ra lỗi ngoại lệ cảnh báo kết nối chỉ đọc.
- Chèn một cách chính xác lệnh mua bán và giao kết dữ liệu
- Không làm gì vì mức lan truyền đặt là
SUPPORTS
Bạn đầu hàng? Câu trả lời chính xác là B. Lệnh mua bán được chèn một cách
chính xác vào cơ sở dữ liệu, thậm chí cả khi cờ chỉ đọc được thiết lập giá
trị
true và lan truyền giao tác được đặt là
SUPPORTS. Nhưng tại sao lại có thể như thế?
Không có giao tác nào được khởi động vì phương thức truyền dẫn là
SUPPORTS, như vậy là phương thức này thực sự dùng
giao tác cục bộ (của cơ sở dữ liệu). Cờ chỉ đọc chỉ được áp dụng nếu một
giao tác được khởi động. Trong trường hợp này, không có giao tác nào thực
hiện nên cờ chỉ đọc bị bỏ qua.
Được thôi, nếu đúng là như thế thì chú giải
@Transactional sẽ có tác dụng gì trong liệt kê 6 khi cờ chỉ
đọc có giá trị true và phương thức truyền dẫn là
REQUIRED?
Liệt kê 6. Sử dụng cờ chỉ đọc với phương thức truyền dẫn
REQUIRED của — JDBC
@Transactional(readOnly = true, propagation=Propagation.REQUIRED) public long insertTrade(TradeData trade) throws Exception { //JDBC code... }
Khi chạy, phương thức
insertTrade() trong liệt
kê 6 sẽ làm gì:
- Đưa ra một lỗi ngoại lệ cảnh báo kết nối chỉ đọc
- Chèn đúng đắn lệnh mua bán và giao kết dữ liệu
- Không làm gì cả vì cờ chỉ đọc được thiết đặt giá trị
true
Câu hỏi rất dễ trả lời vì đã có các giải thích lúc trước. Câu trả lời chính
xác là A. Sẽ có một ngoại lệ được đưa ra, chỉ báo rằng bạn đang cố thực
hiện một thao tác cập nhật trên kết nối chỉ đọc. Vì một giao tác sẽ được
khởi động (
REQUIRED), kết nối này sẽ được thiết
đặt là chỉ đọc. Chắc chắn, khi bạn thử thực hiện câu lệnh SQL ấy, bạn sẽ
nhận được một ngoại lệ thông báo rằng kết nối là chỉ đọc.
Cái dở của cờ chỉ đọc là bạn cần khởi động một giao tác nó mới có tác dụng. Tại sao bạn cần một giao tác nếu như bạn chỉ đọc dữ liệu? Câu trả lời là bạn không cần. Việc khởi động một giao tác để thực thi hành động chỉ đọc thêm gánh nặng cho luồng xử lý và có thể gây ra khóa việc chia sẻ khi đọc dữ liệu trong cơ sở dữ liệu (phụ thuộc vào kiểu cơ sở dữ liệu mà bạn đang dùng và mức phân lập được thiết đặt). Điểm cốt yếu là cờ chỉ đọc là sẽ hơi vô nghĩa khi bạn dùng nó trong Java bền vững dựa trên JDBC và sinh thêm chi phí khi phải khởi tạo một giao tác không cần thiết.
Tình hình sẽ thế nào khi bạn dùng khung công tác dựa trên ORM? Vẫn với
những câu hỏi nhanh như trên, bạn có thể đoán kết quả của chú giải
@Transactional trong Liệt kê 7 là gì nếu phương
thức
insertTrade() được gọi khi sử dụng JPA với
Hibernate?
Liệt kê 7. Sử dụng cờ chỉ đọc với chế độ lan truyền là
REQUIRED của — JPA
@Transactional(readOnly = true, propagation=Propagation.REQUIRED) public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); }
Phương thức
insertTrade() trong Liệt kê 7
sẽ:
- Đưa ra một ngoại lệ cảnh báo kết nối chỉ đọc
- Chèn chính xác một lệnh mua bán và giao kết dữ liệu
- Không làm gì vì cờ
readOnlyđược thiết đặt là true
Câu trả lời có một chút lắt léo. Trong một số trường hợp thì câu trả lời là
C, nhưng trong hầu hết trường hợp (đặc biệt khi dùng JPA) thì câu trả lời
là B. Lệnh mua bán được chèn vào cơ sở dữ liệu mà không có lỗi. Chờ một tí
– ví dụ trước đó chỉ ra rằng sẽ có một lỗi kết nối chỉ đọc xảy ra khi chế
độ lan truyền là
REQUIRED. Điều này là đúng khi
bạn dùng JDBC. Tuy nhiên, khi bạn dùng khung công tác dựa trên ORM thì cờ
chỉ đọc sẽ làm việc khác một chút. Khi bạn sinh một khóa cho thao tác
chèn, khung công tác ORM sẽ tới cơ sở dữ liệu để lấy khóa và sau đó thực
hiện thao tác chèn. Với một vài nhà cung cấp sản phẩm, như Hibernate, chế
độ xả (mode flush) được đặt là
MANUAL và không
có thao tác chèn nào xảy ra đối với phép chèn mà không sinh khóa. Điều này
cũng đúng với các thao tác cập nhật. Tuy nhiên, các nhà cung cấp sản phẩm
khác, như TopLink, sẽ luôn thực thi phép chèn và cập nhật khi cờ chỉ đọc
được đặt là true. Mặc dù việc này là đặc thù đối với cả nhà cung cấp sản
phẩm lẫn phiên bản sản phẩm, điểm đáng nói ở đây là bạn không thể chắc
chắn rằng phép chèn hay cập nhật sẽ không xảy ra khi cờ chỉ đọc được thiết
lập, đặc biệt khi sử dụng JPA vì nó không biết nhà cung cấp sản phẩm là
ai.
Và những điều này đẩy tôi tới một cạm bẫy lớn khác mà tôi thường xuyên gặp.
Với tất cả những gì bạn đã đọc cho đến giờ, bạn cho rằng mã lệnh trong
Liệt kê 8 sẽ làm gì nếu bạn chỉ đặt cờ chỉ đọc trong chú giải
@Transactional?
Liệt kê 8. Sử dụng cờ chỉ đọc với — JPA
@Transactional(readOnly = true) public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
Phương thức
getTrade() trong Liệt kê 8 sẽ:
- Khởi động một giao tác, nhận một lệnh mua bán, sau đó hoàn tất giao tác
- Nhận một lệnh mua bán mà không khởi động một giao tác
Câu trả lời chính xác ở đây là A. Một giao tác sẽ được khởi tạo và hoàn
tất. Đừng quên rằng: chế độ lan truyền mặc định của chú giải
@Transactional là
REQUIRED. Điều đó có nghĩa là một giao tác được khởi động khi
thực tế nó không cần phải có (xem phần đừng bao giờ nói
không bao giờ). Tùy thuộc vào cơ sở dữ liệu mà ta đang dùng, điều
này có thể gây ra việc khóa chia sẻ một cách không cần thiết, kết quả là
có thể gây ra tình trạng khóa chết trong cơ sở dữ liệu. Thêm vào đó, thời
gian và tài nguyên dành cho việc xử lý không cần thiết bị lãng phí cho
việc khởi động và kết thúc một giao tác. Điểm cốt yếu là khi dùng khung
công tác dựa trên ORM, cờ chỉ đọc khá là vô dụng và trong hầu hết trường
hợp cờ này bị bỏ qua. Nhưng nếu bạn vẫn khăng khăng muốn dùng nó thì hãy
luôn đặt chế độ lan truyền là
SUPPORTS, như chỉ
ra trong Liệt kê 9, như vậy sẽ không có giao tác nào được khởi động:
Liệt kê 9. Dùng cờ chỉ đọc và chế độ lan truyền
SUPPORTS khi thực hiện thao tác select
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
Tốt hơn hết, hãy tránh hoàn toàn việc sử dụng chú giải
@Transactional khi thực hiện thao tác đọc, như chỉ ra trong
Liệt kê 10:
Liệt kê 10. Loại bỏ chú giải
@Transactional khi thực hiện thao tác select
public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
Những lỗi thường vấp đối với thuộc tính giao tác
REQUIRES_NEW
Dù bạn đang sử dụng khung công tác Spring hay EJB, việc dùng thuộc tính
giao tác
REQUIRES_NEW cũng mang lại hậu quả
tiêu cực và dẫn tới dữ liệu bị hỏng và không nhất quán. Thuộc tính
REQUIRES_NEW luôn khởi động một giao tác mới khi
thực hiện phương thức, dù đang có hay không có một giao tác khác. Nhiều
người lập trình dùng thuộc tính
REQUIRES_NEW
không chính xác, nghĩ rằng đó là cách đúng để đảm bảo chắc chắn khởi động
một giao tác. Xem hai phương thức sau đây trong Liệt kê 11:
Liệt kê 11. Sử dụng thuộc tính
REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRES_NEW) public long insertTrade(TradeData trade) throws Exception {...} @Transactional(propagation=Propagation.REQUIRES_NEW) public void updateAcct(TradeData trade) throws Exception {...}
Chú ý rằng trong Liệt kê 11 thì cả hai phương thức đều là công cộng
(public), tức là chúng có thể được gọi độc lập với nhau. Vấn đề xảy ra với
thuộc tính
REQUIRES_NEW là khi các phương thức
sử dụng nó được gọi trong cùng một đơn vị công việc logic thông qua giao
tiếp liên dịch vụ hoặc qua sự phối hợp. Ví dụ, giả sử trong Liệt kê 11 bạn
gọi phương thức
updateAcct() một cách độc lập
với các phương thức khác trong một vài ca sử dụng, nhưng cũng có trường
hợp trong đó phương thức
updateAcct() được gọi
trong phương thức
insertTrade(). Bây giờ nếu có
ngoại lệ xảy ra sau khi gọi phương thức
updateAcct(), lệnh mua bán sẽ bị hủy bỏ nhưng cập nhật tài
khoản sẽ vẫn được giao kết vào cơ sở dữ liệu, như ta thấy trong Liệt kê
12:
Liệt kê 12. Đa cập nhật sử dụng thuộc tính giao tác
REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRES_NEW) public long insertTrade(TradeData trade) throws Exception { em.persist(trade); updateAcct(trade); //exception occurs here! Trade rolled back but account update is not! ... }
Điều này xảy ra vì một giao tác mới được khởi động trong phương thức
updateAcct(), như vậy giao tác này sẽ hoàn tất
khi phương thức
updateAcct() kết thúc. Khi ta
dùng thuộc tính giao tác
REQUIRES_NEW, nếu đã
có một giao tác tồn tại rồi, thì giao tác hiện tại sẽ bị buộc tạm dừng và
một giao tác mới được khởi động. Khi phương thức kết thúc thì giao tác mới
sẽ được giao kết và giao tác ban đầu lại phục hồi.
Vì cách hoạt động như thế nên thuộc tính giao tác
REQUIRES_NEW chỉ nên dùng trong trường hợp hành động cơ sở dữ
liệu trong phương thức được gọi cần được ghi lưu vào cơ sở dữ liệu bất
chấp kết quả của giao tác phủ ngoài. Ví dụ, giả sử người ta cố gắng ghi
lại tất cả các giao dịch chứng khoán vào trong cơ sở dữ liệu kiểm toán.
Thông tin này cần được ghi lại bền vững bất kể giao dịch thất bại hay
không bởi các lý do như lỗi không hợp lệ, thiếu tiền hay những lý do khác.
Nếu ta không sử dụng thuộc tính
REQUIRES_NEW
trong phương thức kiểm toán, bản ghi kiểm toán sẽ bị cuộn lùi trở lại, gỡ
bỏ giao dịch định thực hiện. Dùng thuộc tính
REQUIRES_NEW đảm bảo rằng dữ liệu kiểm toán sẽ được ghi lưu
bất chấp kết quả của giao tác khởi tạo. Điểm chính ở đây là ta luôn sử
dụng hoặc là thuộc tính
MANDATORY hoặc là thuộc
tính
REQUIRED thay cho
REQUIRES_NEW trừ phi bạn có lý do gì đó để dùng nó tương tự
như trong ví dụ kiểm toán đã nêu.
Những cái bẫy do cuộn lùi giao tác
Tôi để lại trình bày cuối cùng cái bẫy giao tác phổ biến nhất. Thật không may, tôi lại thấy nó xuất hiện nhiều hơn trong các mã lệnh chạy sản xuất. Tôi sẽ bắt đầu với Spring Framework và sau đó chuyển sang EJB 3.
Cho đến giờ, mã lệnh mà chúng ta đã xem xét trông giống như trong Liệt kê 13:
Liệt kê 13. Không hỗ trợ cuộn lùi lại
@Transactional(propagation=Propagation.REQUIRED) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Giả sử số dư tài khoản không đủ tiền để mua chứng khoán đang nói đến hoặc
còn chưa được thiết lập để mua bán chứng khoán và chương trình đưa ra một
ngoại lệ đã kiểm tra (checked exception) (ví dụ,
FundsNotAvailableException). Lệnh mua bán này có được tiếp tục
ghi lưu trong cơ sở dữ liệu hay không hay toàn bộ đơn vị công việc logic
bị cuộn lùi lại để hủy bỏ? Câu trả lời, thật đáng ngạc nhiên, là với ngoại
lệ kiểm tra đó (cả trong Spring hay trong EJB), thì giao tác sẽ giao kết
bất cứ công việc nào còn chưa được giao kết. Nhìn vào Đoạn mã lệnh 13, nếu
một ngoại lệ đã kiểm tra xảy ra trong phương thức
updateAcct(), lệnh mua bán sẽ vẫn được ghi lưu bền vững, nhưng
tài khoản sẽ không được cập nhật tương ứng để phản ánh giao dịch mua bán
đó.
Có lẽ đây là vấn đề chính về tính toàn vẹn và nhất quán dữ liệu khi sử dụng các giao tác. Các ngoại lệ thời gian chạy (run-time) (tức là các ngoại lệ không kiểm tra được (unchecked exceptions) tự động bắt buộc toàn bộ đơn vị công việc logic phải cuộn lùi để hủy bỏ, nhưng các ngoại lệ đã kiểm tra (checked exceptions) thì không. Bởi vậy, mã lệnh trong Liệt kê 13 là vô ích trên quan điểm giao tác; mặc dù nó có vẻ là dùng các giao tác để duy trì tính nguyên tử và tính nhất quán, thực tế là nó không làm được.
Mặc dù kiểu hành xử này có vẻ lạ, các giao tác hành xử theo cách này là vì một số lý do thích đáng. Trước hết, không phải tất cả các ngoại lệ đã kiểm tra đều tệ; chúng có thể được dùng cho việc báo cáo sự kiện hoặc để chuyển hướng việc xử lý dựa trên những điều kiện nhất định. Nhưng hơn thế nữa, mã lệnh trình ứng dụng có thể đưa ra những hành động sửa chữa đối với một số dạng ngoại lệ đã kiểm tra, do đó cho phép giao tác này hoàn tất. Ví dụ, xét một kịch bản trong đó bạn đang viết chương trình cho một cửa hàng bán lẻ sách trực tuyến. Để hoàn thành một đơn hàng sách, bạn cần gửi một thư điện tử khẳng định lại như một phần của quá trình đặt hàng. Nếu máy chủ thư không hoạt động, bạn sẽ cần gửi một kiểu ngoại lệ đã kiểm tra SMTP chỉ ra rằng thông điệp không được gửi. Nếu ngoại lệ đã kiểm tra này tự động gây ra cuộn lùi thì toàn bộ đơn hàng mua sách sẽ bị hủy bỏ chỉ vì máy chủ thư không hoạt động. Bằng cách không tự động cuộn lùi khi các ngoại lệ đã kiểm tra, bạn có thể bắt được ngoại lệ này và thực hiện một số hành động sửa chữa (như gửi thông điệp thư điện tử đến hàng đợi chờ xử lý) và giao kết phần còn lại của đơn đặt hàng.
Khi bạn sử dụng mô hình giao tác khai báo (được mô tả chi tiết trong phần 2
của loạt bài này), bạn phải chỉ rõ thùng chứa hay khung công tác nên xử lý
các ngoại lệ đã kiểm tra ra sao. Trong Spring Framework bạn chỉ rõ điều
này thông qua tham số
rollbackFor trong chú
giải
@Transactional, như thấy trong Liệt kê
14.
Liệt kê 14. Bổ sung hỗ trợ cuộn lùi giao tác trong Spring
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Hãy lưu ý đến việc sử dụng tham số
rollbackFor
trong chú giải
@Transactional. Tham số này hoặc
là nhận chỉ một lớp ngoại lệ hoặc là nhận một mảng các lớp ngoại lệ, hoặc
bạn có thể dùng tham số
rollbackForClassName để
chỉ rõ tên của các ngoại lệ dưới dạng một xâu ký tự của Java. Bạn cũng có
thể sử dụng dạng phủ định của thuộc tính (
noRollbackFor) để chỉ rõ rằng tất cả các ngoại lệ đều bắt buộc
phải cuộn lùi ngoại trừ những ngoại lệ nhất định. Thường thì hầu hết những
người lập trình chọn giá trị
Exception.class,
điều này chỉ thị rằng tất cả các ngoại lệ trong phương thức này bắt buộc
phải cuộn lùi.
EJB lại hoạt động khác một chút với Spring Framework trong vấn đề cuộn lùi
một giao tác. Chú giải
@TransactionAttribute có
trong đặc tả của EJB 3.0 không bao gồm các chỉ thị để xác định hành vi hủy
bỏ. Hơn thế nữa, bạn phải dùng phương thức
SessionContext.setRollbackOnly() để đánh dấu giao tác phải
cuộn lùi để hủy bỏ, như minh họa trong Liệt kê 15:
Liệt kê 15. Thêm hỗ trợ cuộn lùi giao tác trong EJB
@TransactionAttribute(TransactionAttributeType.REQUIRED) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error sessionCtx.setRollbackOnly(); throw up; } }
Một khi phương thức
setRollbackOnly() đã được
gọi, bạn không thể thay đổi quyết định nữa; kết cục duy nhất có thể là
cuộn lùi giao tác khi đã hoàn tất phương thức khởi động giao tác này.
Chiến lược giao tác mô tả trong bài viết tiếp theo của loạt bài này sẽ
hướng dẫn khi nào và ở đâu cần cuộn lùi.
Kết luận
Mã lệnh dùng để thực hiện các giao tác trên nền Java không quá phức tạp; tuy nhiên, cách bạn dùng và cấu hình chúng có thể có chút rắc rối. Nhiều cái bẫy có liên quan đến việc thực hiện các hỗ trợ giao tác trên nền Java (bao gồm một số cái bẫy nữa ít phổ biến hơn mà tôi không thảo luận ở đây). Vấn đề lớn nhất với đa số các cạm bẫy này là không có một cảnh báo biên dịch hay một lỗi khi đang chạy nào cho ta biết việc thực hiện giao tác là không chính xác. Hơn thế nữa, trái ngược với giả định phản ánh trong giai thoại "Muộn còn hơn không" ở đầu bài viết, việc thực hiện hỗ trợ giao tác không chỉ là lao động lập trình. Cần có một nỗ lực thiết kế rất đáng kể trong việc phát triển một chiến lược giao tác toàn diện. Những bài còn lại trong loạt bài Các chiến lược giao tác sẽ giúp hướng dẫn bạn về vấn đề thiết kế một chiến lược giao tác hiệu quả cho các ca sử dụng trong một phạm vi rộng từ những ứng dụng đơn giản cho đến ứng dụng xử lý giao tác hiệu năng cao.
Tài nguyên
Học tập
- Straight Through Processing for Financial Service Firms (Hal McIntyre, Summit Group Press, 2004): Tìm hiểu thêm về những nguyên nhân và chi phí của dữ liệu hỏng trong việc xử lý giao tác của các dịch vụ tài chính.
- Java Transaction Design Strategies (Mark Richards, C4Media Publishing, 2006): Cuốn sách này giới thiệu những thảo luận mức sâu hơn về các giao tác trên nền Java.
- Java Transaction Processing (Mark Little, Prentice Hall, 2004): Một nguồn tham khảo tốt về các giao tác.
- Chapter 9. Transaction management: Nhiều kiến thức hơn về xử lý giao tác trong Spring ở chương sách này trong tài liệu về Spring Framework 2.5.
- Enterprise JavaBeans 3.0 trang tìa nguyên: Bạn có thể tìm thấy tài liệu về đặc tả EJB 3.0 ở đây.
- Duyệt qua technology bookstore để kiếm những cuốn sách về chủ đề này và những chủ đề công nghệ khác.
- Có thể tìm được hàng trăm bài viết về mọi khía cạnh của lập trình Java.
Thảo luận
- Hãy xem developerWorks blogs và tham gia vào công đồng developerWorks community.
Bình luận
-
Vùng dữ liệu trên developerWorks
Khám phá các bài viết xoay quanh lĩnh vực dữ liệu, Quản lý hệ thống thông tin
-
Vùng mã nguồn mở trên developerWorks
Xem các bài viết về HTML, CSS, JavaScript,...
-
Điện toán đám mây
Tìm hiểu về điện toán đám mây

markdown:
Lý do chung nhất khi sử dụng các giao tác trong một ứng dụng là để duy trì tính toàn vẹn và nhất quán của dữ liệu ở mức cao. Nếu bạn không quan tâm đến chất lượng dữ liệu của mình, thì bạn cũng không cần quan tâm đến các giao tác. Sau hết, việc hỗ trợ giao tác trên nền Java có thể hủy hoại hiệu năng, sinh ra vấn đề về khóa và các vấn đề tương tranh trong cơ sở dữ liệu, và do vậy gây thêm phức tạp cho trình ứng dụng của bạn.
Nhưng những người phát triển lại không bận tâm đến những giao tác gây thiệt
hại cho mình như thế. Hầu hết các ứng dụng có liên quan đến kinh doanh đều
yêu cầu chất lượng dữ liệu ở mức cao. Chỉ riêng ngành kinh doanh đầu tư
tài chính đã mất mười tỉ đô la cho các hoạt động thương mại thất bại, mà
dữ liệu tồi là nguyên nhân thứ hai dẫn tới tình trạng này (xem
[Tài nguyên](#resources)). Mặc dù việc thiếu các hỗ trợ giao
tác chỉ là một tác nhân dẫn đến tình trạng dữ liệu tồi (vẫn là nguyên nhân
chính), một kết luận chắc chắn là hàng tỷ đô la đã bị lãng phí chỉ riêng
trong lĩnh vực kinh doanh đầu tư tài chính là hậu quả của việc thiếu hụt
hoặc không có các hỗ trợ giao tác.
Không biết gì về các hỗ trợ giao tác là nguyên nhân khác của vấn đề. Rất
thường xuyên tôi đã nghe những tuyên bố theo kiểu “chúng tôi không cần hỗ
trợ giao tác trong các trình ứng dụng của chúng tôi đâu, bởi vì chúng chả
bao giờ lỗi cả.” Đúng. Tôi đã từng chứng kiến một số trình ứng dụng trong
thực tế cực hiếm hoặc không bao giờ đưa ra các báo lỗi. Những trình ứng
dụng ấy trông cậy vào việc có mã lệnh viết rất tốt, có các thủ tục kiểm
tra dữ liệu hợp lệ được viết tốt và việc hỗ trợ kiểm soát mã và kiểm thử
đầy đủ để giảm chi phí thực thi và những phức tạp liên quan đến xử lý giao
tác. Vấn đề của cách suy nghĩ như thế là ở chỗ nó chỉ tính đến một đặc
trưng của hỗ trợ giao tác:
*tính nguyên tử *. Tính nguyên tử đảm bảo
rằng mọi cập nhật sẽ được xem như một đơn vị công việc duy nhất và, hoặc
là tất cả được giao kết hoặc là tất cả bị hủy bỏ. Nhưng sự hủy bỏ hoặc
phối hợp các cập nhật không phải là khía cạnh duy nhất của hỗ trợ giao
tác. Một khía cạnh khác, *sự phân lập*, sẽ đảm bảo rằng mỗi đơn vị
công việc được tách biệt khỏi các đơn vị khác. Nếu không có sự phân lập
giao tác thích hợp, các đơn vị công việc khác có thể truy nhập vào các cập
nhật được tạo ra bởi một đơn vị công việc đang chạy, mặc dù đơn vị này
chưa hoàn thành xong việc của mình. Và kết quả là các quyết định kinh
doanh có thể được đưa ra dựa trên dữ liệu chưa hoàn chỉnh, gây ra những
giao dịch kinh doanh thất bại hoặc những hậu quả tiêu cực.
Vậy thì khi đã biết rằng chi phí cao và ảnh hưởng xấu của dữ liệu tồi và các hiểu biết cơ bản về giao tác là quan trọng (và cần thiết), bạn cần sử dụng các giao tác và học cách giải quyết các vấn đề nảy sinh. Bạn gấp rút bổ sung hỗ trợ giao tác vào trình ứng dụng của mình. Và đây chính là chỗ mà các vấn đề thường nảy sinh. Các giao tác hình như thường không hoạt động như hứa hẹn trên nền Java. Bài viết này sẽ khảo sát tỉ mỉ lý do tại sao như thế. Cùng với sự trợ giúp của các đoạn mã ví dụ, tôi sẽ giới thiệu những cạm bẫy phổ biến trong giao tác mà tôi thường thấy và kinh nghiệm trong lĩnh vực này, hầu hết trường hợp là trong các môi trường sản xuất.
Mặc dù hầu hết các đoạn mã ví dụ trong bài viết này sử dụng khung công tác
Spring (Spring Framework) phiên bản 2.5, khái niệm giao tác là tương tự
như trong đặc tả EJB 3.0. Trong đa số các trường hợp, chỉ đơn giản là ta
thay thế lời chú giải
@Transactional của khung
công tác Spring bằng
@TransactionAttribute
trong đặc tả của EJB 3.0. Những chỗ mà hai bộ khung này khác nhau về khái
niệm và kỹ thuật, tôi sẽ đưa ra cả hai ví dụ mã nguồn của khung công tác
Spring và EJB 3.
## Những cạm bẫy trong giao tác cục bộ.
Cách tốt nhất để khởi đầu là bằng một kịch bản dễ nhất: việc sử dụng
*các
giao tác cục bộ*, cũng thường được gọi là *giao tác cơ sở dữ
liệu*. Thời kỳ đầu mới xuất hiện cơ sở dữ liệu bền vững (ví dụ
JDBC), chúng ta thường giao phó việc xử lý giao tác cho cơ sở dữ liệu. Rốt
cuộc thì đây có phải chính là cái mà cơ sở dữ liệu cần phải làm? Các giao
tác cục bộ làm việc tốt với các đơn vị công việc logic (LUW), tức là thực
hiện các câu lệnh đơn như chèn, cập nhật hoặc xóa. Ví dụ, xét đoạn mã lệnh
JDBC đơn giản trong Liệt kê 1, đoạn mã lệnh này thực hiện thao tác chèn
một lệnh mua bán chứng khoán vào bảng
TRADE:
##### Liệt kê 1. Thao tác chèn đơn giản vào một cơ sở dữ liệu sử dụng JDBC
@Stateless public class TradingServiceImpl implements TradingService { @Resource SessionContext ctx; @Resource(mappedName="java:jdbc/tradingDS") DataSource ds; public long insertTrade(TradeData trade) throws Exception { Connection dbConnection = ds.getConnection(); try { Statement sql = dbConnection.createStatement(); String stmt = "INSERT INTO TRADE (ACCT_ID, SIDE, SYMBOL, SHARES, PRICE, STATE)" + "VALUES (" + trade.getAcct() + "','" + trade.getAction() + "','" + trade.getSymbol() + "'," + trade.getShares() + "," + trade.getPrice() + ",'" + trade.getState() + "')"; sql.executeUpdate(stmt, Statement.RETURN_GENERATED_KEYS); ResultSet rs = sql.getGeneratedKeys(); if (rs.next()) { return rs.getBigDecimal(1).longValue(); } else { throw new Exception("Trade Order Insert Failed"); } } finally { if (dbConnection != null) dbConnection.close(); } } }
Đoạn mã lệnh JDBC trong Liệt kê 1 không có logic giao tác, nó một mực đưa
lệnh mua bán vào bảng
TRADE trong cơ sở dữ
liệu. Trong trường hợp này, cơ sở dữ liệu điều khiển logic giao tác.
Điều này là tốt và hợp lý đối với trường hợp chỉ có một hành động duy trì cơ sở dữ liệu trong đơn vị công việc lô gic (LUW). Nhưng giả sử rằng bạn cần cập nhật số dư tài khoản cùng thời điểm với việc bạn chèn một lệnh mua bán vào cơ sở dữ liệu, như ta thấy trong Liệt kê 2:
##### Liệt kê 2. Thực hiện nhiều cập nhật bảng trong cùng một phương thức
public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Trong trường hợp này, các phương thức
insertTrade() và
updateAcct() đã
dùng mã lệnh JDBC chuẩn mà không có các giao tác. Một khi phương thức
insertTrade() kết thúc, cơ sở dữ liệu sẽ
khẳng định (và giao kết (commit)) lệnh mua bán. Nếu phương thức
updateAcct() thất bại bởi bất cứ lý do gì, lệnh
mua bán này sẽ vẫn tồn tại trong bảng
TRADE khi
kết thúc phương thức placeTrade(), kết quả là dữ liệu không nhất quán
trong cơ sở dữ liệu. Nếu phương thức
placeTrade() sử dụng các giao tác, cả hai hoạt động này sẽ nằm
trong cùng một LUW và lệnh mua bán này sẽ bị hủy nếu việc cập nhật tài
khoản bị thất bại.
Với sự phổ biến rộng rãi của các khung công tác bền vững của Java như
Hibernate, TopLink và Java Persistence API (JPA) đang phát triển, chúng ta
hiếm khi viết thẳng các đoạn mã lệnh JDBC nữa. Phổ biến hơn là chúng ta
dùng các khung công tác ánh xạ quan hệ - đối tượng (ORM) mới hơn để làm
cho công việc dễ dàng hơn bằng cách thay thế tất cả các đoạn mã lệnh JDBC
khó chịu này bằng một vài lời gọi phương thức đơn giản. Ví dụ, để chèn một
lệnh mua bán từ ví dụ đoạn mã lệnh JDBC trong
[Liệt kê
1](#listing1), sử dụng khung công tác Spring với JPA, bạn sẽ ánh xạ đối tượng
TradeData vào bảng
TRADE và thay thế toàn bộ đoạn mã lệnh JDBC này bằng đoạn mã
lệnh JPA trong Liệt kê 3:
##### Liệt kê 3. Thao tác chèn đơn giản dùng JPA
public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } }
Lưu ý rằng trong Liệt kê 3 ta gọi phương thức
persist() trong
EntityManager để
chèn một lệnh mua bán. Đơn giản quá, đúng không? Không hẳn thế. Đoạn mã
lệnh này sẽ không chèn lệnh mua bán vào bảng
TRADE như ta mong muốn, cũng không sinh ra ngoại lệ. Nó chỉ
đơn giản là trả lại giá trị
0 như là khóa của
lệnh mua bán này mà chẳng biến đổi gì cơ sở dữ liệu cả. Đây là cạm bẫy chủ
yếu đầu tiên của xử lý giao tác:
* các khung công tác dựa trên nền ORM
yêu cầu phải có một giao tác để kích hoạt một quá trình đồng bộ hóa
giữa đối tượng nhớ sẵn (cache object) và cơ sở dữ liệu*. Chính là
thông qua việc giao kết một giao tác mà mã SQL sẽ được sinh ra và tác động
đến cơ sở dữ liệu với các hành động mong muốn (như chèn, cập nhật, xóa).
Không có một giao tác ở đây thì không thể kích hoạt một quá trình trên ORM
để sinh mã lệnh SQL và thực hiện các thay đổi, như vậy phương thức đơn
giản chỉ kết thúc– không có lỗi ngoại lệ, không có cập nhật. Nếu bạn đang
dùng khung công tác dựa trên ORM, bạn phải dùng sử dụng các giao tác. Bạn
không còn có thể dựa vào cơ sở dữ liệu để quản lý các kết nối và hoàn tất
công việc.
Những ví dụ đơn giản này biểu thị rõ ràng rằng giao tác là cần thiết để duy trì dữ liệu toàn vẹn và nhất quán. Nhưng đây mới chỉ là bề ngoài của những rắc rối và những cạm bẫy thường vấp phải khi thực thi các giao tác trên nền Java.
## Bẫy chú giải
@Transactionalcủa khung công tác Spring
Như vậy bạn đã kiểm thử mã lệnh trong
[Liệt kê 3](#listing3) và
khám phá ra rằng phương thức
persist() không
thực hiện khi thiếu giao tác. Kết quả là bạn thấy vài đường liên kết nhờ
một thao tác tìm kiếm đơn giản trên Internet và biết rằng với khung công
tác Spring, ta cần dùng chú giải
@Transactional. Bởi thế bạn thêm chú giải vào mã lệnh như trong
Liệt kê 4:
##### Liệt kê 4. Sử dụng chú giải
@Transactional
public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; @Transactional public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } }
Kiểm thử lại mã lệnh và bạn sẽ nhận thấy chương trình vẫn không hoạt động. Vấn đề là bạn phải thông báo với SpringFramework rằng bạn đang sử dụng các chú giải để quản lý giao tác. Trừ phi bạn đang thực hiện kiểm thử đơn vị toàn bộ, đôi khi cái bẫy này khá là khó tìm ra. Thông thường nó dẫn người phát triển đến chỗ chỉ đơn giản thêm vào các logic giao tác trong tệp cấu hình Spring mà không nghĩ tới các chú giải.
Khi sử dụng chú giải
@Transactional trong
Spring, ta phải thêm dòng mã sau vào tệp cấu hình Spring:
<tx:annotation-driven transaction-manager="transactionManager"/>
Thuộc tính
transaction-manager lưu giữ một tham
chiếu đến bean quản lý giao tác được định nghĩa trong tệp cấu hình Spring.
Dòng mã này báo cho Spring sử dụng chú giải
@Transaction khi áp dụng bộ chặn giao tác. Nếu không có đoạn
mã này, chú giải
@Transactional sẽ bị bỏ qua,
kết quả là không có giao tác nào được sử dụng trong mã lệnh.
Việc làm cho chú giải cơ sở
@Transactional có
tác dụng trong mã lệnh ở Liệt kê 4 chỉ là sự khởi đầu. Lưu ý rằng
[Liệt kê 4](#listing4) sử dụng chú giải
@Transactional mà không định rõ bất cứ tham số chú giải bổ
sung nào. Tôi nhận thấy nhiều người dùng chú giải
@Transactional mà không bỏ thời gian tìm hiểu đầy đủ xem nó
làm gì. Ví dụ, khi sử dụng chú giải @Transactional không tham số như ta đã
làm trong Liệt kê 4, chế độ lan truyền giao tác sẽ được thiết lập là gì?
Cờ báo chỉ đọc được đặt là gì? Mức phân lập giao tác được đặt là gì? Quan
trọng hơn, khi nào thì giao tác sẽ bị cuộn lùi trở lại? Hiểu chú giải giao
tác được sử dụng như thế nào là rất quan trọng để đảm bảo bạn có mức độ hỗ
trợ giao tác thích hợp trong trình ứng dụng của mình. Và đây là trả lời
những câu hỏi tôi vừa đặt ra: khi sử dụng chú giải
@Transactional không có bất kỳ tham số nào, chế độ lan truyền
được đặt là
REQUIRED, cờ báo chỉ đọc đặt là
false, mức phân lập giao tác đặt giá trị
mặc định của cơ sở dữ liệu (thường là
READ_COMMITTED), và giao tác sẽ không bị cuộn lùi trở lại khi
ngoại lệ đã được kiểm tra.
## Bẫy cờ chỉ đọc của chú giải
@Transactional
Một cạm bẫy phổ biến nhất mà tôi thường xuyên gặp là dùng sai cờ chỉ đọc
trong chú giải Spring
@Transactional. Ở đây có
một câu hỏi nhanh dành cho bạn: Khi dùng mã lệnh JDBC chuẩn của Java bền
vững, chú giải
@Transactional trong Liệt kê 5
thực hiện công việc gì khi cờ chỉ đọc được thiết lập giá trị
true và chế độ lan truyền đặt là
SUPPORTS?
##### Liệt kê 5. Sử dụng cờ chỉ đọc với chế độ lan truyền JDBC là
SUPPORTS.
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) public long insertTrade(TradeData trade) throws Exception { //JDBC Code... }
Khi thi hành phương thức
insertTrade() trong
Liệt kê 5, nó sẽ:
- Đưa ra lỗi ngoại lệ cảnh báo kết nối chỉ đọc.
- Chèn một cách chính xác lệnh mua bán và giao kết dữ liệu
- Không làm gì vì mức lan truyền đặt là
SUPPORTS
Bạn đầu hàng? Câu trả lời chính xác là B. Lệnh mua bán được chèn một cách
chính xác vào cơ sở dữ liệu, thậm chí cả khi cờ chỉ đọc được thiết lập giá
trị
true và lan truyền giao tác được đặt là
SUPPORTS. Nhưng tại sao lại có thể như thế?
Không có giao tác nào được khởi động vì phương thức truyền dẫn là
SUPPORTS, như vậy là phương thức này thực sự dùng
giao tác cục bộ (của cơ sở dữ liệu). Cờ chỉ đọc chỉ được áp dụng nếu một
giao tác được khởi động. Trong trường hợp này, không có giao tác nào thực
hiện nên cờ chỉ đọc bị bỏ qua.
Được thôi, nếu đúng là như thế thì chú giải
@Transactional sẽ có tác dụng gì trong liệt kê 6 khi cờ chỉ
đọc có giá trị true và phương thức truyền dẫn là
REQUIRED?
##### Liệt kê 6. Sử dụng cờ chỉ đọc với phương thức truyền dẫn
REQUIRED của — JDBC
@Transactional(readOnly = true, propagation=Propagation.REQUIRED) public long insertTrade(TradeData trade) throws Exception { //JDBC code... }
Khi chạy, phương thức
insertTrade() trong liệt
kê 6 sẽ làm gì:
- Đưa ra một lỗi ngoại lệ cảnh báo kết nối chỉ đọc
- Chèn đúng đắn lệnh mua bán và giao kết dữ liệu
- Không làm gì cả vì cờ chỉ đọc được thiết đặt giá trị
true
Câu hỏi rất dễ trả lời vì đã có các giải thích lúc trước. Câu trả lời chính
xác là A. Sẽ có một ngoại lệ được đưa ra, chỉ báo rằng bạn đang cố thực
hiện một thao tác cập nhật trên kết nối chỉ đọc. Vì một giao tác sẽ được
khởi động (
REQUIRED), kết nối này sẽ được thiết
đặt là chỉ đọc. Chắc chắn, khi bạn thử thực hiện câu lệnh SQL ấy, bạn sẽ
nhận được một ngoại lệ thông báo rằng kết nối là chỉ đọc.
Cái dở của cờ chỉ đọc là bạn cần khởi động một giao tác nó mới có tác dụng. Tại sao bạn cần một giao tác nếu như bạn chỉ đọc dữ liệu? Câu trả lời là bạn không cần. Việc khởi động một giao tác để thực thi hành động chỉ đọc thêm gánh nặng cho luồng xử lý và có thể gây ra khóa việc chia sẻ khi đọc dữ liệu trong cơ sở dữ liệu (phụ thuộc vào kiểu cơ sở dữ liệu mà bạn đang dùng và mức phân lập được thiết đặt). Điểm cốt yếu là cờ chỉ đọc là sẽ hơi vô nghĩa khi bạn dùng nó trong Java bền vững dựa trên JDBC và sinh thêm chi phí khi phải khởi tạo một giao tác không cần thiết.
Tình hình sẽ thế nào khi bạn dùng khung công tác dựa trên ORM? Vẫn với
những câu hỏi nhanh như trên, bạn có thể đoán kết quả của chú giải
@Transactional trong Liệt kê 7 là gì nếu phương
thức
insertTrade() được gọi khi sử dụng JPA với
Hibernate?
##### Liệt kê 7. Sử dụng cờ chỉ đọc với chế độ lan truyền là
REQUIRED của — JPA
@Transactional(readOnly = true, propagation=Propagation.REQUIRED) public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); }
Phương thức
insertTrade() trong Liệt kê 7
sẽ:
- Đưa ra một ngoại lệ cảnh báo kết nối chỉ đọc
- Chèn chính xác một lệnh mua bán và giao kết dữ liệu
- Không làm gì vì cờ
readOnlyđược thiết đặt là true
Câu trả lời có một chút lắt léo. Trong một số trường hợp thì câu trả lời là
C, nhưng trong hầu hết trường hợp (đặc biệt khi dùng JPA) thì câu trả lời
là B. Lệnh mua bán được chèn vào cơ sở dữ liệu mà không có lỗi. Chờ một tí
– ví dụ trước đó chỉ ra rằng sẽ có một lỗi kết nối chỉ đọc xảy ra khi chế
độ lan truyền là
REQUIRED. Điều này là đúng khi
bạn dùng JDBC. Tuy nhiên, khi bạn dùng khung công tác dựa trên ORM thì cờ
chỉ đọc sẽ làm việc khác một chút. Khi bạn sinh một khóa cho thao tác
chèn, khung công tác ORM sẽ tới cơ sở dữ liệu để lấy khóa và sau đó thực
hiện thao tác chèn. Với một vài nhà cung cấp sản phẩm, như Hibernate, chế
độ xả (mode flush) được đặt là
MANUAL và không
có thao tác chèn nào xảy ra đối với phép chèn mà không sinh khóa. Điều này
cũng đúng với các thao tác cập nhật. Tuy nhiên, các nhà cung cấp sản phẩm
khác, như TopLink, sẽ luôn thực thi phép chèn và cập nhật khi cờ chỉ đọc
được đặt là true. Mặc dù việc này là đặc thù đối với cả nhà cung cấp sản
phẩm lẫn phiên bản sản phẩm, điểm đáng nói ở đây là bạn không thể chắc
chắn rằng phép chèn hay cập nhật sẽ không xảy ra khi cờ chỉ đọc được thiết
lập, đặc biệt khi sử dụng JPA vì nó không biết nhà cung cấp sản phẩm là
ai.
Và những điều này đẩy tôi tới một cạm bẫy lớn khác mà tôi thường xuyên gặp.
Với tất cả những gì bạn đã đọc cho đến giờ, bạn cho rằng mã lệnh trong
Liệt kê 8 sẽ làm gì nếu bạn chỉ đặt cờ chỉ đọc trong chú giải
@Transactional?
##### Liệt kê 8. Sử dụng cờ chỉ đọc với — JPA
@Transactional(readOnly = true) public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
Phương thức
getTrade() trong Liệt kê 8 sẽ:
- Khởi động một giao tác, nhận một lệnh mua bán, sau đó hoàn tất giao tác
- Nhận một lệnh mua bán mà không khởi động một giao tác
Câu trả lời chính xác ở đây là A. Một giao tác sẽ được khởi tạo và hoàn
tất. Đừng quên rằng: chế độ lan truyền mặc định của chú giải
@Transactional là
REQUIRED. Điều đó có nghĩa là một giao tác được khởi động khi
thực tế nó không cần phải có (xem phần
[đừng bao giờ nói
không bao giờ](#never)). Tùy thuộc vào cơ sở dữ liệu mà ta đang dùng, điều
này có thể gây ra việc khóa chia sẻ một cách không cần thiết, kết quả là
có thể gây ra tình trạng khóa chết trong cơ sở dữ liệu. Thêm vào đó, thời
gian và tài nguyên dành cho việc xử lý không cần thiết bị lãng phí cho
việc khởi động và kết thúc một giao tác. Điểm cốt yếu là khi dùng khung
công tác dựa trên ORM, cờ chỉ đọc khá là vô dụng và trong hầu hết trường
hợp cờ này bị bỏ qua. Nhưng nếu bạn vẫn khăng khăng muốn dùng nó thì hãy
luôn đặt chế độ lan truyền là
SUPPORTS, như chỉ
ra trong Liệt kê 9, như vậy sẽ không có giao tác nào được khởi động:
##### Liệt kê 9. Dùng cờ chỉ đọc và chế độ lan truyền
SUPPORTS khi thực hiện thao tác select
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
Tốt hơn hết, hãy tránh hoàn toàn việc sử dụng chú giải
@Transactional khi thực hiện thao tác đọc, như chỉ ra trong
Liệt kê 10:
##### Liệt kê 10. Loại bỏ chú giải
@Transactional khi thực hiện thao tác select
public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); }
## Những lỗi thường vấp đối với thuộc tính giao tác
REQUIRES_NEW
Dù bạn đang sử dụng khung công tác Spring hay EJB, việc dùng thuộc tính
giao tác
REQUIRES_NEW cũng mang lại hậu quả
tiêu cực và dẫn tới dữ liệu bị hỏng và không nhất quán. Thuộc tính
REQUIRES_NEW luôn khởi động một giao tác mới khi
thực hiện phương thức, dù đang có hay không có một giao tác khác. Nhiều
người lập trình dùng thuộc tính
REQUIRES_NEW
không chính xác, nghĩ rằng đó là cách đúng để đảm bảo chắc chắn khởi động
một giao tác. Xem hai phương thức sau đây trong Liệt kê 11:
##### Liệt kê 11. Sử dụng thuộc tính
REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRES_NEW) public long insertTrade(TradeData trade) throws Exception {...} @Transactional(propagation=Propagation.REQUIRES_NEW) public void updateAcct(TradeData trade) throws Exception {...}
Chú ý rằng trong Liệt kê 11 thì cả hai phương thức đều là công cộng
(public), tức là chúng có thể được gọi độc lập với nhau. Vấn đề xảy ra với
thuộc tính
REQUIRES_NEW là khi các phương thức
sử dụng nó được gọi trong cùng một đơn vị công việc logic thông qua giao
tiếp liên dịch vụ hoặc qua sự phối hợp. Ví dụ, giả sử trong Liệt kê 11 bạn
gọi phương thức
updateAcct() một cách độc lập
với các phương thức khác trong một vài ca sử dụng, nhưng cũng có trường
hợp trong đó phương thức
updateAcct() được gọi
trong phương thức
insertTrade(). Bây giờ nếu có
ngoại lệ xảy ra sau khi gọi phương thức
updateAcct(), lệnh mua bán sẽ bị hủy bỏ nhưng cập nhật tài
khoản sẽ vẫn được giao kết vào cơ sở dữ liệu, như ta thấy trong Liệt kê
12:
##### Liệt kê 12. Đa cập nhật sử dụng thuộc tính giao tác
REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRES_NEW) public long insertTrade(TradeData trade) throws Exception { em.persist(trade); updateAcct(trade); //exception occurs here! Trade rolled back but account update is not! ... }
Điều này xảy ra vì một giao tác mới được khởi động trong phương thức
updateAcct(), như vậy giao tác này sẽ hoàn tất
khi phương thức
updateAcct() kết thúc. Khi ta
dùng thuộc tính giao tác
REQUIRES_NEW, nếu đã
có một giao tác tồn tại rồi, thì giao tác hiện tại sẽ bị buộc tạm dừng và
một giao tác mới được khởi động. Khi phương thức kết thúc thì giao tác mới
sẽ được giao kết và giao tác ban đầu lại phục hồi.
Vì cách hoạt động như thế nên thuộc tính giao tác
REQUIRES_NEW chỉ nên dùng trong trường hợp hành động cơ sở dữ
liệu trong phương thức được gọi cần được ghi lưu vào cơ sở dữ liệu bất
chấp kết quả của giao tác phủ ngoài. Ví dụ, giả sử người ta cố gắng ghi
lại tất cả các giao dịch chứng khoán vào trong cơ sở dữ liệu kiểm toán.
Thông tin này cần được ghi lại bền vững bất kể giao dịch thất bại hay
không bởi các lý do như lỗi không hợp lệ, thiếu tiền hay những lý do khác.
Nếu ta không sử dụng thuộc tính
REQUIRES_NEW
trong phương thức kiểm toán, bản ghi kiểm toán sẽ bị cuộn lùi trở lại, gỡ
bỏ giao dịch định thực hiện. Dùng thuộc tính
REQUIRES_NEW đảm bảo rằng dữ liệu kiểm toán sẽ được ghi lưu
bất chấp kết quả của giao tác khởi tạo. Điểm chính ở đây là ta luôn sử
dụng hoặc là thuộc tính
MANDATORY hoặc là thuộc
tính
REQUIRED thay cho
REQUIRES_NEW trừ phi bạn có lý do gì đó để dùng nó tương tự
như trong ví dụ kiểm toán đã nêu.
## Những cái bẫy do cuộn lùi giao tác
Tôi để lại trình bày cuối cùng cái bẫy giao tác phổ biến nhất. Thật không may, tôi lại thấy nó xuất hiện nhiều hơn trong các mã lệnh chạy sản xuất. Tôi sẽ bắt đầu với Spring Framework và sau đó chuyển sang EJB 3.
Cho đến giờ, mã lệnh mà chúng ta đã xem xét trông giống như trong Liệt kê 13:
##### Liệt kê 13. Không hỗ trợ cuộn lùi lại
@Transactional(propagation=Propagation.REQUIRED) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Giả sử số dư tài khoản không đủ tiền để mua chứng khoán đang nói đến hoặc
còn chưa được thiết lập để mua bán chứng khoán và chương trình đưa ra một
ngoại lệ đã kiểm tra (checked exception) (ví dụ,
FundsNotAvailableException). Lệnh mua bán này có được tiếp tục
ghi lưu trong cơ sở dữ liệu hay không hay toàn bộ đơn vị công việc logic
bị cuộn lùi lại để hủy bỏ? Câu trả lời, thật đáng ngạc nhiên, là với ngoại
lệ kiểm tra đó (cả trong Spring hay trong EJB), thì giao tác sẽ giao kết
bất cứ công việc nào còn chưa được giao kết. Nhìn vào Đoạn mã lệnh 13, nếu
một ngoại lệ đã kiểm tra xảy ra trong phương thức
updateAcct(), lệnh mua bán sẽ vẫn được ghi lưu bền vững, nhưng
tài khoản sẽ không được cập nhật tương ứng để phản ánh giao dịch mua bán
đó.
Có lẽ đây là vấn đề chính về tính toàn vẹn và nhất quán dữ liệu khi sử dụng các giao tác. Các ngoại lệ thời gian chạy (run-time) (tức là các ngoại lệ không kiểm tra được (unchecked exceptions) tự động bắt buộc toàn bộ đơn vị công việc logic phải cuộn lùi để hủy bỏ, nhưng các ngoại lệ đã kiểm tra (checked exceptions) thì không. Bởi vậy, mã lệnh trong Liệt kê 13 là vô ích trên quan điểm giao tác; mặc dù nó có vẻ là dùng các giao tác để duy trì tính nguyên tử và tính nhất quán, thực tế là nó không làm được.
Mặc dù kiểu hành xử này có vẻ lạ, các giao tác hành xử theo cách này là vì một số lý do thích đáng. Trước hết, không phải tất cả các ngoại lệ đã kiểm tra đều tệ; chúng có thể được dùng cho việc báo cáo sự kiện hoặc để chuyển hướng việc xử lý dựa trên những điều kiện nhất định. Nhưng hơn thế nữa, mã lệnh trình ứng dụng có thể đưa ra những hành động sửa chữa đối với một số dạng ngoại lệ đã kiểm tra, do đó cho phép giao tác này hoàn tất. Ví dụ, xét một kịch bản trong đó bạn đang viết chương trình cho một cửa hàng bán lẻ sách trực tuyến. Để hoàn thành một đơn hàng sách, bạn cần gửi một thư điện tử khẳng định lại như một phần của quá trình đặt hàng. Nếu máy chủ thư không hoạt động, bạn sẽ cần gửi một kiểu ngoại lệ đã kiểm tra SMTP chỉ ra rằng thông điệp không được gửi. Nếu ngoại lệ đã kiểm tra này tự động gây ra cuộn lùi thì toàn bộ đơn hàng mua sách sẽ bị hủy bỏ chỉ vì máy chủ thư không hoạt động. Bằng cách không tự động cuộn lùi khi các ngoại lệ đã kiểm tra, bạn có thể bắt được ngoại lệ này và thực hiện một số hành động sửa chữa (như gửi thông điệp thư điện tử đến hàng đợi chờ xử lý) và giao kết phần còn lại của đơn đặt hàng.
Khi bạn sử dụng mô hình giao tác khai báo (được mô tả chi tiết trong phần 2
của loạt bài này), bạn phải chỉ rõ thùng chứa hay khung công tác nên xử lý
các ngoại lệ đã kiểm tra ra sao. Trong Spring Framework bạn chỉ rõ điều
này thông qua tham số
rollbackFor trong chú
giải
@Transactional, như thấy trong Liệt kê
14.
##### Liệt kê 14. Bổ sung hỗ trợ cuộn lùi giao tác trong Spring
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } }
Hãy lưu ý đến việc sử dụng tham số
rollbackFor
trong chú giải
@Transactional. Tham số này hoặc
là nhận chỉ một lớp ngoại lệ hoặc là nhận một mảng các lớp ngoại lệ, hoặc
bạn có thể dùng tham số
rollbackForClassName để
chỉ rõ tên của các ngoại lệ dưới dạng một xâu ký tự của Java. Bạn cũng có
thể sử dụng dạng phủ định của thuộc tính (
noRollbackFor) để chỉ rõ rằng tất cả các ngoại lệ đều bắt buộc
phải cuộn lùi ngoại trừ những ngoại lệ nhất định. Thường thì hầu hết những
người lập trình chọn giá trị
Exception.class,
điều này chỉ thị rằng tất cả các ngoại lệ trong phương thức này bắt buộc
phải cuộn lùi.
EJB lại hoạt động khác một chút với Spring Framework trong vấn đề cuộn lùi
một giao tác. Chú giải
@TransactionAttribute có
trong đặc tả của EJB 3.0 không bao gồm các chỉ thị để xác định hành vi hủy
bỏ. Hơn thế nữa, bạn phải dùng phương thức
SessionContext.setRollbackOnly() để đánh dấu giao tác phải
cuộn lùi để hủy bỏ, như minh họa trong Liệt kê 15:
##### Liệt kê 15. Thêm hỗ trợ cuộn lùi giao tác trong EJB
@TransactionAttribute(TransactionAttributeType.REQUIRED) public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error sessionCtx.setRollbackOnly(); throw up; } }
Một khi phương thức
setRollbackOnly() đã được
gọi, bạn không thể thay đổi quyết định nữa; kết cục duy nhất có thể là
cuộn lùi giao tác khi đã hoàn tất phương thức khởi động giao tác này.
Chiến lược giao tác mô tả trong bài viết tiếp theo của loạt bài này sẽ
hướng dẫn khi nào và ở đâu cần cuộn lùi.
## Kết luận
Mã lệnh dùng để thực hiện các giao tác trên nền Java không quá phức tạp;
tuy nhiên, cách bạn dùng và cấu hình chúng có thể có chút rắc rối. Nhiều
cái bẫy có liên quan đến việc thực hiện các hỗ trợ giao tác trên nền Java
(bao gồm một số cái bẫy nữa ít phổ biến hơn mà tôi không thảo luận ở đây).
Vấn đề lớn nhất với đa số các cạm bẫy này là không có một cảnh báo biên
dịch hay một lỗi khi đang chạy nào cho ta biết việc thực hiện giao tác là
không chính xác. Hơn thế nữa, trái ngược với giả định phản ánh trong giai
thoại "
[Muộn còn hơn không](#anecdote)" ở đầu bài viết, việc
thực hiện hỗ trợ giao tác không chỉ là lao động lập trình. Cần có một nỗ
lực thiết kế rất đáng kể trong việc phát triển một chiến lược giao tác
toàn diện. Những bài còn lại trong loạt bài Các chiến lược giao tác sẽ
giúp hướng dẫn bạn về vấn đề thiết kế một chiến lược giao tác hiệu quả cho
các ca sử dụng trong một phạm vi rộng từ những ứng dụng đơn giản cho đến
ứng dụng xử lý giao tác hiệu năng cao.
## Tài nguyên
### Học tập
[(Hal McIntyre, Summit Group Press, 2004): Tìm hiểu thêm về những nguyên nhân và chi phí của dữ liệu hỏng trong việc xử lý giao tác của các dịch vụ tài chính.](http://www.amazon.com/Straight-Through-Processing-Financial-Services/dp/0966917855) *Straight Through Processing for Financial Service Firms* [(Mark Richards, C4Media Publishing, 2006): Cuốn sách này giới thiệu những thảo luận mức sâu hơn về các giao tác trên nền Java.](http://www.amazon.com/Java-Transaction-Design-Strategies-Richards/dp/1411695917) *Java Transaction Design Strategies* [(Mark Little, Prentice Hall, 2004): Một nguồn tham khảo tốt về các giao tác.](http://www.amazon.com/Java-Transaction-Processing-Implementation-Professional/dp/013035290X) *Java Transaction Processing* [Chapter 9. Transaction management](http://static.springframework.org/spring/docs/2.5.x/reference/transaction.html): Nhiều kiến thức hơn về xử lý giao tác trong Spring ở chương sách này trong tài liệu về Spring Framework 2.5. [Enterprise JavaBeans 3.0](http://java.sun.com/javaee/reference/)trang tìa nguyên: Bạn có thể tìm thấy tài liệu về đặc tả EJB 3.0 ở đây.
- Duyệt qua
[technology bookstore](http://www.ibm.com/developerworks/apps/SendTo?bookstore=safari&S_TACT=105AGY75)để kiếm những cuốn sách về chủ đề này và những chủ đề công nghệ khác. [Có thể tìm được hàng trăm bài viết về mọi khía cạnh của lập trình Java.](http://www.ibm.com/developerworks/java?S_TACT=105AGY75)
### Thảo luận
- Hãy xem
[developerWorks blogs](http://www.ibm.com/developerworks/blogs/?S_TACT=105AGY75)và tham gia vào công đồng [developerWorks community](http://www.ibm.com/developerworks/community?S_TACT=105AGY75).
## Bình luận
[Vùng dữ liệu trên developerWorks](http://www.ibm.com/developerworks/vn/views/data/libraryview.jsp)
Khám phá các bài viết xoay quanh lĩnh vực dữ liệu, Quản lý hệ thống thông tin
[Vùng mã nguồn mở trên developerWorks](http://www.ibm.com/developerworks/vn/views/opensource/libraryview.jsp)
Xem các bài viết về HTML, CSS, JavaScript,...
[Điện toán đám mây](http://www.ibm.com/developerworks/vn/views/cloud/libraryview.jsp)
Tìm hiểu về điện toán đám mây

Content-Type: text/html; charset=UTF-8

Content-Language: en-US

Kp-eeAlive: timeout=10, max=48


text:
News
hanoi-vi
86
dd.MM.yyyy
Turn on more accessible mode
Turn off more accessible mode
English
|
Tiếng Việt
PHÁI ĐOÀN NGOẠI GIAO ISRAEL
Đại sứ quán Israel tại Việt Nam
Chuyển tới nội dung
sơ đồ trang
Hanoi-Vi
Đại sứ quán
Đại sứ
Các tài liệu
Liên lạc với chúng tôi
Dịch vụ lãnh sự
Dịch vụ lãnh sự
Visa vào Israel
Ý kiến phản hồi
Dinh cong
Các phòng ban
MASHAV
Kinh tế & Thương mại
Văn hóa
Hoạt động từ thiện
Quan hệ song phương
Dự án hợp tác
Tin tức và sự kiện
Currently selected
Lịch sự kiện
About Israel
Spot lights on Israel
Culture
Economy
Education
Health & Social Services
History
Land
People
Science & Technology
State
The Middle East
Cảm nhận
Israeli Missions Around The World
Hanoi-Vi
Tin tức và sự kiện
Tin tức và sự kiện
Lịch sự kiện
Công cụ & Thông tin
Liên hệ
FAQs
Israel tại các nước
Rss
Các ấn phẩm
Tin tức và sự kiện
GovXContentSection
Hội thảo về du lịch Israel lần thứ nhất
04.12.2013
Đại sứ quán Israel tại Hà nội đã tổ chức buổi hội thảo về du lịch Israel đầu tiên tại Việt nam với chủ đề “Israel-the Unique destination”
Đọc thêm
Chú hề bác sỹ đầu tiên trên thế giới tới Việt Nam
25.11.2013
Dưới sự điều phối của Đại sứ quán Israel tại Việt Nam, trong suốt tuần cuối tháng 11 và tuần đầu tháng 12- David Barashi - "chú hề bác sỹ" đến từ Israel sẽ đồng hành với các bác sỹ, các ngh ...
Đọc thêm
Đầu bếp Israel dạy nấu ăn tại trường Hoa Sữa
24.11.2013
Chiều chủ nhật 24/11/2013, nhận lời mời của Đại sứ quán Israel tại Việt Nam, cô Mika Sharon, đầu bếp nổi tiếng người Israel sẽ tới dạy nấu ăn tình nguyện cho các học viên có hoàn cảnh đặc b ...
Đọc thêm
Thông báo quan trọng từ Phòng Lãnh Sự
31.10.2013
Thứ 6 ngày 1/11/2013: Phòng Lãnh sự chỉ tiếp khách sau 11h. Thứ 2 ngày 4/11/2013: Phòng Lãnh sự không tiếp khách
Đọc thêm
Bộ trưởng Bộ NN&PTNT Israel thăm Việt Nam
31.10.2013
Từ ngày 31/10 đến 4/11/2013, Ông Yair Shamir- Bộ trưởng bộ nông nghiệp và phát triển nông thôn(NN&PTNT) Israel sẽ tới thăm và làm việc chính thức tại Việt Nam
Đọc thêm
Trước
5
6
7
8
9
10
11
12
13
14
Sau
mfaFooter
Contact us
Site map

Cache-Control: private, max-age=0

X-MS-InvokeApp: 1; RequireReadOnly