數據庫鏈接(1)-從JDBC到MyBatis

摘要

由於有持久層框架,和Spring的存在,愈來愈多的人對數據庫鏈接這塊不甚瞭解,只知使用方便,不知其原理。因此寫一個數據庫鏈接的系列文章,總結下本人在數據庫鏈接方面遇到的問題,和對數據庫鏈接的理解。html

JDBC

jdbc:Java DataBase Connectivity,Java 數據庫鏈接,一套標準的Java API,用來執行SQL語句。這套命名應該是很老了,畢竟將Data Base直接映射成了關係型數據庫,或者說,像我以前在介紹NoSQL數據庫時屢次提到的,NoSQL數據庫尚未一套統一的訪問標準語句。java

jdbc的做用就是將SQL變成了Java API 訪問。mysql

Connection conn = null;
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/test?"
                + "user=root&password=123456&useUnicode=true&characterEncoding=UTF8";
        conn = DriverManager.getConnection(url);
        Statement stmt = conn.createStatement();
        String sql = "select *from post where user_id=1";
        ResultSet resultSet = stmt.executeQuery(sql);
        List<Post> posts = new ArrayList<>();
        while (resultSet.next()) {
            Post post = new Post();
            post.setId(resultSet.getLong("id"));
            post.setTitle(resultSet.getString("title"));
            post.setContents(resultSet.getString("contents"));
            posts.add(post);
        }
        stmt.close();
        conn.close();

其中Connection,DriverManager,Statement這些類都是jdk提供的,不依賴其餘的jar。jdk提供了一套通用的SQL訪問API,可是各個數據庫並不相同,有各自的標準,因此各個針對MySQL,Oracle提供了不一樣的驅動。好比MySQL的驅動。git

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
        </dependency>

執行Class.forName("com.mysql.jdbc.Driver");加載MySQL驅動github

DriverManager.registerDriver(new Driver());

這段代碼中包含了全部的基本的數據庫操做對象
JDBC 四大對象: DataSource , Connection, Statement,ResultSetweb

  1. 鏈接urlspring

  2. 鏈接: 數據庫Server通訊與服務的通訊sql

  3. statement:把 SQL 語句發送到 DBMS數據庫

  4. ResultSet : 數據庫操做返回結果apache

後續的其餘擴展,都是基於以上各個部分的擴展
這裏寫圖片描述

獲取connection,構建statement,執行時Java操做數據庫最基本的操做,之後的全部擴展都圍繞這個。
從上面的代碼中咱們能夠看到這只是一個hello world,在實際開發中,有不少的數據庫操做,若是每一個都寫一個,那重複代碼太多了

Spring-Template--解決重複代碼

將1的url封裝成了一個DataSource對象

@Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource("jdbc:mysql://localhost:3306/test?"
                + "user=root&password=123456&useUnicode=true&characterEncoding=UTF8");
    }
    @Bean
    public JdbcTemplate jdbcTemplate() {
        return  new JdbcTemplate(dataSource());
    }

將3 Statement重複代碼解決了

@Service
public class JdbcTemplateService {
    @Autowired
    private JdbcTemplate mJdbcTemplate;
    
    public void queryById(long userId) {
        String sql = "select * from post where user_id = " + userId;
        List<Post> result =mJdbcTemplate.query(sql, new PostRowMapper());
    }

    class PostRowMapper implements RowMapper<Post> {
        public Post mapRow(ResultSet rs, int rowNum) throws SQLException {
            Post post = new Post();
            post.setId(rs.getLong("id"));
            post.setTitle(rs.getString("title"));
            post.setContents(rs.getString("contents"));
            return post;
        }

    }
}

解決了鏈接獲取,查詢重複語句的問題,
可是沒有解決對象映射的問題,須要爲每一個數據庫對象生成獨自的Mapper

那麼JdbcTemplate是如何作到的呢,由於statemnt的前提是須要一個鏈接,而後執行。
因此對於Spring框架而言,它當前沒有connection對象,因此它須要一個回調來執行。

public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL query [" + sql + "]");
        }

        class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
            @Override
            @Nullable
            public T doInStatement(Statement stmt) throws SQLException {
                ResultSet rs = null;
                try {
                    rs = stmt.executeQuery(sql);
                    return rse.extractData(rs);
                }
                finally {
                    JdbcUtils.closeResultSet(rs);
                }
            }
            @Override
            public String getSql() {
                return sql;
            }
        }

        return execute(new QueryStatementCallback());
    }

這裏寫圖片描述

對外暴露JdbcTemplate,
內部實現是經過回調方法來實現Statement的執行

鏈接池

Template只是解決了重複代碼的問題,並無解決鏈接的資源消耗問題,因此須要鏈接池,經過一個容器儲存鏈接,而後複用已有的鏈接,來實現節約資源的目的

一些開源的數據庫鏈接池

  • DBCP
    Apache 下面的,實現了基本的數據庫鏈接池功能,沒有自動回收空閒鏈接的功能

  • C3P0
    實現了數據源與JNDI的綁定,目前使用它的開源項目有Hibernate,

  • Druid
    阿里的開源數據庫鏈接池,分庫分表數據庫中間件TDDL就是用的這個

數據庫鏈接池是一個老生常談的話題,不作過多的介紹,在下面的mybatis框架中講它的實現

持久層框架-mybatis

雖然有了JdbcTemplate,可是還缺少一些操做,好比對象映射,查詢數據的時候但願自動映射到對象上,
另外須要自動生成SQL語句,不須要進行SQL的拼接,賦值。

mybatis的介紹

MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

重點在於避免了全部的JDBC代碼,和手動設置參數以及獲取結果集

這裏寫圖片描述
對外暴露:SqlSession
在jdbc中是沒有session這個概念,只有connection.session即會話,mybatis與數據庫的一次交互

內部實現:Executor,StatmentHandler 替換Statement,ResultHander替換resultset,另外多了一個ParameterHandler來處理參數

構建一個SqlSessionFactory

@Bean
    public SqlSessionFactory sqlSessionFactory() {
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development", transactionFactory, dataSource());
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session
                .Configuration(environment);
        configuration.addMapper(PostMapper.class);
        return new SqlSessionFactoryBuilder().build(configuration);
    }

獲取session而後執行

@Autowired
    private SqlSessionFactory sqlSessionFactory;
    public void queryByUserId(long userId) {
        SqlSession session = sqlSessionFactory.openSession();
        PostMapper postMapper = session.getMapper(PostMapper.class);
        Post post = postMapper.findPostByUserId(userId);
    }
}

spring-mybatis

spring-mybatis 的做用就是讓你不知道mybatis
Spring 將會加載必要的 MyBatis 工廠類和 session 類。由spring來接管數據庫鏈接的建立。
而且提供一個簡單的方式來注入 MyBatis 數據映射器和 SqlSession 到業務層的 bean 中

全部代碼

https://github.com/FS1360472174/javaweb/tree/master/db-connection/mysql-jdbc

mybatis 與hibernate一些區別,下期再講

關注【方丈的寺院】,與方丈一塊兒開始技術修行之路
喜歡這篇文章的話,點個讚唄
在這裏插入圖片描述

參考

http://www.cnblogs.com/JavaSubin/p/5294721.html http://www.mybatis.org/mybatis-3/zh/index.html http://www.mybatis.org/spring/zh/index.html http://blog.csdn.net/u014723529/article/details/41288333 https://github.com/spring-projects/spring-framework/blob/master/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java

相關文章
相關標籤/搜索