《Spring实战 第三版》五

《第5章 征服数据库》

几个概念
数据持久化

  • 将对象永久保存到数据库中
  • 可以减少访问数据库的次数

ORM

  • ORM(Object Relational Mapping),对象关系映射
  • 通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。
  • 本质上就是将数据从一种形式转换到另外一种形式
  • 是使用对象操作数据库的设计思想

JPA

  • JAP(Java Persistence API),Java持久化API
  • 是一套规范,应用于对象关系映射(ORM)
  • JPA仅为关系数据库管理系统提供持久化特性

Hibernate

  • 是Java的一个开源的对象关系映射(ORM)框架
  • 版本3.2及更高版本提供了JPA的实现

DAO

  • DAO(Data Access Object),数据访问对象
  • 为某种类型的数据库或其他持久性机制提供一个抽象接口的对象
  • 通过映射应用程序对持久层的调用,DAO提供一些特定的数据操作,而无需暴露数据库细节。

iBATIS

  • 于2010年6月16号被谷歌托管,改名为MyBatis
  • 是一个基于SQL映射支持Java和.NET的持久层框架
  • iBATIS提供的持久层框架包括SQL Maps和Data Access Object

Spring的数据访问哲学

DAO提供了数据读取和写入到数据库的一种方式
它以接口的方式发布功能
应用程序通过接口来进行数据访问

举个例子:假设DAO发布了一个接口,该接口声明了将对象存储到数据库的方法save
然后有一个用户服务类,它实现了该接口
那么,应用程序想要将对象存储到数据库,那么直接调用用户服务类save方法即可

OK,那么我们再回过头来看,用户服务类实际上是一个持久化的过程
因为是用户服务类实现了把对象存储到数据中,那么这个实现可以有多种选择
可以是JDBC,Hibernate、JPA或者其他任意的持久化框架

但我们在调用时只需要看接口声明的方法即可,不管它是怎么实现的
即便持久化的实现方式发生了改变,也不影响对save方法的调用
换句话说,DAO实际上是独立于持久化实现的
一言以蔽之,数据访问独立于持久化机制

1.Spring的数据访问异常体系

JDBC的SQLException表示在尝试访问数据库时出现了问题
但是这个异常却没有告诉你哪里出错了以及如何进行处理
一些持久化框架提供了相对丰富的异常体系,但它是某个框架所特有的

Spring JDBC提供的数据访问异常体系解决了以上两个问题
不同于JDBC,Spring提供了多个数据访问异常,分别描述了它们抛出时所对应的问题
而且它并没有与特定的持久化方式相关联

这些异常都是继承自DataAccessException
DataAccessException的特殊之处在于它是一个非检查性异常
即没有必要捕获Spring所抛出的数据访问异常

2.数据访问模板化

Spring将数据访问过程中固定的和可变的部分明确为两个不同的类:
模板(template)和回调(callback)

模板管理过程中固定的部分,而回调处理自定义的数据访问代码

配置数据源

Spring所支持的大多数持久化功能都依赖于数据源
Spring提供了在Spring上下文中配置数据源Bean的多种方式

  1. 提供JDBC驱动程序定义的数据源
  2. 通过JNDI查找的数据源
  3. 连接池的数据源
1.使用JNDI数据源

Spring应用程序经常部署在Java EE应用服务器中,如WebSphere,JBoss或者Tomcat
这时配置JNDI来获取数据源

利用Spring,我们可以像使用Spring Bean那样配置JNDI中数据源的引用并将其装配到需要的类中
位于jee命名空间下的<jee:jndi-lookup>元素可以用于检索JNDI的任何对象并将其用于Spring Bean中
如果应用程序的数据源配置在JNDi中,则可以使用<jee:jndi-lookup>元素并将其装配到Spring中

<jee:jndi-lookup id="dataSource" 
jndi-name="..."
resource-ref="true"/>

jndi-name用于指定JNDI中资源的名称

2.使用数据连接池

Spring本身没有提供数据源连接池的实现,
第三方Apache的DBCP是个不错的选择
需要导入commons-pool2-2.8.0.jar,commons-dbcp2-2.7.0.jar
DBCP包含了多个提供连接池功能的数据源,其中BasicDataSource是最常用的
使用mysql数据库,具体配置如下:

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/USR?serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

BasicDataSource是可以对连接池的属性进行配置的

3.基于JDBC驱动的数据源

在Spring中,通过JDBC驱动定义数据源是最简单的配置方式
Spring提供了两种数据源对象供选择

  1. DriverManagerDataSource:在每个连接请求时都会返回一个新建的链接
  2. SingleConnectionDataSource:在每次连接请求时都会返回同一个连接

使用JDBC驱动定义的数据源如下,使用的数据库为mysql:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/USR?serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

与之前的DHCP相比,差别不大,主要是数据源不一样
以及DriverManagerDataSource没有提供连接池功能

在Spring中使用JDBC

持久化技术有很多种,如Hibernate,MyBait和JPA等等
JDBC是最古老的一种方式:将Java对象保存到数据库中

JDBC其实还是很有竞争优势的:

  1. 不需要掌握其他框架的查询语言
  2. 可以更好地对数据访问的性能调优
  3. 允许用户使用数据库的所有特性
  4. 可以在更低层次上处理数据

如果直接使用JDBC所提供的直接操作数据库的API
那么就需要负责处理与数据库访问相关的所有事情
而且代码冗长,甚至复杂

Spring将数据访问的样板式代码提取到模板类中
Spring为JDBC提供了2个模板类共供使用:

  1. JdbcTemplate: 最基本的Spring JDBC模板
  2. NamedParameterJdbcTemplate: 可以将查询值以命令参数的形式绑定到SQL中
  3. SimpleJdbcTemplate:已不再使用,其功能已被前两个模板类覆盖

Spring的JDBC框架的例子,使用JdbcTemplate模板类
准备一个数据库的表:

CREATE TABLE t_user_main (
userId int(10) DEFAULT NULL COMMENT '用户id,作为主键',
userName varchar(50) DEFAULT NULL COMMENT '用户名',
age int(3) DEFAULT NULL COMMENT '年龄'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

定义一个User类,类的属性与数据库表中定义的列一一对应

public class User {
    private int ID;
    private String Name;
    private int age;
    /*所有属性的set和get方法*/
}

接着定义DAO的接口,假设该接口拥有两个功能

public interface UserDAO {
    //将对象存储到数据库
    void save(User user);
    //从数据库中读取数据
    List<User> getUser();
}

然后编写DAO接口的实现类,并在Spring的XML文件中对其定义

public class UserDAOImpl implements UserDAO{
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
    @Override
    //通过insert 语句来达到将对象保存到数据库的目的
    public void save(User user) {
        jdbcTemplate.update("insert into t_user_main(userID ,userName,age) values (?,?,?)",
                new Object[]{user.getID(),user.getName(),user.getAge()},
                new int[]{Types.INTEGER,Types.VARCHAR,Types.INTEGER});
    }
    @Override
    //通过select语句来达到读取数据的目的
    public List<User> getUser() {
        //RowMapper是执行查找操作的回调接口
        //通过实现该接口,可对其返回的结果集进行操作
        List<User> list = jdbcTemplate.query("select * from t_user_main", new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
                User user = new User();
                user.setID(resultSet.getInt("userID"));
                user.setName(resultSet.getString("userName"));
                user.setAge(resultSet.getInt("age"));
                return user;
            }
        });
        return list;
    }
}

然后将其在XML文件中进行定义

<bean id="user" class="UserDAOImpl">
    <property name="jdbcTemplate" ref="dataSource"/>
</bean>

如此就可以在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类
实现了DAO与持久化机制的独立性

在未引入NamedParameterJdbcTemplate模板之前
我们需要留意查询中参数的顺序,将值传递给update等方法时要保证正确的顺序
引入NamedParameterJdbcTemplate模板之后
参数的顺序就不重要了
命名参数可以赋予SQL中的每个参数一个明确的名字
在调用update等语句时就通过名字来引用参数

JDBC是访问关系型数据库的最基本方式
Spring的JDBC模板能够把我们从处理样板式代码的泥沼中解救出来
我们只需要关心实际的数据查询和更新即可

猜你喜欢

转载自www.cnblogs.com/ASE265/p/12459300.html