2011-09-07 21 views
13

Tôi gặp sự cố khi viết kiểm tra cho ứng dụng cơ sở dữ liệu bằng JPA2 và EclipseLink:Trường id của thực thể JPA có được xem xét bằng equals và hashCode không?

Tôi thêm một số thực thể vào cơ sở dữ liệu, truy xuất lại và muốn so sánh nó với một trường hợp có giá trị tôi mong đợi xác nhận việc bổ sung đã làm việc như tôi dự định.

Đầu tiên tôi đã viết một cái gì đó giống như

assertEquals(expResult, dbResult); 

mà thất bại, vì tôi có thể không thực sự biết giá trị của id lĩnh vực, được tạo ra bởi các cơ sở dữ liệu và do đó dbResult khác với expResult mà tôi tạo ra với new và được điền thủ công.

tôi thấy hai lựa chọn:

  • Hoặc là tôi loại bỏ các lĩnh vực id từ equalshashCode để so sánh chỉ dựa trên "giá trị thực". Tôi không biết nếu điều này gây ra vấn đề trong cơ sở dữ liệu hoặc ở nơi khác, mặc dù.

  • Hoặc tôi viết các bài kiểm tra để kiểm tra rõ ràng mọi trường ngoại trừ id theo cách thủ công.

Tôi nên làm gì?

Trả lời

14

Bạn có thể thấy rất nhiều tranh cãi về vấn đề này. Lập trường của tôi là bạn hoàn toàn không sử dụng khóa chính cơ sở dữ liệu cho bất kỳ thứ gì trong ứng dụng của bạn. Nó sẽ hoàn toàn vô hình. Xác định các đối tượng của bạn trong ứng dụng của bạn bằng một số thuộc tính khác hoặc kết hợp các thuộc tính.

Mặt trận "hoạt động kiên trì thử nghiệm", những gì bạn thực sự muốn có thể kiểm tra xem các trường đã được lưu và tải chính xác chưa và có thể khóa chính đã được chỉ định một số giá trị khi bạn lưu nó. Điều này có lẽ không phải là một công việc cho phương pháp equals ở tất cả.

+7

có thể tìm thấy rất nhiều tranh cãi? Đó là lạc quan. – digitaljoel

1

Tôi sẽ viết bài kiểm tra của mình để kiểm tra rõ ràng các trường. Để thực hiện điều này dễ dàng, trước khi thực hiện kiểm tra assertEqual, tôi sẽ đặt id của cả kết quả mong đợi và thực tế thành cùng một giá trị được xác định trước và sau đó sử dụng phương thức equals bình thường.

Xóa ID khỏi bằng không phải là chính đáng, chỉ vì thử nghiệm hơi khó. Bạn đang nói trên những lợi ích hiệu suất nghiêm trọng và mã toàn vẹn.

+0

Các vấn đề hiệu suất và tính toàn vẹn liên quan đến việc không xem xét id là gì? Việc kiểm tra một id cơ sở dữ liệu có giống với việc sử dụng 'Object # hashCode' trong các phương thức' equals' và 'hashCode' của tôi không? – soc

+0

Cho phép nói rằng bạn có các thực thể dự án. Bạn phải gửi một danh sách các dự án duy nhất từ ​​lớp dịch vụ của bạn. Bây giờ có một khả năng rằng một equals bị lỗi sẽ xem xét hai hồ sơ duy nhất như cùng một hồ sơ. Có ID làm giảm vấn đề này. Ngoài ra giải pháp không thể mở rộng, chúng tôi phải cập nhật phương thức equals của chúng tôi, nếu chúng tôi quyết định thay đổi những gì làm cho một đối tượng duy nhất. –

+0

Có một ID được đảm bảo là duy nhất là hoàn hảo cho băm. Chúng tôi được đảm bảo để tránh va chạm Hash. Nếu không, chất lượng băm trở thành một chức năng của việc liệu chúng ta có xem xét tất cả các thuộc tính nên là duy nhất và bỏ qua tất cả các thuộc tính không phải là. –

7

Từ sách Hibernate in Action, được khuyến nghị để xác định khóa doanh nghiệp và kiểm tra bình đẳng trên đó. Khóa doanh nghiệp là "thuộc tính hoặc một số kết hợp thuộc tính, đó là duy nhất cho mỗi cá thể có cùng một nhận dạng cơ sở dữ liệu." Trong các khu vực khác, nó nói không sử dụng id là một trong những thuộc tính đó và không sử dụng các giá trị trong các bộ sưu tập.

7

Dựa vào các id được tạo cơ sở dữ liệu trong việc triển khai equalshashCode không được khuyến khích. Bạn nên dựa vào các thuộc tính duy nhất/bán độc đáo của các lớp của bạn trong việc kiểm tra sự bình đẳng và tạo ra các giá trị hashcode. Các Hibernate documentation có một trang rộng lớn thảo luận về điều này, và các sự kiện trong đó được áp dụng cho nhiều hay ít mọi nhà cung cấp JPA.

Lý do cơ bản để sử dụng khóa kinh doanh trên các giá trị được tạo cơ sở dữ liệu trong việc thực hiện equalshashCode của bạn là nhà cung cấp JPA phải thực sự phát hành SELECT sau khi kiên trì thực thể trong cơ sở dữ liệu. Nếu bạn so sánh đối tượng bằng cách sử dụng cơ sở dữ liệu được tạo ra Ids, sau đó bạn sẽ kết thúc có một bài kiểm tra bình đẳng mà không thành công trong các tình huống sau:

  • Nếu E1E2 là các đơn vị của lớp E (xác minh bình đẳng sử dụng cơ sở dữ liệu được tạo ra Id) , sau đó nếu E1E2 sẽ bằng nhau nếu chúng chưa được lưu trữ trong cơ sở dữ liệu. Đây không phải là những gì bạn muốn, đặc biệt là nếu muốn lưu trữ E1E2 trong một số Set trước khi kiên trì. Điều này tệ hơn nếu các thuộc tính của E1E2 có các giá trị khác nhau; việc triển khai equals sẽ ngăn hai đối tượng khác nhau đáng kể được thêm vào Set và triển khai hashCode sẽ cung cấp cho bạn thời gian tra cứu O(n) khi thực thể được tra cứu từ HashMap bằng khóa chính.
  • Nếu E1 là một tổ chức quản lý mà đã tồn, và E2 là một thực thể mà không được vẫn kiên trì, sau đó kiểm tra bình đẳng sẽ xét thấy E1! = E2 trong kịch bản mà tất cả các giá trị thuộc tính của E1E2 (trừ cho các Id) là tương tự. Một lần nữa, điều này có lẽ không phải là những gì bạn muốn, đặc biệt là nếu bạn muốn tránh các thực thể trùng lặp trong cơ sở dữ liệu mà chỉ khác nhau trong các cơ sở dữ liệu của họ tạo ra các Id.

Việc triển khai equalshashCode do đó phải sử dụng khóa kinh doanh, để thể hiện hành vi nhất quán cho cả thực thể bền vững và không được chấp nhận.