我正在使用Spring支持的数据访问技术,我注意到它提到了多个选项,我不确定它们之间的区别:
据我所知,Spring JDBC提供了模板,用于减少用于通过简单的方式访问数据库的样板代码 - 您编写自己的SQL查询。
Spring-ORM提供了通过ORM技术访问数据库的简化模板,例如Hibernate,My(i)Batis等。
Spring-DAO按照Spring的网站:
Spring中的数据访问对象(DAO)支持旨在实现它 易于使用JDBC,Hibernate或JDO等数据访问技术 以一致的方式
我对ORM与JDBC有一点关系,因为它们针对的是访问数据库的不同方式。但Spring-DAO简直令人困惑!
有谁能请澄清这三者之间究竟有什么不同? 哪种情况应该首选?
此外,还有另一个项目Spring-DATA
也可用(http://projects.spring.io/spring-data/)现在,它是否是Spring支持的所有数据访问技术的父项目,或者它只是Spring的新名称 - DAO?
答案 0 :(得分:148)
以下是每项技术的介绍。
<强>弹簧-DAO 强>
Spring-DAO并不是一个严格意义上的弹簧模块,而是应该指示你编写DAO并写好它们的约定。因此,它既不提供接口,也不提供实现或模板来访问您的数据。编写DAO时,应使用@Repository
对它们进行注释,以便将与底层技术(JDBC,Hibernate,JPA等)链接的异常一致地转换为正确的DataAccessException
子类。
例如,假设您现在正在使用Hibernate,并且您的服务层捕获HibernateException
以便对其做出反应。如果更改为JPA,则DAO接口不应更改,服务层仍将使用捕获HibernateException
的块进行编译,但您永远不会输入这些块,因为您的DAO现在正在抛出JPA PersistenceException
。通过在DAO上使用@Repository
,链接到底层技术的异常将转换为Spring DataAccessException
;您的服务层捕获这些异常,如果您决定更改持久性技术,Spring仍然会抛出相同的Spring DataAccessExceptions
,因为Spring已经翻译了本机异常。
但请注意,由于以下原因,这限制了使用:
@Repository
注释DAO是一个好主意,因为扫描过程会自动添加bean。此外,Spring可能会为注释添加其他有用的功能。<强>弹簧-JDBC 强>
Spring-JDBC提供了JdbcTemplate类,它可以删除管道代码并帮助您专注于SQL查询和参数。您只需要使用DataSource
对其进行配置,然后就可以编写如下代码:
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还提供了一个JdbcDaoSupport,您可以扩展它以开发DAO。它基本上定义了两个属性:一个DataSource和一个JdbcTemplate,它们都可以用来实现DAO方法。它还提供了从SQL异常到spring DataAccessExceptions的异常转换器。
如果您打算使用普通的jdbc,那么这就是您需要使用的模块。
<强>弹簧ORM 强>
Spring-ORM是一个涵盖许多持久性技术的伞形模块,即JPA,JDO,Hibernate和iBatis。对于这些技术中的每一种,Spring都提供了集成类,以便按照Spring的配置原则使用每种技术,并与Spring事务管理顺利集成。
对于每种技术,配置主要包括将DataSource
bean注入某种SessionFactory
或EntityManagerFactory
等bean。对于纯JDBC,不需要这样的集成类(除了JdbcTemplate),因为JDBC只依赖于数据源。
如果你打算使用像JPA或Hibernate这样的ORM,你不需要spring-jdbc,只需要这个模块。
<强>弹簧数据强>
Spring-Data是一个总体项目,它提供了一个通用API来定义如何以更通用的方式访问数据(DAO +注释),涵盖SQL和NOSQL数据源。
最初的想法是提供一种技术,以便开发人员以技术无关的方式为DAO(finder方法)和实体类编写接口,并且仅基于配置(DAO和实体上的注释+ spring)配置,无论是基于xml还是基于java),决定实现技术,无论是JPA(SQL)还是redis,hadoop等(NOSQL)。
如果您遵循spring为finder方法名称定义的命名约定,那么您甚至不需要为最简单的情况提供与finder方法相对应的查询字符串。对于其他情况,您必须在finder方法的注释中提供查询字符串。
加载应用程序上下文时,spring为DAO接口提供代理,其中包含与数据访问技术相关的所有样板代码,并调用已配置的查询。
Spring-Data专注于非SQL技术,但仍然为JPA(唯一的SQL技术)提供了一个模块。
下一步
知道这一切,你现在要决定要选择什么。这里的好消息是,您不需要为该技术做出明确的最终选择。这实际上就是Spring的所在:作为开发人员,您在编写代码时专注于业务,如果您做得好,更改底层技术就是实现或配置细节。
注意:交易管理
Spring提供了一个用于事务管理的API。如果您计划使用spring进行数据访问,那么您还应该使用spring进行事务管理,因为它们很好地集成在一起。对于spring支持的每种数据访问技术,都有一个匹配的事务管理器用于本地事务,或者如果需要分布式事务,则可以选择JTA。所有这些都实现了相同的API,因此(再一次)技术选择只是一个可以在不对业务代码产生进一步影响的情况下进行更改的配置。
注意:Spring文档
您提到的Spring文档的链接相当陈旧。以下是最新版本的文档(4.1.6,涵盖所有主题):
Spring-data不是Spring框架的一部分。有一个共同的模块,您应该首先阅读以习惯这些原则。文档可以在这里找到:
答案 1 :(得分:3)
Spring DAO ( D ata A ccess O bject):是一个提供抽象接口的对象JDBC实现框架,即Spring DAO是通用概念,用于访问JDBC和Hibernate,MyBatis,JPA,JDO,使用它的各个支持类。它通过定义@Repository
注释提供广义异常层次结构。此注释将SQL exception translation的Spring容器定义为SQLException
到Spring的数据访问策略 - 不可知DataAccessException
层次结构。
即。特定于平台的异常是捕获,然后作为Spring未经检查的数据访问异常之一重新抛出。
Spring JDBC :对于普通JDBC,我们使用此模块,该模块仅依赖于DataSource
和模板类,如JdbcTemplate
,NamedParameterJdbcTemplate
(包裹{{ 1}})和JdbcTemplate
用于减少交叉问题。
SimpleJdbcTemplate
并在Spring XML中:
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);
}
}
Spring JDBC还提供了<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
,JdbcDaoSupport
,NamedParameterJdbcDaoSupport
,它们是支持(即方便)扩展方式开发我们自己的DAO抽象接口,如下所示:
SimpleJdbcDaoSupport
并在Spring XML中:
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);
}
}
Spring ORM:对于ORM工具支持,例如Hibernate,JPA,MyBatis ......通过注入<bean id="employeeDAO" class="EmployeeDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
以及以下类和各自的DataSource
类,可以轻松集成Spring。
DaoSupport
for Hibernate SessionFactory
代表JPA,EntityManagerFactory
for MyBatis 答案 2 :(得分:0)
您可以创建SomeObjectDao
之类的界面,然后创建此界面的不同实现,例如JdbcSomeObjectDao
,HibernateSomeObjectDao
。然后在SomeObjectService
类中,您将在SomeObjectDao
接口上操作,并在其中注入一个具体实现。因此,SomeObjectDao
的每个实现都将隐藏细节,无论您使用JDBC还是ORM等。
通常是JDBC,ORM的不同实现会引发不同类型的异常。 Spring的 DAO支持可以将这些不同的,特定于技术的异常映射到常见的Spring DAO异常。所以你与实际的实现分离得更多。此外,Spring的 DAO支持提供了一组抽象的*DataSupport
类,这些类在DAO开发中更有帮助。因此,除了实现SomeObjectDao
接口之外,您还可以扩展Spring的*DataSupport
类之一。
答案 3 :(得分:0)
作为附加信息。我建议您使用Spring Data JPA。 使用注释,例如:@ Repository,@ Service。 我给你看一个例子:
@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);
}
其中CustomerEntitlementsProjection是Spring投影,与您的实体或DTO pojo链接;
@Projection(name = "customerEntitlementsProjection", types = { BbsExerul.class })
public interface CustomerEntitlementsProjection {
String getContractNumber();
String getExecutiveNumber();
答案 4 :(得分:0)