DAO

/ spring / 没有评论 / 376浏览

在软件开发中,最基本的功能,就是对数据库的操作。从代码编写的角度考虑,虽然不难实现,但是要考虑兼容不同数据源、不同的技术实现时,恐怕就不是那么容易设计了。于是出现了很多持久化技术,如Hibernate、MyBatis等。虽然它们彼此的实现方式不同,但spring对它们都提供了支持,并且spring对Java JDBC API进行了封装,简化了我们使用JDBC API的难度。spring为不同的持久化技术指定了统一的异常体系,这样做的好处就是使业务层和具体的持久化技术得到了解耦。

在spring中用于访问数据的对象叫做DAO(Data Access Object),定义这个对象的好处是只要我们定义好DAO接口后,并且使用具体的技术实现DAO接口,用户就可以很方便的实现不同持久化技术的切换。这样就达到了上述所说的使业务层和具体的持久化技术得到了解耦。如下图所示:

WX20170820-155054.png

spring为不同的持久化技术提供了统一的数据访问模板,这样做的目的是尽可能的简化整个数据访问的步骤。下面我们通到简单的代码来演示用JDBC访问数据库的步骤:

@Test
public void test() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = DriverManager.getConnection(""); // 创建连接
connection.setAutoCommit(false); // 设置事物
preparedStatement = connection.prepareStatement(""); // 相关SQL
preparedStatement.setLong(1, 1);
preparedStatement.execute();
connection.commit(); // 提交事物
} catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
try {
preparedStatement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

上述代码就是我们通过JDBC连接数据库的基本步骤:主要做了以下几个步骤:

  1. 准备连接
  2. 启动事物
  3. 执行SQL
  4. 提交/回滚
  5. 关闭资源

按照传统的编码方式,只要我们编写任何带事物的数据访问程序时,都需要重写上面的代码,而上述代码中只有部分是和业务相关的,大部分代码都是重复的,所以spring为了解决这个弊端,于是采用了模板设计模式,将这个相同的代码,放到模板类中,并将变化的部分提取出来,这样就解决了业务代码和其它代码放到一起的弊端了。具体的拆分如下:

WX20170820-162614.png

spring为不同的持久化技术都提供了相关的模板类,并且每个模板类中都提供了简化后的访问数据库的模板及回调,这样在我们使用时,就可以在回调中编写具体的数据库逻辑,而使用模板执行数据库操作。下面是spring为我们提供不同持久化技术的相关模板:

WX20170820-163452.png

我们在编写数据库相关业务时,可以直接使用上述的模板类。

不管使用哪种持久化技术,都必须要使用数据库连接,在spring中数据库连接是通过数据源获得的。在spring中配置数据源很方便,我们可以直接在spring的xml的文件中配置不同的数据源。

DBCP数据源

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" 
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/jilinwula"
p:username="root"
p:password="root" />

BasicDataSource提供了close()方法关闭数据源,所以需要设置destroy-method="close"属性,这样当spring容器关闭时,数据源能够正常关闭。除了上述属性外,BasicDataSource还提供了很多的属性,来帮助我们配置数据源,具体的配置如下:

WX20170820-172517.png

WX20170820-172604.png

WX20170820-172636.png

C3P0数据源

C3P0是一个开源的JDBC数据源项目,同样,我们也可以直接在spring的xml配置文件中配置。具体配置如下:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="oracle.jdbc.driver.OracleDrive"
p:jdbcUrl="jdbc:oracle:thin:@127.0.0.1:1521:jilinwula"
p:user="root"
p:password="root"/>

C3P0与DBCP数据源相比提供了更丰富的配置属性,通过这些属性,可以对数据源进行各种有效的控制。具体的配置如下:

我们在实际的开发中除了使用上述的数据源之外,还有一个数据源比较常用就是druid数据源,这个数据源是由阿里开源的,下面我们看一下druid数据源的具体配置:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!-- 基本属性 urluserpassword -->
<property name="url" value="${druid.url}" />
<property name="username" value="${druid.username}" />
<property name="password" value="${druid.password}" />

<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${druid.initialSize}" />
<property name="minIdle" value="${druid.minIdle}" />
<property name="maxActive" value="${druid.maxActive}" />

<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${druid.maxWait}" />

<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" />

<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" />

<property name="validationQuery" value="${druid.validationQuery}" />
<property name="testWhileIdle" value="${druid.testWhileIdle}" />
<property name="testOnBorrow" value="${druid.testOnBorrow}" />
<property name="testOnReturn" value="${druid.testOnReturn}" />
</bean>

在spring中除了使用上述的方式配置数据源外,还提供了一个简单的数据源实现类DriverManagerDataSource,该实现类虽然没有提供连接池,但我们依然可以用它获取数据库连接,DriverManagerDataSource常常用来执行单元测试,因为它不需要依赖额外的依赖类。下面我们看一下DriverManagerDataSource的具体使用:

@Test
public void test() throws SQLException {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/jilinwula");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("root");
Connection connection = driverManagerDataSource.getConnection();
System.out.println(connection);
}

上述就是spring中对各种持久化技术的支持。