2013-03-05 50 views
10

Tôi đã quyết định thử và sử dụng mybatis cho một dự án mới. Tôi đã quen thuộc với SQL, và tôi đã có một số kinh nghiệm xấu với hibernate gần đây vì vậy tôi đang tìm kiếm một cách tiếp cận cấp thấp hơn để DAO.Lưu/Cập nhật bộ sưu tập với mybatis, thực hành phổ biến là gì?

Dường như khá đẹp, ngoại trừ một điều, và đó là xử lý các bộ sưu tập.

Tôi có hai POJO, nhóm và người dùng, nhiều người dùng. Tôi đã quyết định một triết lý thiết kế rằng một POJO có một bộ sưu tập chỉ nên cập nhật mối quan hệ M-M giữa các bảng khi được lưu. Vì vậy, ví dụ, khi tôi lưu một đối tượng nhóm có một bộ sưu tập người dùng, triết lý thiết kế ra lệnh cho người dùng đã được lưu, và tôi chỉ phải lưu nhóm và mối quan hệ group_user trong cơ sở dữ liệu.

như vậy, cho hàm saveGroup trong giao diện, tôi đã thực hiện lập bản đồ XML này cho mybatis:

<insert id="saveGroup" keyColumn="id" 
    parameterType="se.myapp.domain.Group"> 
    <choose> 
     <when test="id == null"> 
     INSERT INTO myapp_group (name, description) 
     VALUES 
     (#{username}, #{password}); 
     </when> 
     <otherwise> 
     UPDATE myapp_group set name=#{name}, description=#{description} 
     where id=#{id}; 
     </otherwise> 
    </choose> 

    <if test="users != null"> 
     create temporary table tmpnewgroups (group_id integer, user_id integer); 

     insert into tmpnewgroups (group_id, user_id) values (
     <foreach collection="users" item="user" open="" close="" separator="),()"> 
      #{id},#{user.id} 
     </foreach> 
     ); 

     insert into myapp_user_group(group_id, user_id) 
     select tmp.group_id, tmp.user_id 
     from tmpnewgroups tmp 
     left outer join myapp_user_group ug 
      on ug.group_id = tmp.group_id and ug.user_id = tmp.user_id 
     where ug.group_id is null; 

     delete from myapp_user_group 
     where group_id = #{id} and user_id not in (select user_id from tmpnewgroups); 
    </if> 

</insert> 

Công việc này không như mong đợi (chèn/cập nhật nhóm, tiết kiệm bộ sưu tập của người sử dụng như các mối quan hệ trong cơ sở dữ liệu). Nhưng tôi không thực sự cảm thấy rằng đây là thực hành tốt nhất. Ứng dụng được tạo ra để tôi có thể chuyển sang chế độ ngủ đông nếu cần, do đó, logic để lưu bộ sưu tập tốt nhất nên ở trong lớp cơ sở dữ liệu. Có một số "ma thuật" trong mybatis mà tôi không biết điều đó có thể sắp xếp các hoạt động như thế này không?

Bất kỳ suy nghĩ nào về cách cải thiện điều này? Hoặc tôi nên suy nghĩ lại về thiết kế ứng dụng và đưa việc xử lý các bộ sưu tập lên cao hơn trong mô hình?

+0

đã xảy ra sự cố khi sử dụng ' 'và' ' của nó để mô tả nhiều: nhiều mối quan hệ? – Gus

+0

Kết quả tốt cho việc thu thập dữ liệu, không lưu dữ liệu. Bắt một bộ sưu tập là không có vấn đề, nó tiết kiệm cho họ rằng tôi đã tìm thấy được cồng kềnh. – Dytut

+0

Bạn đã xem xét sử dụng [Trình tạo MyBatis] (https://code.google.com/p/mybatis/wiki/Generator) chưa? Nó sẽ tạo ra các hoạt động CRUD cơ bản để bạn tiết kiệm cho bạn một tấn SQL được mã hóa bằng tay để bạn chỉ phải viết các phép nối phức tạp hơn, v.v. Bạn có thể sử dụng mã được tạo trong DAO của bạn và di chuyển rất nhiều logic lựa chọn mà bạn có XML của bạn vào DAO. – clav

Trả lời

1

Phần thứ hai của hoạt động ánh xạ dữ liệu saveGroup của bạn thực sự là một lý do để suy nghĩ lại thiết kế ứng dụng của bạn. Kiên trì bộ sưu tập người dùng trong bộ nhớ của bạn vào một bảng tạm thời để so sánh nó với một bảng tạm thời để chèn và xóa các đồng bằng là một hoạt động khá nặng mà không cần thiết nếu chỉ có tên hoặc mô tả của nhóm cần cập nhật, tức là khi không có đồng bằng. Cho dù đây có phải là trường hợp có thể được quyết định bởi máy chủ cơ sở dữ liệu hay không, đó là giải pháp hiện tại của bạn hoặc ứng dụng cơ sở dữ liệu, ứng dụng của bạn.

Ngoài trường hợp nhóm và có thể người dùng cần chèn lần đầu, nếu bạn muốn ứng dụng của mình quyết định có cần cập nhật bảng liên kết hay không thì ứng dụng của bạn cần biết người dùng có hay không bộ sưu tập đã thay đổi kể từ khi nó được lấy ra từ cơ sở dữ liệu. Thật không may MyBatis sẽ không giúp ứng dụng của bạn làm điều đó.

Hãy xem, so với Hibernate MyBatis là không biết rõ các đối tượng của bạn và trạng thái mà chúng mang theo sau MyBatis đã thực hiện công việc của mình, đó là ánh xạ dữ liệu chứ không phải ánh xạ đối tượng. Hibernate có thể tự động phát hiện trạng thái bẩn của các đối tượng của bạn, MyBatis không thể, vì đây không bao giờ là một phần của mô tả công việc của nó. Vì vậy, bạn được để lại cho các thiết bị của riêng bạn.

Cách tiếp cận siêu đơn giản là lưu trữ mã băm của người dùng sau khi chọn và kiểm tra xem hashcode đã thay đổi hay chưa bằng cách sử dụng phương thức có tên là isUserDirty(). Bạn có thể chỉ cần kiểm tra điều kiện đó từ bên trong ánh xạ của mình bằng cách sử dụng <if test="isUserDirty">. Đây là khóa học không phải là một cách tiếp cận rất chung chung và phụ thuộc vào một hashCode() thực hiện phong nha. Hãy xem số answer của leonbloy cho một câu hỏi tương tự cho cách tiếp cận chung chung hơn. Tất nhiên điều này có thể vẫn còn một chút quá đơn giản là tốt, đặc biệt là kể từ khi chúng tôi đang nói chuyện với nhiều mối quan hệ. Cách tiếp cận nào là tốt nhất tất cả phụ thuộc vào trường hợp của bạn.

Bây giờ bạn nên biết phải làm gì. Chúc may mắn!

PS thay vì chèn và xóa đồng bằng, tôi sẽ khuyên bạn nên ghi đè đơn giản: xóa tất cả rồi chèn tất cả, trong giao dịch. Chiến lược bảng tạm thời của bạn là một chiến lược tối ưu hóa có thể thực sự không cải thiện hiệu suất của cơ sở dữ liệu của bạn ở tất cả, trên thực tế tôi đoán là nó có thể làm cho nó tồi tệ hơn. Nếu bạn đã lược tả chính xác chiến lược này và biết bạn đang làm gì, bạn có thể bỏ qua bản đăng này.