由于有持久层框架,和Spring的存在,愈来愈多的人对数据库链接这块不甚了解,只知使用方便,不知其原理。因此写一个数据库链接的系列文章,总结下本人在数据库链接方面遇到的问题,和对数据库链接的理解。html
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
链接urlspring
链接: 数据库Server通讯与服务的通讯sql
statement:把 SQL 语句发送到 DBMS数据库
ResultSet : 数据库操做返回结果apache
后续的其余扩展,都是基于以上各个部分的扩展
获取connection,构建statement,执行时Java操做数据库最基本的操做,之后的全部扩展都围绕这个。
从上面的代码中咱们能够看到这只是一个hello world,在实际开发中,有不少的数据库操做,若是每一个都写一个,那重复代码太多了
将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框架中讲它的实现
虽然有了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 的做用就是让你不知道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