《Spring 揭秘》 -- (3)

245 阅读2分钟

前言

上一篇讲了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模式,一步步调试,查找方法的调用关系来寻找我们需要的知识。