2011-07-15 26 views
5

Câu hỏi này được dự định là phần mềm bất khả tri/nền tảng. Tôi chỉ tìm kiếm mã SQL chung.Cách tốt nhất để lấy cây của các đối tượng được lưu trữ trong RDBMS

xem xét như sau (rất đơn giản vì ví dụ của) bảng:

 
Table: Authors 
id | name 
1 | Tyson 
2 | Gordon 
3 | Tony 
etc 

Table: Books 
id | author | title 
1 | 1  | Tyson's First Book 
2 | 2  | Gordon's Book 
3 | 1  | Tyson's Second Book 
4 | 3  | Tony's Book 
etc 

Table: Stores 
id | name 
1 | Books Overflow 
2 | Books Exchange 
etc 

Table: Stores_Books 
id | store | book 
1 | 1  | 1 
2 | 2  | 4 
3 | 1  | 3 
4 | 2  | 2 

Như bạn thấy, có một mối quan hệ một-nhiều giữa Book s và Author s, và nhiều-to- nhiều mối quan hệ giữa Book s và Store s.

Câu hỏi một: Truy vấn tốt nhất để mong muốn tải một tác giả và sách của họ (và sách được bán) vào chương trình hướng đối tượng ở đâu mỗi hàng đại diện cho một đối tượng?

Câu hỏi hai: Truy vấn tốt nhất để mong muốn tải toàn bộ cây đối tượng vào một chương trình hướng đối tượng trong đó mỗi hàng đại diện cho một cá thể đối tượng là gì?

Cả hai trường hợp này đều dễ tưởng tượng khi tải chậm. Trong cả hai trường hợp, bạn sẽ tìm nạp tác giả với một truy vấn và sau đó ngay khi bạn cần sách của họ (và những cuốn sách nào bán sách), bạn sẽ sử dụng truy vấn khác để nhận thông tin đó.

Đang tải cách tốt nhất để thực hiện việc này hay tôi nên sử dụng tham gia và phân tích cú pháp kết quả khi tạo cây đối tượng (trong nỗ lực tải dữ liệu mong muốn)? Trong trường hợp này, kết quả đầu ra/đích tối ưu từ cơ sở dữ liệu để làm cho việc phân tích cú pháp đơn giản nhất có thể là bao nhiêu?

Theo như tôi có thể nói, với tải mong muốn, tôi sẽ cần phải quản lý một từ điển hoặc chỉ mục của một số loại của tất cả các đối tượng trong khi tôi đang phân tích dữ liệu. Đây có phải là trường hợp hoặc có cách nào tốt hơn không?

Trả lời

3

Đó là một câu hỏi khó trả lời. Tôi đã thực hiện điều này trước bằng cách viết một truy vấn trả về mọi thứ dưới dạng một bảng phẳng và sau đó lặp qua các kết quả, tạo ra các đối tượng hoặc các cấu trúc khi các cột có ý nghĩa nhất thay đổi. Tôi nghĩ rằng hoạt động tốt hơn nhiều cuộc gọi cơ sở dữ liệu bởi vì có rất nhiều chi phí liên quan đến mỗi cuộc gọi, mặc dù tùy thuộc vào việc có bao nhiêu thực thể nhỏ hơn đối với mỗi thực thể lớn có thể không tốt nhất.

Điều sau đây có thể áp dụng cho cả câu hỏi của bạn 1 và 2.

SELECT a.id, a.name, b.id, b.name FROM authors a LEFT JOIN books b ON a.id=b.author 

(mã giả, trong chương trình của bạn mà làm cho các cuộc gọi db)

while (%row=fetchrow) { 
    if ($row{a.id} != currentauthor.id) { 
     currentauthor.id=$row{a.id}; 
     currentauthor.name=$row{a.name}; 
     } 
    currentbook=new book($row{b.id, b.name}); 
    push currentauthor.booklist, currentbook; 
    } 

[sửa] Tôi chỉ nhận ra tôi không trả lời phần thứ hai của câu hỏi của bạn. Tùy thuộc vào kích thước của dữ liệu cho các cửa hàng và những gì tôi dự định làm với nó, tôi hoặc là

Trước khi lặp qua các cuốn sách/tác giả như trên, slurp toàn bộ bảng cửa hàng vào một cấu trúc trong chương trình của tôi, giống như cuốn sách/cấu trúc tác giả trên nhưng được lập chỉ mục bởi các StoreID, và sau đó làm một tra cứu trong cơ cấu mà mỗi khi tôi đọc một kỷ lục cuốn sách và lưu trữ một tham chiếu đến các cửa hàng bảng

hoặc, nếu có nhiều cửa hàng,

Tham gia vào lưu trữ trên các cuốn sách và có thêm một vòng lặp lồng nhau để thêm các đối tượng cửa hàng trong một phần của mã thêm một cuốn sách.

Đây là bài viết có liên quan trên Wikipedia: http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch

Tôi hy vọng điều đó sẽ hữu ích!

+0

Mã giả của bạn đã cho tôi ý tưởng về phạm vi biến cục bộ bout. Miễn là tôi yêu cầu cơ sở dữ liệu sắp xếp đầu ra dựa trên một tiêu chí đã biết (như tác giả và sau đó cuốn sách, như trong ví dụ của bạn) thì tôi không phải giữ một chỉ mục/từ điển cục bộ của đối tượng vì tôi chỉ có thể tham khảo " currentAuthor ". – KPthunder

+0

Vâng, đó là chính xác. Bạn có lẽ thậm chí không cần phải nói với cơ sở dữ liệu để sắp xếp các cột bởi a.id bởi vì nó sẽ trả về chúng theo thứ tự đó trừ khi bạn yêu cầu nó sắp xếp theo một cách khác. (Tôi không chắc cơ sở dữ liệu đảm bảo rằng hành vi đó, nhưng đó là những gì họ làm.) – ratsbane

+1

Đây là một câu hỏi tiếp theo. Còn nếu 'Book's và' Author's cũng rất nhiều (ngoài 'Book's và' Store ') thì sao? Sau đó tôi sẽ cần một chỉ mục/từ điển ứng dụng, phải không? – KPthunder

1

Dưới đây là một số T-SQL để giúp bạn bắt đầu:

1.

chọn a.name, b.title từ tác giả một gia Books b trên a.id = b.author

2.

chọn a.name, b.title, s.name từ tác giả một tham gia Books b trên a.id = b.author tham gia Stores_Books sb trên sb.book = b.id tham gia Cửa hàng s trên s.id = sb.store

2

Trong chương trình OO bạn không sử dụng SQL, thay vào đó bạn hãy để điều đó được thực hiện vô hình bằng cơ chế Persistence của bạn. Để giải thích:

Nếu bạn có một chương trình hướng đối tượng thì bạn muốn mô hình đối tượng tự nhiên đại diện cho các khái niệm của Tác giả, Sách và Cửa hàng. Sau đó bạn có một vấn đề "Object/Relational mapping". Bằng cách nào đó bạn muốn lấy dữ liệu từ cơ sở dữ liệu bằng cách sử dụng SQL và làm việc tự nhiên với các đối tượng của bạn.

Trong thế giới Java, chúng tôi làm điều đó với Java Persistence API (JPA). Bạn không thực sự viết SQL thay vì bạn chỉ "chú thích" lớp Java để nói "Lớp này tương ứng với Bảng đó, thuộc tính này cho cột đó", và sau đó thực hiện một số điều thú vị với JOIN và thực tế có thể chọn Lazy hoặc Eager tải vì nó có ý nghĩa.

Vì vậy, bạn có thể kết thúc với một lớp Author (Tôi đang làm cho các thuộc tính công cộng ở đây cho ngắn gọn, trong cuộc sống thực, chúng tôi có các thuộc tính riêng và getter và setter.

@Entity 
public Class Author { 
    public int id; 
    public String name; 
    // more in a minute 

lớp đó được chú thích như một thực thể và JPA tương ứng với các cột trong bảng tương ứng Các chú thích có nhiều khả năng hơn để bạn có thể chỉ định các ánh xạ giữa tên của các thuộc tính và cột không khớp chính xác; các ánh xạ như

PUBLISHED_AUTHOR => Author, 
    FULL_NAME => name 

Bây giờ những gì về JOINS và các mối quan hệ?Lớp tác giả có một bộ sưu tập của Sách

@Entity 
    public Class Author { 
    public int id; 
    public String name; 
    public List<Book> books; 

và lớp Book có một thuộc tính đó là nó là tác giả

@Entity 
    public Class Book { 
     public int id; 
     public String title 
     public Author author 

Lớp Giám đốc JPA Entity lấy về một thể hiện của sách sử dụng một phương pháp tìm (tôi' sẽ không đi vào chi tiết ở đây)

int primaryKey = 1; 
    Book aBook = em.find(primaryKey); // approximately 

Bây giờ mã của bạn có thể chỉ cần đi

aBook.author.name 

Bạn không bao giờ thấy thực tế là SQL được sử dụng để tìm nạp dữ liệu cho Sách và vào thời điểm bạn yêu cầu thuộc tính tác giả cũng tìm nạp dữ liệu tác giả. Một JOIN SQL có thể đã được sử dụng, bạn không cần phải biết. Bạn có thể kiểm soát việc tìm nạp có Eager hoặc Lazy bằng chú thích khác hay không.

Tương tự

int primaryKey = 2 
    Author author = em.find(primaryKey); 

    author.books.size() ; // how many books did the author write? 

chúng ta có được một danh sách tất cả những cuốn sách cũng như các tác giả dữ liệu khác, SQL xảy ra, chúng tôi đã không nhìn thấy nó.

+0

Tôi biết về những người lập bản đồ quan hệ đối tượng chẳng hạn như Hibernate/JPA, nhưng tôi quan tâm nhiều hơn đến cách tốt nhất để làm việc háo hức tải từ đầu. – KPthunder

+0

+1 cho câu trả lời chi tiết ... công việc tốt! – tzup

+0

Giới thiệu tuyệt vời! Nhưng chú thích nào kiểm soát "cho dù tìm nạp là Eager hay Lazy"? Làm thế nào để sử dụng nó và nơi để xác định? Làm thế nào tôi có thể nhận được danh sách của tất cả các tác giả từ cơ sở dữ liệu để hiển thị chúng chúng ta hãy nói trong một JTree? Làm thế nào sau đó chỉ cần nhận được danh sách của tất cả các cửa hàng mà sách từ một tác giả nào đó được bán? Tôi thấy quá nhiều câu hỏi phía trước. – Dime

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