Spring's support for the DAO

A, Spring concept of DAO

DAO (Data Access Object) is the object used to access the data, although in most cases the data stored in the database, but this is not the only option, you can also store data to a file or LDAP. DAO different end shield only data storage medium, and also shields the different specific implementation techniques.

Early, JDBC access to the database is the mainstream choice. In recent years, data persistence technology gained considerable development, Hibernate, MyBatis, JPA, JDO implementation techniques become splendor persistence put in dispute. As long as the data access DAO well defined interfaces, and the use of specific techniques to implement the functions of the interface DAO, it can be smoothly switched between different implementation techniques.

The figure is a typical application example of the DAO, define access to User data objects UserDao the interface method, the business layer UserDao operation data, and the use of specific persistence technology UserDao interface method, so that the service layer and the particular persistence technology to achieve decoupling.

DAO layer of abstraction may provide some benefit: First, you can easily construct mock objects, easy to carry unit testing; secondly, there will be more options when using the section, you can either use JDK dynamic proxy, you can use CGLib dynamic proxy.

Essentially Spring hope in a uniform way to integrate the underlying persistence technology, that is, in a uniform manner and call transaction management, avoid specific implementation intrusion into the code of business layer. Because each technology has its own persistence of abnormal system, so Spring provides a unified exception hierarchy, the impedance of different systems to eliminate abnormal, easy to define and implement specific technology-agnostic DAO interfaces, and integration into the same transaction management system.

 

Second, the consistent exception system

Consistent exception system is the key to the integration of different persistence technologies. Spring and provides a implementation technology-independent system for abnormal DAO layer semantics, by the converter and converts the different abnormal persistence technology into Spring abnormality.

1.Spring DAO exception system

In many orthodox API or framework, checked exceptions are excessive use, even when using the API, code is filled with a lot of boilerplate code. In many cases, in addition to recording the exception information in try / catch in the outside, and not much substantive work to do. Problems caused by abnormalities tend to be non-recoverable, such as data connection fails, syntax errors and other SQL statements. Forced captured checked exceptions in addition to restrict the freedom of developers, but anything worthwhile does not provide. Hence, Spring's exception hierarchy are built on the basis of abnormal runtime, developers can capture anomalies of interest as required.

The reason why a lot of JDK API difficult to use, a big reason is the proliferation of checked exceptions, such as JavaMail, EJB, JDBC and so on. These use the API, piles of exception handling distracting entering into a business code undermine the neat and elegant code.

Spring org.springframework.dao provide a comprehensive package of DAO exception elegant system, these anomalies are inherited DataAccessException, and in turn inherited DataAccessException NestedRuntimeException, NestedRuntimeException abnormal nested encapsulated source abnormality. Thus, although different persistence technology-specific exception has been converted into Spring DAO abnormal system, but the original exception information is not lost; as long as users are willing, you can easily obtain raw exceptions by getCause () method.

Spring DAO exception system and is not related to the specific implementation technology, which defines the directory tree from abnormal levels of DAO abstract concepts. In all persistence framework, and have not found such a rich semantic framework abnormal system. Spring is undoubtedly the originality of this design, which enables developers to focus on a specific abnormal becomes very easy to semantics. In the JDBC SQLException, the user must abnormality getErrorCode () or getSQLState, () takes an error code, and these codes is determined according to the cause of the error. This is too low-level API not only brought the difficulty of programming code, but also to make portable code becomes difficult because getErrorCode () method is related to the database.

Spring approach to the classification established abnormal categories, for most applications, this exception Categories with the appropriate granularity of abnormal type of division. In one aspect, so that developers departing from the underlying technical details as fine as acupuncture anesthesia; the other hand, the process of interest can be selected exception from this abnormal semantically rich system.

The following figure shows the first level of those abnormal system located in Spring DAO exception classes, may have a large number of sub-categories under each abnormal exception classes.

Spring DAO exception hierarchies class is very rich, just to name a subclass under DataAccessException exception classes. You can easily understand the semantic anomaly represented by the name of the exception class. Table simple description of these anomalies under the following pass.

To further refine the problem domain error, Spring of an exception class is a subclass of the subdivision, as it has more than 10 InvalidDataAccessResourceUsageException subclass, the following is one of two sub-classes, as shown in FIG.

For InvalidDataAccessResourceUsageException abnormal, persistence technology have different corresponding sub exception class. As BadSqlGrammarException the corresponding SQL statement syntax error JDBC technology to achieve abnormal, while the corresponding Hibemate HibernateQueryException implementation techniques query syntax exception.

Spring 的这个异常体系具有高度的可扩展性,当 Spring 需要对一种新的持久化技术提供支持时,只要为其定义一个对应的子异常就可以了,这种更改完全满足设计模式中的“开一闭原则”。

虽然 Spring 定义了如此丰富的异常类,但作为开发人员,仅需对感兴趣的异常进行处理即可。假设某个项目要求在发生乐观锁异常时,尝试再次获取乐观锁,而不是直接返回错误;那么,只需在代码中显式捕捉 ConcunencyFailureException 异常,然后在 catch 代码块中编写满足需求的逻辑即可。其他众多的异常则可以简单地交由框架自动处理,如发生运行期异常时自动回滚事务。

2.JDBC的异常转换器

传统的 JDBC API 在发生几乎所有的数据操作问题时都会抛出相同的 SQLException,它将异常的细节性信息封装在异常属性中。所以,如果希望了解异常的具体原因,则必须分析异常对象的信息。

SQLException 拥有两个代表异常具体原因的属性:错误码和 SQL 状态码。前者是数据库相关的,可通过 getErrorCode() 方法返回,其值的类型是 int;而后者是一个标准的错误代码,可通过 getSQLState() 方法返回,是一个 String 类型的值,由 5 个字符组成。

Spring 根据错误码和 SQL 状态码信息将 SQLException 译成 Spring DAO 的异常体系所对应的异常。在 org.springframework.jdbc.support 包中定义了 SQLExceptionTranslator 接口,该接口的两个实现类 SQLErrorCodeSQLExceptionTranslator 和 SQLStateSQLExceptionTranslator 分别负责处理 SQLException 中错误码和 SQL 状态码的翻译工作。将 SQLException 翻译成 SpringDAO 异常体系的工作是比较困难的,但 Spring 框架替我们完成了这项艰巨的工作并保证了转换的正确性,我们有充分的理由依赖这个转换的正确性。

3.其他持久化技术的异常转换器

由于各种框架级的持久化技术都拥有一个语义明确的异常体系,所以将这些异常转换为 Spring DAO 的体系相对轻松一些。下面将学习不同持久化技术的异常转换器。

Spring4.0 移除了对 Hibernate 低版本的支持,只支持 Hibernate3.6 之后的版本。另外,Spring4.0 移除了对 TopLink 的支持。在 org.springframework.orm 包中,分别为 Spring 所支持的 ORM 持久化技术定义了一个子包,在这些子包中提供相应 ORM 技术的整合类。Spring 为 各种 ORM 持久化技术所提供的异常转换器在下表说明。

这些工具类除了具有异常转换的功能,在进行事务管理时,还提供了从事务上下文中返回相同会话的功能。

Spring 也支持 MyBatis ORM 持久化技术,由于 MyBatis 抛出的异常是和 JDBC 相同的 SQLException 异常,所以直接采用和 JDBC 相同的异常转换器。

 

三、统一数据访问模板

到一个餐馆用餐,大抵会经历这样一个流程:进入餐馆-->迎宾小姐问候并引到适合的位置-->拿起菜单点菜-->用餐-->埋单-->离开餐馆。之所以我们喜欢时不时到餐馆用餐,就是因为我们只要点菜-->用餐-->埋单就可以了,幕后的烹饪制作、刷锅洗盘等工作完全不用关心,一切已经由餐馆服务人员按照服务流程按部就班、有条不紊地执行了。衡量一个餐馆服务质量好坏的一个重要标准是我们无须关心他们所负责的流程:不用催问菜为什么还没有上好(不但快而且服务态度佳),不用关心盘子为什么不干净(不但干净而且已经进行了消毒)。

从某种角度看,与其说餐馆为我们提供了服务,还不如说我们参与到餐馆的流程中:不管什么顾客点的菜都由相同的厨师烹制,不管什么顾客都按单付钱。在幕后,餐馆拥有一个服务模板,模板中定义的流程可以用于应付所有的顾客,只要为顾客提供几个专有需求(点的菜可不一样,座位可以自由选择),其他一切都按模板化的方式处理。

在直接使用具体的持久化技术时,大多需要处理整个流程,并没有享受餐馆用餐式的便捷。Spring 为支持的持久化技术分别提供了模板访问的方式,降低了使用各种持久化技术的难度,因此可以大幅度地提高开发效率。

1.使用模板和回调机制

下面是一段使用 JDBC 进行数据访问操作的简单代码,我们已经尽可能地简化了整个过程的处理,但以下步骤都是不可或缺的,如下面代码所示。

public void saveCustomer(Customer customer)throws Exception{
    Connection con = null;
    PreparedStatement stmt = null;
    try{
        //①获取资源
        con = getConnection();
        
        //②启动事务
        con.setAutoCommit(false);
    
        //③具体的数据访问操作和处理
        stmt = con.prepareStatment("insert into CUSTMOERS(ID,NAME) values(?,?)");
        stmt.setLong(1,customerId);
        stmt.setString(2,customer.getName());
        stmt.execute();
        ...
        stmt.execute();
        
        //④提交事务
        con.commit();
    
    }catch(Exception e){
        try{
            //⑤回滚事务
            con.rollback();
        }catch(SQLException sqlex){
            sqlex.printStackTrace(System.out);
        }
        throw e;
    }finally{
        //⑥释放资源
        try{
            stmt.close();
            con.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

如上述代码所示,JDBC 数据访问操作按以下流程进行:
(1)准备资源。
(2)启动事务。
(3)在事务中执行具体的数据访问操作。
(4)提交/回滚事务。
(5)关闭资源,处理异常。

按照传统的方式,在编写任何带事务的数据访问程序时,都需要重复编写上面的代码,而其中只有粗体部分所示的代码是业务相关的,其他代码都是在例行公事,因而导致大量八股文式的代码充斥着整个程序。

Spring 将这个相同的数据访问流程固化到模板类中,并将数据访问中固定和变化的部分分开,同时保证模板类是线程安全的,以便多个数据访问线程共享同一个模板实例。固定的部分在模板类中已经准备好,而变化的部分通过回调接口开放出来,用于定义具体数据访问和结果返回的操作。下图描述了模板类拆分固定和变化部分的逻辑。

这样,只要编写好回调接口,并调用模板类进行数据访问,就可以得到预想的结果:数据访问成功执行,前置和后置的样板化工作也按顺序正确执行,在提高开发效率的同时保证了资源使用的正确性,彻底消除了因忘记进行资源释放而引起的资源泄露问题。

2.Spring 为不同持久化技术所提供的模板类

Spring 为各种支持的持久化技术都提供了简化操作的模板和回调,在回调中编写具体的数据操作逻辑,使用模板执行数据操作,在 Spring 中,这是典型的数据操作模式。下面来了解一下 Spring 为不同的持久化技术所提供的模板类,如下表所示。

如果直接使用模板类,则一般需要在 DAO 中定义一个模板对象并提供数据资源。

Spring 为每种持久化技术都提供了支持类,支持类中已经完成了这样的功能。这样,只需扩展这些支持类,就可以直接编写实际的数据访问逻辑,因此更加方便。

不同持久化技术的支持类如下表所示。

这些支持类都继承于 dao.support.DaoSupport 类,DaoSupport 类实现了 ImtializingBean接口,在 afterPropertiesSet() 接口方法中检查模板对象和数据源是否被正确设置,否则将抛出异常。

所有的支持类都是 abstract 的,其目的是希望被继承使用,而非直接使用。

Guess you like

Origin www.cnblogs.com/jwen1994/p/11235210.html