spring学习(四)spring 持久层的封装
持久层:所谓“持久层”,也就是在系统逻辑层面上,专著于实现数据持久化的一个相对独立的领域(Domain),是把数据保存到可掉电式存储设备中。持久层是负责向(或者从)一个或者多个数据存储器中存储(或者获取)数据的一组类和组件。大多数情况下特别是企业级应用,数据持久化往往也就意味着将内存中的数据保存到磁盘上加以固化,而持久化的实现过程则大多通过各种关系数据库来完成。
一、DAO的支持
DAO是数据访问对象(data access object)的缩写,是一个面向对象的数据库接口。对于数据库的存取,spring提供了DAO的支持,可以不用管任何
的底
层数据库细节,spring 的一组DAO接口就可以完成所有数据的操作。DAO提供了数据读取和写入到数据库中的一种方式。
spring没有自己的持久层实现,但是它提供了DAO的支持,可以任意封装任何其他的持久层实现框架。
服务对象通过接口来访问DAO,优点:
1.使得服务对象易于测试,因为他们不再与特定的数据访问实现绑定在一起。
2.数据访问层是以持久化技术无关的方式进行访问的。持久化方式的选择独立于DAO,只有相关的数据访问方法通过接口来进行发布。这样可以实现灵活的设计并使得切换持久化框架对应用程序其他部分所带来的影响最小。
spring将数据访问过程中固定的和可变的部分明确划分为两个不同的类:模板(template)和回调(callback)。
spring的模板类处理数据访问的固定部分——事物控制、管理资源以及处理异常。
spring的回调类处理应用程序相关的数据访问——创建语句、绑定参数以及整理结果集。

(1)举一个传统的DAO例子,首先建立一个用户对象User
package spring.chapter4;
public class User {
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id=id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username=username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password=password;
}
}
(2)设计一个操作用户的DAO接口IUserDAO
package spring.chapter4;
public interface IUserDAO {
public void insert(User user);
public void delete(User user);
public void update(User user);
public User find(Long id);
}
(3)写一个IUserDAO的实现类,就是操作数据库的底层代码
package spring.chapter4; import java.sql.SQLException; import javax.activation.DataSource; import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
import com.mysql.jdbc.StatementImpl; public class UserDAO implements IUserDAO {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource=dataSource;
} public void insert(User user) {
String userName=user.getUsername();
String password=user.getPassword();
Connection conn=null;
java.sql.PreparedStatement stmt=null;
try {
conn=dataSource.getConnection();
stmt=conn.prepareStatement("insert into user(name,password) value(?,?)");
stmt.setString(1, userName);
stmt.setString(2, password);
}catch(SQLException e) {
e.printStackTrace();
}
finally {
if(stmt!=null) {
try {
stmt.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
if(conn!=null) {
try {
conn.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
//省略其他方法
}
二、数据源的注入
1.在spring中都是采用IOC(控制反转)方式注入数据源,直接在配置文件中给DAO注入数据源。在spring中不用考虑数据库的类型,均可以使用配置文件来完成数据源的注入,同时支持多种不同的数据源,如JDBC、连接池和JNDI等注入。不管使用声明方式,只要保留一个DataSource的接口就可以进行数据源注入了。
(4)结合前面的UserDAO,可以写如下配置文件来注入DataSource。(通过jdbc驱动程序定义的数据源)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/news" />
<property name="username" value="root" />
<property name="password" value="******" />
</bean>
<bean id="userDao" class="spring.chapter4.UserDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
(5)测试代码如下:
package spring.chapter4; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDAO {
public static void main(String [] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring/chapter4/web.xml");
User user=new User();
user.setUsername("gaochao");
user.setPassword("gaochao");
IUserDAO userDao=(IUserDAO)context.getBean("userDao");
userDao.insert(user); System.out.println("name:"+user.getUsername()+",password:"+user.getPassword());
} }
2.DBCP连接池注入数据源
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/news" />
<property name="username" value="root" />
<property name="password" value="******" />
</bean>
<bean id="userDao" class="spring.chapter4.UserDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
可以看出,只需要修改Bean的class为org.apache.commons.dbcp.BasicDataSource就可以。注意这里设置了一个destroy-method方法,该方法表示在BeanFactory关闭的时候调用close方法关闭BasicDataSource。
3.JNDI的支持
与DBCP相比,在进行web开发中,更多的是使用JNDI来连接数据库。这里以Tomcat容器为例,首先在Tomcat\conf目录下找到server.xml中的</Host>前添加context,代码如下:
<!-应用程序的目录是webapp -->
<Context path="webapp" docBase="webapp">
<Resource name="jdbc/news" scope="Shareable" type="javax.sql.DataSource" />
<ResourceParams name="jdbc/news">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-数据库的连接URL -->
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:3306/news</value>
</parameter>
<!- 数据库连接的驱动程序 -->
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<!-数据库连接的用户名 -->
<parameter>
<name>username</name>
<value>gaochao</value>
</parameter>
<!-数据库连接的密码 -->
<parameter>
<name>password</name>
<value>*****</value>
</parameter>
<!-等待连接的时间,单位为毫秒,-1为不限制 -->
<parameter>
<name>maxWait</name>
<value>3000</value>
</parameter>
<!-连接池中最少连接数,0为不限制 -->
<parameter>
<name>maxIdle</name>
<value>10</value>
</parameter>
<!-连接池中最多的连接数,0为不限制 -->
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
</ResourceParams>
</Context>
在Tomcat配置好连接池后就可以修改前面的spring配置文件来获取连接池:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="jndiName" value="jdbc/news" />
</bean>
<bean id="userDao" class="spring.chapter4.UserDAO">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
三、JDBC的支持
1.Template模式:在父类中定义一个操作中的骨架算法,而将一些用户自定义的逻辑延迟到子类中。示例:加入所有的business方法中都必须进行用户验证、异常捕获和一个业务操作,那么就将用户验证、异常捕获封装到父类中,子类只需要写一些business代码就可以了。父类代码如下:
package spring.chapter4;
public abstract class BusinessTemplate {
public void execute() throws Exception{
validataUser();
try {
business();
doBusiness();
}catch (Error e) {
e.printStackTrace();
}
}
void validataUser() {
System.out.println("验证用户...");
};
void business() {
System.out.println("业务1");
}
public abstract void doBusiness();
}
这里是一个抽象类,有一个execute()方法,在该方法中进行了用户验证、异常捕获和一个业务的执行。在这三项任务结束后执行了doBusiness()方法,同时doBusiness()方法又是一个抽象方法,继承该抽象类就要重写这个抽象方法,在这里定义用户自己的业务,写一个子类如下:
package spring.chapter4;
public class Business extends BusinessTemplate{
public void doBusiness() {
System.out.println("自定义业务");
}
}
这里继承类就重写了doBusiness方法,定义一个用户自己的业务,接着写一个测试类如下:
package spring.chapter4;
public class TestTemplate {
public static void main(String[] args) throws Exception {
Business business=new Business();
business.execute();
}
}
这里的Business类调用了父类的execute方法,按execute()方法执行顺序来执行后,运行结果如下:

这里的Business类是BusinessTemplate的一个子类,原本也需要写用户验证和异常捕获等业务,而采用了一个父类模板就将所有的业务都省略了,其他任何想乣进行用户验证。异常捕获和业务这些操作的逻辑都只需要继承BusinessTemplate,然后写用户的逻辑代码就可以了,再也不用写那些重复的逻辑了,spring正是采用了这样的方法来封装了数据库操作的Connection,Statement这些连接、关闭及异常捕获等。
使用JDBC模板:
▲JdbcTemplate:最基本的spring JDBC模板,这个模板支持最简单的JDBC数据库访问功能以及简单的索引参数查询
▲NamedParameterJdbcTemplate:使用该模板类执行查询时,可以将查询值以命名参数的形式绑定到SQL中,而不是使用简单的索引参数
▲SimpleJdbcTemplate:该模板利用java 5的一些特性,如自动装箱,泛型以及可变参数列表来简化JDBC模板的使用
2.JdbcTemplate
spring提高了org.springframework.jdbc.core.JdbcTemplate类,它封装了数据库的操作的方法。JdbcTemplate的构造函数接受一个DataSource对象,使用JdbcTemplate template=new JdbcTemplate(dataSource)来完成JdbcTemplate的初始化,然后就可以使用JdbcTemplate来操作数据库了。将UserDAO使用JdbcTemplate为:
package spring.chapter4; import java.awt.List;
import java.util.Iterator;
import java.util.Map; import javax.activation.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class UserDAO1 implements IUserDAO {
private JdbcTemplate jdbctemplate;
public void setDataSource(DataSource dataSource) {
jdbctemplate = new JdbcTemplate(dataSource);
}
public void insert(User user) {
String name=user.getUsername();
String password=user.getPassword();
this.jdbctemplate.update("insert into user (username,password)"+"values('"+name+"','"+password+"')");
}
public User find(Long id) {
List list=jdbctemplate.queryForList("select * form user where id="+id.longValue());
Iterator it=list.iterator();
if(it.hasNext()) {
Map map=(Map) it.next();
Long l=new Long(map.get("id").toString());
String name=map.get("username").toString();
String password=map.get("password").toString();
User user=new User();
user.setId(l);
user.setUsername(name);
user.setPassword(password);
return user;
}
return null;
}
//省略其他方法
}
2.1使用JdbcTemplate查询数据库
(1)返回单个对象查询:
Object query(String sql,ResultSetExtractor extractor)
Object query (String sql,Object[] args,ResultSetExtractor extractor)
int queryForInt(String sql)
int queryForInt(String sql,Object[] args)
int queryForLong(String sql)
long queryForLong(String sql,Object[] args)
Object queryForObject(String sql,Class requiredType)
Object queryForObject(String sql,Object[] args,Class requiredType)
Object queryForObject(String sql,RowMapper rowMapper)
Object queryForObject(String sql,Object[] args,RowMapper rowMapper)
(2)返回多个对象查询:
List query(String sql,RowMapper rowMapper)
List query(String sql,Object[] args,RowMapper rowMapper)
List queryForList(String sql)
List queryForList(String sql,Object[] args)
List queryForList(String,Class elementType)
2.2使用JdbcTemplate更新数据
void execute(String sql)
Object execute(String sql,PrepareStatementCallback action)
Object execute(ConnectionCallback action)
int update(String sql)
int update(String sql,Object[] args)
int update(PrepareStatementCreator psc)
int update(String sql,PreparestatementSetter pss)
int update(String sql,Object[] args,int[] argTypes)
2.3面向对象查询数据
spring JDBC的操作还是使用了sql语句,如果对sql不是非常熟悉的程序员可能在运用上有麻烦,为此spring提供了org.springframework.jdbc.object包来设计完全面向对象查询,只要封装一个面向对象的查询类,丝毫不用写任何sql语句就可以完成JdbcTemplate所有的数据库操作功能。
(1)org.springframework.jdbc.object.SqlQuery
(2)org.springframework.jdbc.object.MappingSqlQuery
(3)org.springframework.jdbc.object.SqlUpdate
(4)org.springframework.jdbc.object.SqlFunction
3.NameParameterJdbcTemplate:
4.SimpleJdbcTemplate:
spring学习(四)spring 持久层的封装的更多相关文章
- Spring学习(四)-----Spring Bean引用同xml和不同xml bean的例子
在Spring,bean可以“访问”对方通过bean配置文件指定相同或不同的引用. 1. Bean在不同的XML文件 如果是在不同XML文件中的bean,可以用一个“ref”标签,“bean”属性引用 ...
- Spring Boot 入门之持久层篇(三)
原文地址:Spring Boot 入门之持久层篇(三) 博客地址:http://www.extlight.com 一.前言 上一篇<Spring Boot 入门之 Web 篇(二)>介绍了 ...
- (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合
http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...
- Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档
0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...
- Spring学习(十一)-----Spring使用@Required注解依赖检查
Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- spring boot整合双持久层框架jpa、mybatis
公司之前用的是spring boot + jpa,但由于jpa无法完美的解决某些动态查询问题,就使用的jdbcTemplate 动态封装SQL,由于代码相对复杂,可读性差,现准备再引入mybatis. ...
- Spring学习四----------Bean的配置之Bean的配置项及作用域
© 版权声明:本文为博主原创文章,转载请注明出处 Bean的作用域(每个作用域都是在同一个Bean容器中) 1.singleton:单例,指一个Bean容器中只存在一份(默认) 2.prototype ...
- Spring/SpringMVC/MyBatis(持久层、业务层、控制层思路小结)
准备工作: ## 7 导入省市区数据到数据库中 1. 从FTP下载SQL脚本文件 2. 把脚本文件移动到易于描述绝对路径的位置 3. 进入MySQL控制台 4. 使用`xxx_xxx`数据库 5. 运 ...
随机推荐
- python学习之路---day09
函数案例: return 可以终止函数后面的调用 def abc() print("1") print("2") print("3") pr ...
- P4592 [TJOI2018]异或 (可持久化Trie)
[题目链接] https://www.luogu.org/problemnew/show/P4592 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\ ...
- java的Spring学习2- junit
1.maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...
- naginx安装入门
一.nginx是什么 nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件.它是一个俄罗斯人lgor sysoev开发的,作者将源代码开源出来供全球使用. nginx比它大哥apach ...
- PIE SDK地图书签
地图书签,可以理解为暂时记录当前地图的范围和放大级别,在后续的操作中如果想回到地图之前的状态,就可以点击保存的书签就可以回到此状态,如图所示: 地图刚加载的时候是一幅世界地图 我们将地图的中心拖到南美 ...
- 第三次 Scrum Meeting
第三次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/4/7 20:00 60min 新主楼G411 附Github仓库:WEDO 例会照片 工作情况总结(4.5-4. ...
- oracle OEM安装(一)
01,用户解锁添加密码 [oracle@oracle01 ~]$ sqlplus / as sysdba SQL Production :: Copyright (c) , , Oracle. All ...
- nginx 代理服务指令详解
nginx 正向代理与反向代理说明图 超级形象说明. 正向代理指令: 1, resolver 这个用于DNS服务器的ip . DNS服务器的主要工作是进行域名解析,将域名映射为对应IP地址 resol ...
- vue中遇到的坑 --- 变化检测问题(数组相关)
最近在项目中遇到了一个问题,不知道为什么,所以最后通过动手做demo实践.查文档的方式解决了,这里做一个总结. 例1 <!DOCTYPE html> <html lang=" ...
- mysql安装 2018最新安装mysql教程及遇到的问题解决Windows下
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8094659.html 今天因为换了个LINUX系统 把我的E盘不小心给卸载了 结果还是不能用 ...