Spring DAO vs Spring ORM vs Spring JDBC


103

Tôi đã xem qua các công nghệ truy cập dữ liệu được hỗ trợ bởi Spring và tôi nhận thấy rằng nó đề cập đến nhiều tùy chọn và tôi không chắc về sự khác biệt giữa chúng:

Theo tôi hiểu, Spring JDBC cung cấp các mẫu để giảm mã soạn sẵn để truy cập cơ sở dữ liệu theo cách cũ - bạn viết các truy vấn SQL của riêng mình.

Spring-ORM cung cấp các mẫu đơn giản để truy cập cơ sở dữ liệu thông qua các công nghệ ORM, chẳng hạn như Hibernate, My (i) Batis, v.v.

Spring-DAO theo trang web của Spring:

Hỗ trợ Đối tượng Truy cập Dữ liệu (DAO) trong Spring nhằm mục đích giúp bạn dễ dàng làm việc với các công nghệ truy cập dữ liệu như JDBC, Hibernate hoặc JDO một cách nhất quán

Tôi nói rõ một chút về ORM và JDBC vì chúng nhắm đến các cách khác nhau để truy cập vào DB. Nhưng Spring-DAO chỉ đơn giản là khó hiểu!

Bất cứ ai có thể vui lòng làm rõ sự khác biệt chính xác giữa ba điều này là gì? Cái nào nên được ưu tiên trong những tình huống nào?

Ngoài ra, có một dự án khác Spring-DATAcũng có sẵn ( http://projects.spring.io/spring-data/ ) Bây giờ, nó có phải là một dự án mẹ cho tất cả các công nghệ truy cập dữ liệu được hỗ trợ bởi Spring hay chỉ là một tên mới cho Spring -DAO?

Câu trả lời:


162

Đây là phần giới thiệu về từng công nghệ được đề cập.

Spring-DAO

Spring-DAO không phải là một mô-đun mùa xuân theo nghĩa chặt chẽ, mà là các quy ước sẽ quy định bạn viết DAO và viết chúng tốt. Do đó, nó không cung cấp giao diện, triển khai cũng như mẫu để truy cập dữ liệu của bạn. Khi viết DAO, bạn nên chú thích chúng @Repositoryđể các ngoại lệ được liên kết với công nghệ cơ bản (JDBC, Hibernate, JPA, v.v.) luôn được dịch sang DataAccessExceptionlớp con thích hợp .

Ví dụ: giả sử bạn hiện đang sử dụng Hibernate và lớp dịch vụ của bạn bắt kịp HibernateExceptionđể phản ứng với nó. Nếu bạn thay đổi thành JPA, các giao diện DAO của bạn sẽ không thay đổi và lớp dịch vụ sẽ vẫn biên dịch với các khối bắt HibernateException, nhưng bạn sẽ không bao giờ nhập các khối này vì các DAO của bạn hiện đang ném JPA PersistenceException. Bằng cách sử dụng @Repositorytrên DAO của bạn, các ngoại lệ được liên kết với công nghệ cơ bản được chuyển sang Spring DataAccessException; lớp dịch vụ của bạn nắm bắt được các ngoại lệ này và nếu bạn quyết định thay đổi công nghệ bền bỉ, thì Spring tương tự DataAccessExceptionssẽ vẫn được ném ra vì spring đã dịch các ngoại lệ gốc.

Tuy nhiên, lưu ý rằng điều này có giới hạn sử dụng vì những lý do sau:

  1. Thông thường, bạn không nên nắm bắt các trường hợp ngoại lệ liên tục, vì nhà cung cấp có thể đã lùi giao dịch (tùy thuộc vào loại ngoại lệ chính xác) và do đó bạn không nên tiếp tục thực hiện với một đường dẫn thay thế.
  2. Hệ thống phân cấp các trường hợp ngoại lệ thường phong phú hơn trong nhà cung cấp của bạn so với những gì Spring cung cấp và không có ánh xạ chính xác từ nhà cung cấp này sang nhà cung cấp kia. Dựa vào điều này là nguy hiểm. Tuy nhiên, đây là một ý tưởng hay để chú thích các DAO của bạn @Repository, vì các hạt đậu sẽ được tự động thêm vào bằng quy trình quét. Hơn nữa, Spring có thể thêm các tính năng hữu ích khác vào chú thích.

Spring-JDBC

Spring-JDBC cung cấp lớp JdbcTemplate, loại bỏ mã đường ống dẫn nước và giúp bạn tập trung vào truy vấn SQL và các tham số. Bạn chỉ cần cấu hình nó bằng một DataSource, và sau đó bạn có thể viết mã như sau:

int nbRows = jdbcTemplate.queryForObject("select count(1) from person", Integer.class);

Person p = jdbcTemplate.queryForObject("select first, last from person where id=?", 
             rs -> new Person(rs.getString(1), rs.getString(2)), 
             134561351656L);

Spring-JDBC cũng cung cấp JdbcDaoSupport mà bạn có thể mở rộng để phát triển DAO của mình. Về cơ bản, nó định nghĩa 2 thuộc tính: một DataSource và một JdbcTemplate mà cả hai đều có thể được sử dụng để triển khai các phương thức DAO. Nó cũng cung cấp một trình dịch ngoại lệ từ ngoại lệ SQL sang ngoại lệ DataAccessExceptions mùa xuân.

Nếu bạn định sử dụng jdbc thuần túy, đây là mô-đun bạn sẽ cần sử dụng.

Spring-ORM

Spring-ORM là một mô-đun ô bao gồm nhiều công nghệ bền bỉ, cụ thể là JPA, JDO, Hibernate và iBatis. Đối với mỗi công nghệ này, Spring cung cấp các lớp tích hợp để mỗi công nghệ có thể được sử dụng theo các nguyên tắc cấu hình của Spring và tích hợp trơn tru với quản lý giao dịch của Spring.

Đối với mỗi công nghệ, cấu hình về cơ bản bao gồm việc tiêm một DataSourcehạt đậu vào một số loại SessionFactoryhoặc EntityManagerFactoryvv. Đối với JDBC thuần túy, không cần các lớp tích hợp như vậy (ngoài JdbcTemplate), vì JDBC chỉ dựa vào DataSource.

Nếu bạn định sử dụng ORM như JPA hoặc Hibernate, bạn sẽ không cần spring-jdbc mà chỉ cần mô-đun này.

Spring-Data

Spring-Data là một dự án ô cung cấp một API chung để xác định cách truy cập dữ liệu (DAO + chú thích) theo cách chung chung hơn, bao gồm cả nguồn dữ liệu SQL và NOSQL.

Ý tưởng ban đầu là cung cấp một công nghệ để nhà phát triển viết giao diện cho DAO (các phương thức của công cụ tìm kiếm) và các lớp thực thể theo cách bất khả tri về công nghệ và chỉ dựa trên cấu hình (chú thích về DAO & các thực thể + cấu hình mùa xuân, có thể là xml- hoặc dựa trên java), quyết định công nghệ triển khai, có thể là JPA (SQL) hoặc redis, hadoop, v.v. (NOSQL).

Nếu bạn tuân theo các quy ước đặt tên được xác định bởi spring cho các tên phương thức công cụ tìm kiếm, bạn thậm chí không cần cung cấp các chuỗi truy vấn tương ứng với các phương thức công cụ tìm kiếm cho các trường hợp đơn giản nhất. Đối với các tình huống khác, bạn phải cung cấp chuỗi truy vấn bên trong các chú thích trên các phương thức của công cụ tìm.

Khi ngữ cảnh ứng dụng được tải, spring sẽ cung cấp proxy cho các giao diện DAO, chứa tất cả các mã soạn sẵn liên quan đến công nghệ truy cập dữ liệu và gọi các truy vấn đã định cấu hình.

Spring-Data tập trung vào các công nghệ không phải SQL, nhưng vẫn cung cấp một mô-đun cho JPA (công nghệ SQL duy nhất).

Cái gì tiếp theo

Biết tất cả những điều này, bây giờ bạn phải quyết định những gì để chọn. Tin tốt ở đây là bạn không cần phải đưa ra lựa chọn cuối cùng cho công nghệ. Đây thực sự là nơi Spring power cư trú: là một nhà phát triển, bạn tập trung vào công việc kinh doanh khi bạn viết mã và nếu bạn làm tốt, việc thay đổi công nghệ cơ bản là một chi tiết triển khai hoặc cấu hình.

  1. Xác định mô hình dữ liệu với các lớp POJO cho các thực thể và các phương thức get / set để đại diện cho các thuộc tính của thực thể và các mối quan hệ với các thực thể khác. Bạn chắc chắn sẽ cần chú thích các lớp và trường thực thể dựa trên công nghệ, nhưng hiện tại, POJO là đủ để bắt đầu. Bây giờ chỉ cần tập trung vào các yêu cầu kinh doanh.
  2. Xác định giao diện cho các DAO của bạn. 1 DAO bao gồm chính xác 1 thực thể, nhưng bạn chắc chắn sẽ không cần DAO cho từng thực thể đó, vì bạn có thể tải thêm các thực thể bằng cách điều hướng các mối quan hệ. Xác định các phương thức tìm kiếm tuân theo các quy ước đặt tên nghiêm ngặt.
  3. Dựa trên điều này, người khác có thể bắt đầu làm việc trên lớp dịch vụ, với các chế độ giả mạo cho DAO của bạn.
  4. Bạn tìm hiểu các công nghệ bền bỉ khác nhau (sql, no-sql) để tìm ra công nghệ phù hợp nhất với nhu cầu của mình và chọn một trong số chúng. Dựa trên điều này, bạn chú thích các thực thể và triển khai các DAO (hoặc để mùa xuân triển khai chúng cho bạn nếu bạn chọn sử dụng dữ liệu mùa xuân).
  5. Nếu các yêu cầu kinh doanh phát triển và công nghệ truy cập dữ liệu của bạn không đủ để hỗ trợ nó (giả sử bạn bắt đầu với JDBC và một vài thực thể, nhưng bây giờ cần một mô hình dữ liệu phong phú hơn và JPA là lựa chọn tốt hơn), bạn sẽ phải thay đổi cách triển khai trong số các DAO của bạn, thêm một vài chú thích trên các thực thể của bạn và thay đổi cấu hình mùa xuân (thêm định nghĩa EntityManagerFactory). Phần còn lại của mã doanh nghiệp của bạn sẽ không thấy các tác động khác từ thay đổi của bạn.

Lưu ý: Quản lý giao dịch

Spring cung cấp một API để quản lý giao dịch. Nếu bạn dự định sử dụng spring để truy cập dữ liệu, bạn cũng nên sử dụng spring để quản lý giao dịch, vì chúng tích hợp với nhau rất tốt. Đối với mỗi công nghệ truy cập dữ liệu được hỗ trợ bởi Spring, có một trình quản lý giao dịch phù hợp cho các giao dịch địa phương hoặc bạn có thể chọn JTA nếu bạn cần các giao dịch phân tán. Tất cả chúng đều triển khai cùng một API, do đó (một lần nữa) lựa chọn công nghệ chỉ là vấn đề cấu hình có thể được thay đổi mà không ảnh hưởng thêm đến mã doanh nghiệp.

Lưu ý: Tài liệu mùa xuân

Các liên kết đến tài liệu Spring mà bạn đã đề cập khá cũ. Đây là tài liệu của bản phát hành mới nhất (4.1.6, bao gồm tất cả các chủ đề):

Spring-data không phải là một phần của Spring framework. Có một mô-đun chung mà bạn nên đọc trước để làm quen với các nguyên tắc. Tài liệu có thể được tìm thấy tại đây:


Tôi đánh giá cao Câu trả lời này bằng cách sử dụng thuật ngữ "ô" trong một số mô tả ở đây (như Dữ liệu mùa xuân), xác định có các thành phần / mô-đun phụ bên trong (chứ không phải ô là miền cụ thể hơn). Và việc đề cập đến Dữ liệu mùa xuân rất hữu ích trong ngữ cảnh ở đây, mặc dù nó không được đề cập trong câu hỏi.
cellepo

Không spring-jdbccung cấp các công cụ hữu ích khác không được đề cập ở đây? Ví dụ, tôi thấy SimpleJdbcInsertrất rõ ràng và hữu ích cho cả việc chèn mục nhập đơn lẻ cũng như hàng loạt (tất nhiên là theo tỷ lệ hợp lý).
Nom1fan

3

Spring DAO ( D ata A ccess O bject): là một đối tượng cung cấp giao diện trừu tượng cho các khung triển khai JDBC tức là Spring DAO là khái niệm tổng quát để truy cập JDBC và Hibernate, MyBatis, JPA, JDO bằng cách sử dụng các lớp Hỗ trợ riêng lẻ. Và nó cung cấp hệ thống phân cấp ngoại lệ tổng quát bằng cách xác định @Repositorychú thích. Chú thích này xác định vùng chứa Spring để dịch ngoại lệ SQL từ SQLExceptionsang cấu trúc DataAccessExceptionphân cấp bất khả tri chiến lược truy cập dữ liệu của Spring .

tức là các ngoại lệ cụ thể của nền tảng là các lần bắt và sau đó ném lại như một trong các ngoại lệ truy cập dữ liệu chưa được kiểm tra của Spring.


Spring JDBC : Đối với JDBC thuần túy, chúng tôi sử dụng mô-đun này, mô-đun này chỉ phụ thuộc vào DataSourcevà các lớp Mẫu như JdbcTemplate, NamedParameterJdbcTemplate(kết thúc JdbcTemplate) và SimpleJdbcTemplateđể giảm các mối quan tâm về cắt ngang.

public class EmployeeDao {  
private JdbcTemplate jdbcTemplate;  

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {  
    this.jdbcTemplate = jdbcTemplate;  
}  

public int saveEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int updateEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int deleteEmployee(Employee e){  
       return jdbcTemplate.update(query);  
}  

}  

và trong Spring XML:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>

Mùa xuân JDBC cũng cung cấp JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, đó là hỗ trợ (ví dụ thuận tiện ) cách để mở rộng và phát triển của chúng ta DAO giao diện trừu tượng như sau:

public interface EmployeeDao {

    public void saveEmployee(Employee emp);
}

public class EmployeeDaoImpl extends JdbcDaoSupport implements EmployeeDao{

    @Override
    public void saveEmployee(Employee emp) {

        Object[] inputs = new Object[] {emp.getName(), emp.getSalary(), emp.getDept()};
        getJdbcTemplate().update(query, inputs);
    }
}

và trong XML mùa xuân:

<bean id="employeeDAO" class="EmployeeDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>

Spring ORM: Hỗ trợ các công cụ ORM như Hibernate, JPA, MyBatis ... dễ dàng tích hợp Spring bằng cách tiêm vào DataSourcecùng với các lớp sau và các DaoSupportlớp tương ứng .

  • SessionFactory cho Hibernate
  • EntityManagerFactory cho JPA,
  • SqlSessionFactory cho MyBatis

1

Spring-dao lib đã dừng ở phiên bản 2.0.8 (tháng 1 năm 2008). Các lớp học trong spring-dao được sao chép sang spring-tx. Vì vậy, nếu bạn cần một lớp mà bạn tìm thấy trong spring-dao, hãy thêm phụ thuộc vào spring-tx . ( Nguồn .)


0

Bạn có thể tạo giao diện như SomeObjectDaovà sau đó tạo ra hiện thực khác nhau của giao diện này như JdbcSomeObjectDao, HibernateSomeObjectDao. Sau đó, trong SomeObjectServicelớp của bạn, bạn sẽ thao tác trên SomeObjectDaogiao diện và đưa vào đó một trong các triển khai cụ thể. Vì vậy, mỗi triển khai của SomeObjectDaosẽ ẩn các chi tiết, cho dù bạn sử dụng JDBC hay ORM, v.v.

Thông thường JDBC và các triển khai khác nhau của ORM đưa ra các loại ngoại lệ khác nhau. Hỗ trợ DAO của Spring có thể ánh xạ các ngoại lệ công nghệ cụ thể khác nhau đó thành các ngoại lệ Spring DAO chung. Vì vậy, bạn được tách biệt nhiều hơn từ việc triển khai thực tế. Ngoài ra, hỗ trợ DAO của Spring cung cấp tập hợp các *DataSupportlớp trừu tượng giúp nhiều hơn nữa trong việc phát triển DAO. Vì vậy, bên cạnh việc triển khai SomeObjectDaogiao diện của mình , bạn có thể mở rộng một trong các *DataSupportlớp của Spring .


vậy ý ​​bạn là, spring-dao tóm tắt các ngoại lệ cụ thể cho Hibernate / JDO / JDBC và cung cấp một tập hợp các ngoại lệ tiêu chuẩn? Nó có bất kỳ templatesđể truy cập db? hay nó chỉ là một sự trừu tượng để được sử dụng với các thành phần lò xo khác? Ví dụ: có thể viết mã chỉ sử dụng spring-dao để truy cập db (mà không sử dụng spring-jdbc, spring-orm, hibernate hoặc bất kỳ khuôn khổ nào khác) không?
Pat

0

Như một thông tin bổ sung. Tôi khuyên bạn nên sử dụng Spring Data JPA. Sử dụng các chú thích như: @Repository, @Service. Tôi chỉ cho bạn một ví dụ:

@Repository("customerEntitlementsRepository")
public interface CustomerEntitlementsRepository extends CrudRepository<BbsExerul, BbsExerulPK> {

  @Query(value = "SELECT " + "CONTRACT_NUMBER, EXECUTIVE_NUMBER, " + "GROUP_VALUE, " + "CODE, "
      + "SUBCODE, " + "CURRENCY " + "FROM BBS_EXERUL " + "WHERE CONTRACT_NUMBER =:clientId AND "
      + "EXECUTIVE_NUMBER =:representativeId", nativeQuery = true)
  Collection<CustomerEntitlementsProjection> getFieldsExerul(@Param("clientId") String clientId,
      @Param("representativeId") String representativeId);

}

Trong đó CustomerEntitlementsProjection là Spring chiếu, được liên kết với bạn thực thể hoặc DTO pojo;

@Projection(name = "customerEntitlementsProjection", types = { BbsExerul.class })
public interface CustomerEntitlementsProjection {

  String getContractNumber();

  String getExecutiveNumber();

1
Vui lòng định dạng mã của bạn trong các khối mã để có thể đọc được.
Chắc chắnPerformance
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.