2008-12-18 26 views
7

Nếu tôi có đối tượng sao lưu biểu mẫu có cây đối tượng phức tạp - hãy nói một người có đối tượng Thông tin liên hệ có đối tượng Địa chỉ có một chuỗi các chuỗi - Có vẻ như đối tượng cần được điền đầy đủ với các đối tượng thành phần trước khi tôi có thể liên kết với nó. Vì vậy, nếu tôi đang tạo một Person mới, tôi cần đảm bảo rằng nó có tất cả các đối tượng thành phần được tạo ra từ dơi, và nếu tôi lấy một Person từ cơ sở dữ liệu, tôi cần đảm bảo rằng bất kỳ đối tượng nào không dân cư từ cơ sở dữ liệu nhận được dân cư với các đối tượng trống.Thực hành tốt nhất cho khởi tạo cây đối tượng mẫu Spring MVC

Câu hỏi đầu tiên, tất nhiên - tôi có đúng trong các giả định ở trên không? Có vẻ như nếu tôi cố gắng liên kết với person.contactInfo.homeAddress.street và không có ContactInfo, tôi nhận được một ngoại lệ con trỏ null.

Thứ hai, cách tốt nhất để khởi tạo đối tượng của tôi là gì. Tôi có thể nghĩ ra một vài cách tiếp cận. Một là khởi tạo tất cả các đối tượng thành viên khi khai báo:

public class Person { 
    String name; 
    ContactInfo contactInfo = new ContactInfo(); 
    //getters, setters, etc. 
} 

public class ContactInfo { 
    String phone; 
    Address homeAddress = new Address(); 
} 

v.v.

Cách tiếp cận khác là có một PersonFactory khởi tạo mọi thứ (hoặc để có phương thức Factory.getInstance khởi tạo mọi thứ).

Trong trường hợp truy xuất một người từ cơ sở dữ liệu, cách tiếp cận đầu tiên sẽ giải quyết vấn đề (tức là nếu người này không có địa chỉ trong cơ sở dữ liệu, đối tượng sẽ vẫn có địa chỉ), nhưng điều này sẽ có nghĩa là tạo ra từng đối tượng hai lần. Không chắc chắn làm thế nào để xử lý này nếu không, ngoại trừ để làm cho DAO rõ ràng cư trú tất cả mọi thứ ngay cả khi không có gì đã được lấy từ cơ sở dữ liệu. Hoặc để cung cấp cho nhà máy một phương pháp để đi qua đối tượng và "điền vào" bất cứ điều gì đó là mất tích.

Đề xuất?

+0

Có cách nào cung cấp phương pháp nhà máy cho hạt sao lưu mẫu không? – Antoniossss

Trả lời

4

Gọi nó quá mức cần thiết, nhưng những gì chúng tôi thực sự kết thúc là tạo một nhà máy chung sẽ lấy bất kỳ đối tượng nào và sử dụng sự phản chiếu (đệ quy) tìm tất cả các thuộc tính null và khởi tạo một đối tượng của kiểu đúng. Tôi đã làm điều này bằng cách sử dụng Apache Commons BeanUtils. Bằng cách này bạn có thể lấy một đối tượng mà bạn có thể nhận được từ nhiều nguồn khác nhau (DAO, deserialization từ XML, bất cứ điều gì), chuyển nó qua nhà máy này và sử dụng nó làm đối tượng sao lưu mà không lo lắng cần cho ràng buộc có thể là null. Phải thừa nhận rằng, điều này có nghĩa là các thuộc tính instantiating mà chúng ta có thể không cần cho một biểu mẫu cụ thể, nhưng trong trường hợp của chúng ta không thường áp dụng.

+0

chỉ vì tò mò: Để đạt được mục tiêu của bạn, bạn có sử dụng phương pháp BeanUtils.cloneBean không ??? Nếu không, liệu bạn có thể hiển thị như thế nào? –

+0

Không, tôi không sử dụng cloneBean. Tóm lại, tình huống có thể là, ví dụ, tôi có thể có một đối tượng Contact có thuộc tính Address là null. Tôi cần phải đặt một đối tượng Địa chỉ mới ở đó. Vì vậy, tôi sử dụng PropertyDescriptor.getPropertyType() để lấy lớp của thuộc tính, và sau đó sử dụng Class.getConstructor(). NewInstance() để khởi tạo nó. Sự phức tạp duy nhất là trong một số trường hợp, loại thuộc tính là một giao diện; trong những trường hợp đó, đối với ứng dụng tôi đã mô tả, tôi dựa vào quy ước đặt tên mà chúng tôi đã sử dụng cho các giao diện - nếu giao diện là IAddress, việc thực hiện là Địa chỉ. –

1

Tôi đoán bạn đang nói về một cái gì đó như < form:input path="person.contactInfo.homeAddress.street"/>? Không rõ ràng đối với tôi nhưng giả sử tôi là đúng :):

1) Có, Khi bạn viết person.contactInfo.homeAddress.street, đọc person.getContactInfo().getHomeAddress().getStreet(). Nếu các đối tượng ContactInfo hoặc HomeAddress hoặc Street là null, việc triệu gọi một trong các phương thức của chúng sẽ làm tăng NullPointException.

2) Tôi thường khởi tạo các đối tượng thành viên khi khai báo, giống như trong đoạn mã. Không thấy lợi ích của lớp nhà máy để thực hiện công việc nếu các giá trị khởi tạo là không điều kiện. Tôi không thấy rõ vấn đề nơi bạn buộc phải tạo một Người hai lần ... nhưng tôi có thể cảm thấy mệt mỏi;)

+0

Nếu tôi đang lấy nội dung từ cơ sở dữ liệu, thì việc khởi tạo tại khai báo sẽ tạo một ContactInfo, sau đó sẽ được thay thế bằng một ContactInfo khác được tạo bởi DAO với dữ liệu trong đó. Vì vậy, tôi sẽ tạo thêm một cái nữa. –

3

Tôi thường đảm bảo rằng các đối tượng được khởi tạo hoàn toàn - nó làm cho việc sử dụng đối tượng đơn giản hơn nhiều và tránh bạn phân tán kiểm tra null trong suốt mã của bạn. Trong trường hợp bạn đưa ra ở đây tôi có thể đặt khởi tạo trong getter để đối tượng con chỉ được khởi tạo khi nó thực sự sẽ được sử dụng, tức là: khi getter được gọi và sau đó chỉ nếu nó là null.

Về mặt tải từ cơ sở dữ liệu với mối quan hệ một-một, tôi thường làm việc tham gia và tải rất nhiều. Tác động hiệu suất thường là tối thiểu nhưng bạn nên biết rằng có thể có một.

Khi nói đến mối quan hệ một-nhiều, tôi thường đi tải chậm. Hibernate sẽ lấy cái này cho bạn, nhưng nếu bạn đang lăn của riêng bạn thì bạn chỉ cần thực hiện tùy chỉnh Danh sách gọi DAO thích hợp khi bất kỳ phương pháp nào liên quan đến nội dung của nó được gọi.

Một ngoại lệ đối với hành vi này với các mối quan hệ một-nhiều là khi bạn có danh sách các đối tượng cha mẹ mà bạn dự định lặp lại và cho từng phụ huynh bạn muốn lặp lại trên các con của nó. Rõ ràng hiệu suất sẽ hút bởi vì bạn sẽ thực hiện một cuộc gọi n + 1 đến DB khi bạn thực sự có thể thực hiện với 2 cuộc gọi.

+0

Cảm ơn. Tôi thích ý tưởng đặt khởi tạo trong getter; tốt nhất của cả hai thế giới đối với tôi. Tôi sẽ thử nó và đánh dấu điều này là "câu trả lời" nếu nó có vẻ đang hoạt động. Đối với bộ sưu tập tôi thích sử dụng LazyList từ Apache Commons. Nó cho phép bạn chỉ định một nhà máy. –

+2

Phụ lục cho điểm LazyList - nó chỉ ra rằng Spring có một danh sách lười biếng được gọi là AutoPopulatingList. –

1

Tôi đã đi theo phương thức Factory method (không phải là người hâm mộ sử dụng một lớp riêng biệt cho nó, với tôi nó có ý nghĩa hơn để có nó trong một phương thức tĩnh để tất cả ở cùng một nơi). Tôi có một cái gì đó như -

public static Person getInstanceForContactInfoForm() { 
     ContactInfo contactInfo = ContactInfo.getInstanceForContactInfoForm(); 

     Person person = new Person(contactInfo); 
     // set whatever other properties you need for Person 
     // just enough to 1-render the form and 2-avoid any exceptions 
     return person; 
} 

Nếu tôi đang tải người từ cơ sở dữ liệu, tôi có một phương thức trong lớp Person được gọi là "initalizeForContactInfoForm" hoặc gì đó. Sau khi tải Person từ cơ sở dữ liệu, tôi sẽ gọi phương thức này trong lớp Service trong phương thức được gọi bởi phương thức Spring MVC trả về Object Backing Form.

Tôi không nghĩ đây thực sự là một quy ước, nó chỉ là cách tiếp cận mà tôi tự nấu. Tôi không thực sự thấy bất kỳ hạn chế nào là như vậy nếu ai đó không đồng ý, hãy cho tôi biết ...

+0

Hạn chế đối với chúng tôi là chúng tôi thường xuyên sử dụng một ví dụ cụ thể làm đối tượng sao lưu biểu mẫu cho nhiều biểu mẫu. Ngoài ra, tất nhiên, điều này làm tăng chi phí của việc thêm một biểu mẫu mới hoặc thêm trường mới vào biểu mẫu - bây giờ bạn phải thay đổi đối tượng và DAO ngoài biểu mẫu. –

Các vấn đề liên quan