zoukankan      html  css  js  c++  java
  • 数据库连接(1)-从JDBC到MyBatis

    摘要

    因为有持久层框架,和Spring的存在,越来越多的人对数据库连接这块不甚了解,只知使用方便,不知其原理。所以写一个数据库连接的系列文章,总结下本人在数据库连接方面遇到的问题,和对数据库连接的理解。

    JDBC

    jdbc:Java DataBase Connectivity,Java 数据库连接,一套标准的Java API,用来执行SQL语句。这套命名应该是很老了,毕竟将Data Base直接映射成了关系型数据库,或者说,像我之前在介绍NoSQL数据库时多次提到的,NoSQL数据库还没有一套统一的访问标准语句。

    jdbc的作用就是将SQL变成了Java API 访问。

    		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的驱动。

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

    执行Class.forName("com.mysql.jdbc.Driver");加载MySQL驱动

    DriverManager.registerDriver(new Driver());
    

    这段代码中包含了所有的基本的数据库操作对象
    JDBC 四大对象: DataSource , Connection, Statement,ResultSet

    1. 连接url

    2. 连接: 数据库Server通信与服务的通信

    3. statement:把 SQL 语句发送到 DBMS

    4. ResultSet : 数据库操作返回结果

    后续的其他扩展,都是基于以上各个部分的扩展
    这里写图片描述

    获取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

  • 相关阅读:
    C#基础学习(二)
    C#基础学习(一)
    使用finalshll连接linux
    如何在显示表控件的时候隐藏某些列
    SMARTFORMS文本编辑器设置为SAP系统默认的
    python教学 目录
    [Unity官方文档翻译]ScrollRect
    <转载>解决div里面img的缝隙问题
    简单插入类排序
    利用border和伪类画出三角形 ps:好久没写博客了。。。
  • 原文地址:https://www.cnblogs.com/stoneFang/p/10743825.html
Copyright © 2011-2022 走看看