前言
上一篇讲了AOP技术,这篇我们来了解dao。在上一个系列《小马商城》中,我们用到访问数据的框架为mybatis,其中我们只要编写dao接口,就可以实现数据库的操作,那么接下来我们来了解spring是如何访问数据库的。
DAO
DAO ,Database Access Object数据访问对象,使用DAO模式,可以完全分离数据的访问与存储,很好的屏蔽各种数据库的差异性。
基于JDBC的DAO实现
JDBC操作数据库时标准模版
JdbcTemplate
将上面的代码往上提取
public static Object query(String sql){
Connection conn = null;
Statement stmt = null;
List<Object> list = new LinkedList<>();
//1.加载驱动程序
try {
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库的连接
conn = DriverManager.getConnection(URL, NAME, PASSWORD);
//3.通过数据库的连接操作数据库,实现增删改查
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);//选择import java.sql.ResultSet;
while (rs.next()) {//如果对象中有数据,就会循环打印出来
list.add(rs);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
return list;
}
//直接调用查询了
public static void main(String[] args) {
query("select * from table");
}
实际上JdbcTemplate的代码会复杂点,但是原理还是做抽象的提取。
JdbcTemplate中大致分为4种模版:
- 面向Connection的模版方法。连接数据库;
- 面向Statement的模版方法,查询语句;
- 面向PreparedStatement的模版方法,动态拼接sql语句,防止sql注入问题;
- 面向CallableStatement的模版方法,存储过程的访问。 在Connection的模版方法中,我们不是每次都要创建一个数据库连接,而是通一项数据库连接池的技术来完成的。 JDBC 2.0标准引入了dataSource作为数据库资源管理的标准,dataSource可以做到适配不同的数据库,以及数据库的连接数,释放等功能,任何的ORM框架都会与它集成的
ORM框架 spring与mybatis整合
单独使用mybatis进行数据查询时
//配置文件
Configuration configuration = new Configuration();
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
//获取连接数据库的sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Object> list = sqlSession.selectList("select * from table");
sqlSession.close();
spring与mybatis整合时,通过ioc容器将数据库信息注入到dataSource中,sqlSessionFactory从dataSource获取SqlSession,然后在执行sql语句。
在我们编写的dao接口,通过@Mapper生成代理类变为spring的bean,当我们访问接口的时候,代理类先获取SqlSession,然后调用接口方法,执行对应的sql语句,再将数据进行转换返回到我们定义好的实体中。
加载MapperScannerRegistrar处理器
//类似于spring的beanFactory,对dao进行注册,解析bean信息,生成代理类,
MapperScannerRegistrar#registerBeanDefinitions
这里就简单介绍spring与mybatis的整合
事务与AOP
事务
我们通常将事务放在service层,而数据处理放在DAO层,根据service层的相应逻辑来决定事务提交或这回滚。这样的设计模式又一次体现了spring框架中,各个类各施其职的思想。
实践
通 @Transactional注解就能对该方法事务的自动提交了,这里涉及到我们上一篇的aop技术。在没有看代码的时候,我们先想象如果通过aop管理事务。
伪代码
//定义切点 只要带有 @Transactional注解的都要进入AOP方法
@Around
开启事务
执行sql
提交事务
catch 事务回滚
TransactionAspectSupport#invokeWithinTransaction
spring事务传递 ,如果当前已有事务,就不会再开启事务。
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
事务的开启,以及提交。
proceedWithInvocation 执行目标的方法
小结
通过本篇的简单讲解,我们对spring访问数据库有基本的了解,如果要深入了解的话需要多看先源码,源码方法上的英文注释基本都将该方法的用法讲明白了,其次可以结合网上的教程继续深入。 在看spring源码的时候不要担心看不懂,我们可以通过idea的debugger模式,一步步调试,查找方法的调用关系来寻找我们需要的知识。