本文首先讲解从JDBC到mybatis的演变过程,然后是使用mybatis进行开发的两种方式。

一 JDBC的使用及其优化

1.使用JDBC进行数据库操作

  • 加载JDBC驱动;

  • 建立并获取数据库连接;

  • 创建 JDBC Statements 对象;

  • 设置SQL语句的传入参数;

  • 执行SQL语句并获得查询结果;

  • 对查询结果进行转换处理并将处理结果返回;

  • 释放相关资源(关闭Connection,关闭Statement,关闭ResultSet);

代码如下:

public static List<Map<String,Object>> queryForList(){
Connection connection = null;
ResultSet rs = null;
PreparedStatement stmt = null;
List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>(); try {
// 加载JDBC驱动
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://localhost:3306/silk"; String user = "root";
String password = "123456"; // 获取数据库连接
connection = (Connection) DriverManager.getConnection(url,user,password); String sql = "select * from goods where id = ? ";
// 创建Statement对象(每一个Statement为一次数据库执行请求)
stmt = (PreparedStatement) connection.prepareStatement(sql); // 设置传入参数
stmt.setString(1, "1"); // 执行SQL语句
rs = stmt.executeQuery(); // 处理查询结果(将查询结果转换成List<Map>格式)
ResultSetMetaData rsmd = rs.getMetaData();
int num = rsmd.getColumnCount(); while(rs.next()){
Map map = new HashMap();
for(int i = 0;i < num;i++){
String columnName = rsmd.getColumnName(i+1);
map.put(columnName,rs.getString(columnName));
}
resultList.add(map);
} } catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭结果集
if (rs != null) {
rs.close();
rs = null;
}
// 关闭执行
if (stmt != null) {
stmt.close();
stmt = null;
}
if (connection != null) {
connection.close();
connection = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return resultList;
}

2.JDBC操作数据库有哪些问题,如何进行优化呢?

2.1 问题:每一次请求都要进行数据库的连接和关闭,过于频繁,浪费资源,降低了系统的性能。

解决:数据库的连接和关闭可以通过数据库连接池来解决,通过连接池可以反复的使用已经建立的连接去访问数据库,而不是每次都重新建立一个新的连接。

2.2 问题:连接池有很多种,如c3p0,dbcp,druid 可能存在变化

解决:可以通过DataSource进行隔离解耦,统一从DataSource获取数据库连接,用户可以通过DataSource来配置使用哪种连接池

2.3 问题:使用JDBC时,sql语句是散落在各个java文件中的,可读性差不利于维护,改动sql时需要重新打包编译部署,不利于取出sql在客户端执行。

解决:将sql统一放到配置文件中,那么就需要将sql提前加载

2.4 问题:参数传递是按顺序,根据占位符一一匹配的,那如果是多个不确定的参数,这种方式就显得很局限了。
      解决:mybatis可以根据参数的不同,生成动态的sql语句

2.5 问题:sql重复 
      解决:将sql统一放到配置文件中,那么只需要修改这一个地方,对所有用到此sql的地方都生效
 

二 mybatis的两种开发方式

3.原始的dao开发方式:
对于这种开发方式,是直接使用SqlSession提供的方法,通过传递statementId和params来操作数据库,完成与数据库的交互。但是这种方式不符合面向接口编程的特性,所以就有了后面的Mapper接口代理这种开发方式。
3.1 在spring-ibatis配置文件中配置sqlSessionFactory和sqlSession
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName"> // 此处配置数据源 省略。。。

<!-- 将数据源映射到sqlSessionFactory中 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean> <!-- SqlSession模板类实例 -->
<bean id="sessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="close">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean> </beans>

3.2 编写dao接口和它的实现类,将sqlSession注入到实现类中  

 BaseDao接口:
public interface BaseDao<T> {

    /**
* 根据条件获取一个元素
* @param paramMap
* @return
*/
T get(T entity); /**
* 插入记录
* @param entity
*/
int insert(T entity); /**
* 插入记录(批量)
* @param list
* @return
*/
int insert(List<T> list); /**
* 更新记录
* @param entity
* @return
*/
int update(T entity); /**
* 更新记录(批量)
* @param list
* @return
*/
int update(List<T> list); /**
* 删除记录
* @param obj
* @return
*/
int delete(T entity); }

3.3 BaseDaoImpl实现类,并将sqlSession注入到此实现类中,sqlSession中封装了对数据库的各种操作:

public abstract class BaseDaoImpl<T> extends SqlSessionDaoSupport implements BaseDao<T> {

    public static final String SQL_SELECT = "select";
public static final String SQL_SELECT_BY = "selectBy";
public static final String SQL_SELECT_PAGE = "selectPage";
public static final String SQL_INSERT = "insert";
public static final String SQL_DELETE = "delete";
public static final String SQL_UPDATE = "update";
public static final String SQL_BATCH_INSERT = "batchInsert"; @Autowired
protected SqlSessionTemplate sessionTemplate;
@Autowired
protected SqlSessionFactory sessionFactory; @Override
@SuppressWarnings("unchecked")
public T get(T entity) {
if (entity == null) {
return null;
} Object result = this.getSqlSession().selectOne(this.getSqlName(SQL_SELECT), entity);
if (result == null) {
return null;
} return (T) result;
} @Override
public int insert(T entity) {
if (entity == null) {
throw new RuntimeException("T is null");
} int result = this.sessionTemplate.insert(this.getSqlName(SQL_INSERT), entity); return result;
} @Override
public int insert(List<T> list) {
if (list == null || list.size() <= 0) {
return 0;
} this.sessionTemplate.insert(this.getSqlName(SQL_BATCH_INSERT), list); return list.size();
} @Override
public int update(T entity) {
if (entity == null) {
throw new RuntimeException("");
} int result = this.sessionTemplate.update(this.getSqlName(SQL_UPDATE), entity); return result;
}
protected String getSqlName(String sqlId) {
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getName());
sb.append(".");
sb.append(sqlId); return sb.toString();
} }

3.4 再编写对应的Mapper文件,此处省略。

4.Mapper代理开发模式:不需要编写实现类,只要遵守以下规范,mybatis就可以动态生成Mapper接口的代理类

Mapper代理开发模式需要遵守以下规范:

4.1 Mapper.xml文件中的namespace与mapper接口的类路径相同。
   4.2 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 
   4.3 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
   4.4 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

这种开发模式,一般通过sqlSession.getMapper(XXXMapper.class),根据Mapper接口声明的方法和Mapper映射文件来生成一个Mapper代理对象,当通过这个代理对象调用一个Mapper接口声明的方法时,会根据方法名和参数来找到Mapper映射文件中

的statementId,底层还是通过sqlSeesion.select(statementId,params)来和数据库进行交互的。

优缺点比较:Mapper代理开发模式不需要编写实现类,减少了代码量,同时是面向接口编程,推荐使用此种方式。

mybatis两种开发方式的更多相关文章

  1. 6、ASP.NET MVC入门到精通——ASP.Net的两种开发方式

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 目前,ASP.NET中两种主流的开发方式是:ASP.NET Webform和ASP.NET MVC.从下图可以看到ASP.NET WebFo ...

  2. Asp.Net的两种开发方式

    来源:http://www.zhidao91.com/asp-net/ 在经过对.Net平台深入的学习以后,我发现很多语言开发动态网站时,它的后台逻辑都差不多是相同的,今天在这里我给大家来聊聊在.Ne ...

  3. mybatis几种开发方式

    mybatis是比较轻巧的半自动化的CRM框架,它有几种开发方式,现今张列于此: 一.注解方式:在接口方法上面写SQL语句,有点类似springdataJPA 的query sql 语句 范例 @se ...

  4. 二 Mybatis架构&MybatisDao的两种开发方式(原始Dao,接口动态代理)

    MyBatis架构图 三个对象: SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession SqlSessionFactoryBuilder:主要用来 ...

  5. mybatis两种嵌套查询方式

    1,推荐用第一种 <select id="getTeacher2" resultMap="TeacherStudent"> select s.id ...

  6. mybatis两种方式

    // 1.传统的使用 statementId方式 //获取详情 sysApiDocumentMode = template.selectOne("oaApiDocument.getProje ...

  7. SAPUI5 freestyle vs SAP Fiori Elements —— 两种开发SAP UI5 Apps的方式对比

    概述 目前SAPUI5 SDK 提供了两种方式来开发一个SAPUI5 App.一种方式是传统的SAPUI5开发方式,一种是利用SAP Fiori Elements通过模板快速构建应用的方式. 本文简单 ...

  8. Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式

    封面:洛小汐 作者:潘潘 一直以来 他们都说为了生活 便追求所谓成功 顶级薪水.名牌包包 还有学区房 · 不过 总有人丢了生活 仍一无所获 · 我比较随遇而安 有些事懒得明白 平日里问心无愧 感兴趣的 ...

  9. MyBatis中主键回填的两种实现方式

    主键回填其实是一个非常常见的需求,特别是在数据添加的过程中,我们经常需要添加完数据之后,需要获取刚刚添加的数据 id,无论是 Jdbc 还是各种各样的数据库框架都对此提供了相关的支持,本文我就来和和大 ...

随机推荐

  1. SecureCRT8.1+SecureCRT_keygen完成注册

    原文:https://www.cnblogs.com/qiyawei/p/7822957.html 1.下载完secureCRT8.1之后,进行安装. 点击secureCRT.exe的时候会出现如下图 ...

  2. Apache Shiro对象概念

    #,Authentication,认证,也就是验证用户的身份,就是确定你是不是你,比如通过用户名.密码的方式验证,或者某些第三方认证,比如微信认证. #,Authorization,授权,也叫访问控制 ...

  3. vue与jquey

    vue与jquey jQuery是使用选择器($)选取DOM对象,对其进行赋值.取值.事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的.比如需要 ...

  4. Matconvnet安装

    本文主要介绍Linux下Matconvnet的安装注意事项. 最近帮老师校验一份超分的代码,用到了matconvnet深度学习工具包.代码里面使用的是Matconvnet-1.0-beta20版本, ...

  5. bsxfun, arrayfun, cellfun, spfun, structfun

    在使用matlab进行矩阵计算的时候,经常会遇到要使用for循环的情况.但其实很多操作可以用内部的一些函数代替.今天总结一些几个函数的用法: bsxfun, arrayfun, cellfun, sp ...

  6. docker容器中安装vi命令

    在使用docker容器时,有时候里边没有安装vim,敲vim命令时提示说:vim: command not found,这个时候就需要安装vim,可是当你敲apt-get install vim命令时 ...

  7. C# 对象池的实现(能限制最大实例数量,类似于WCF的MaxInstanceCount功能)

    对象池服务可以减少从头创建每个对象的系统开销.在激活对象时,它从池中提取.在停用对象时,它放回池中,等待下一个请求.我们来看下主线程中,如何与对象池打交道: static void Main(stri ...

  8. 两次console.log打印值不同

    var a=[1,2,3] console.log(a); a[2]=10; console.log(a); // 打印结果 // (3) [1, 2, 3] // (3) [1, 2, 10] // ...

  9. PS调出通透唯美阳光外景女生照片

    1.稍微增加了一点曝光度,让照片更明亮. 2.对比度的话我现在比习惯加一点,而且 一般导入PS之后我还会按照片情况去加对比度. 3.高光的部分一般会拉回来一点,根据照片调. 4.阴影部分加一点的话会让 ...

  10. iOS iCloud云存储数据

    https://www.jianshu.com/p/ce8cfaf6030e 2017.11.29 16:05* 字数 452 阅读 302评论 0喜欢 1 因为上一次做了用keychain来持久化存 ...