博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于MyBatis的工作流程和与JDBC的比较与Hibernate的比较
阅读量:5838 次
发布时间:2019-06-18

本文共 9053 字,大约阅读时间需要 30 分钟。

一.传统的JDBC的方式

1.从一个jdbc程序开始

1 public static void main(String[] args) { 2             Connection connection = null; 3             PreparedStatement preparedStatement = null; 4             ResultSet resultSet = null; 5              6             try { 7                 //加载数据库驱动 8                 Class.forName("com.mysql.jdbc.Driver"); 9                 10                 //通过驱动管理类获取数据库链接11                 connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql");12                 //定义sql语句 ?表示占位符13                 String sql = "select * from user where username = ?";14                 //获取预处理statement15                 preparedStatement = connection.prepareStatement(sql);16                 //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值17                 preparedStatement.setString(1, "王五");18                 //向数据库发出sql执行查询,查询出结果集19                 resultSet =  preparedStatement.executeQuery();20                 //遍历查询结果集21                 while(resultSet.next()){22                     System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));23                 }24             } catch (Exception e) {25                 e.printStackTrace();26             }finally{27                 //释放资源28                 if(resultSet!=null){29                     try {30                         resultSet.close();31                     } catch (SQLException e) {32                         // TODO Auto-generated catch block33                         e.printStackTrace();34                     }35                 }36                 if(preparedStatement!=null){37                     try {38                         preparedStatement.close();39                     } catch (SQLException e) {40                         // TODO Auto-generated catch block41                         e.printStackTrace();42                     }43                 }44                 if(connection!=null){45                     try {46                         connection.close();47                     } catch (SQLException e) {48                         // TODO Auto-generated catch block49                         e.printStackTrace();50                     }51                 }52 53             }54 55         }

上边使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作。

2.jdbc操作步骤总结如下:

1、  加载数据库驱动

2、  创建并获取数据库链接

3、  创建jdbc statement对象

4、  设置sql语句

5、  设置sql语句中的参数(使用preparedStatement)

6、  通过statement执行sql并获取结果

7、  对sql执行结果进行解析处理

8、  释放资源(resultSet、preparedstatement、connection)

3.jdbc问题总结如下:

问题1:数据库连接频繁创建和关闭,数据库资源消耗

设想:使用数据库连接池管理数据库连接

解决:在mybatis的全局配置文件SqlMapConfig.xml配置数据库连接池:

  
  
  
  

问题2:sql语句在java代码中硬编码,如果将来修改sql,需要重新进行编译java文件,不利系统维护。

设想:将sql语句配置在单独配置文件中,比如xml文件。

解决:mybatis是在XXXXMapper.xml中配置sql语句

问题3:向sql中设置参数,需要人工判断调用方法setXXXX(占位符的位置也需要人工判断,),编程不方便

设想:在xml中通过配置,自动将输入参数设置(setXXXX)到sql语句中。达到了自动由框架调用setXXXX(占位符号位置由框架自动识别)解决:mybatis在XXXXmapper.xml中定义statement中使用了parametertype指定传和参数类型(可以是pojo),同时在sql语句中用#{}指定占位符号,且#{}中指定传入值

问题4:遍历resultSet,需要人工判断调用getXXXX(列名)方法,如果表添加字段,需要修改代码调用resultSet.getXXX方法获取结果。

设想:在xml中通过配置,指定sql返回的java类型,让框架自动将sql查询结果集映射成java对象。框架内部自动调用resultSet.getXXX方法。解决:mybatis在XXXXmapper.xml中定义resultType,可以指定一个pojo类型(还指定简单),mybatis自动将sql查询结果映射成resultType指定类型的java对象。通过java对象方法取出pojo的属性值。

二.MyBatis

1.MyBatis介绍 

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的statement配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。 

2.Mybatis架构

3.MyBatis的搭建

1、mybatis配置

  SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

  mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、  通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、  由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、  mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、  Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、  Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过 Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、  Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过 Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

附录一个XXXMapper.xml配置模板:

SELECT LAST_INSERT_ID()
insert into user(username,birthday,sex,address,detail,score) values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
delete from user where id=#{id}
update user set username=#{username},sex=#{sex},birthday=#{birthday} where id=#{id}

SqlMapConfig.xml全局配置文件,sqlmapconfig.xml名字不是固定的。

SqlSessionFactory会话工厂,生产SqlSession会话,使用时建议使用单例模式。Sqlsession会话,SqlSession是一个接口,此接口面向用户的,用户使用接口可以操作数据(增、删、改、查),

SqlSession存在多线程访问,由SqlSession不是线程安全,SqlSession使用范围建议在方法中使用。
mapper.xml,映射文件,定义了很多的statement,指定id,访问statement:namespace+statement的id、指定输入参数类型:parameterType=“java简单类型、pojo类型” 通过parameterType将java对象映射到sql语句中。
指定输出结果类型:resultType/resultMap

resultType=“java类型:java简单类型、pojo类型”  resultType指定pojo类型,如何将sql查询结果集映射成pojo类型。规则:select查询的列名要和resulttype指定的pojo类型的属性名一致才可以映射成功,如果名称不一致此列映射不成功。

resultMap:不需要select查询的列名和pojo类的属性名一致,resltMap指定列名与pojo类的属性名的对应关系。

关于xxxMapper.xml文件中的主键自增mysql和oracle中的配置不同:

添加用户:向mysql数据库的user表添加一条记录。
SELECT LAST_INSERT_ID()
insert into user(username,birthday,sex,address,detail,score) values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
mysql实现:
SELECT LAST_INSERT_ID()
oracle实现:
SELECT 自定义序列.NEXTVAL FROM DUAL

 对应的添加一条用户的代码:

public class Mybatis_insert {    public static void main(String[] args) throws IOException {        //创建的会话工厂SqlsessionFactory        String resource = "SqlMapConfig.xml";        InputStream inputStream = Resources.getResourceAsStream(resource);        //创建的会话工厂SqlsessionFactory        SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(inputStream);        //通过工厂得到Sqlsession        SqlSession sqlSession = sqlSessionFactory.openSession();        try {            //由于在SqlMapConfig.xml加载mapper.xml,selectOne方法中可以找到statement的id            //通过SqlSession操作数据库            //第一个参数:指定statement的id            //第二个参数:要传入的输入参数            //插入user对象            User user = new User();            user.setUsername("张三丰");            user.setSex("1");            sqlSession.insert("test.insertUser", user);            //获取对象的主键值            System.out.println(user.getId());            //提交事务            sqlSession.commit();        } catch (Exception e) {            e.printStackTrace();        }finally{            //关闭Sqlsession            sqlSession.close();        }    }}

 上面代码中常用类的介绍

 SqlSession 

 SqlSession中封装了对数据库的sql操作,如:查询、插入、更新、删除等。

 通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

 SqlSessionFactoryBuilder

 SqlSessionFacoty是通过SqlSessionFactoryBuilder进行创建,SqlSessionFactoryBuilder只用于创建SqlSessionFactory,可以当成一个工具类,在使用时随时拿来使用不需要特殊处理为共享对象。

 SqlSessionFactory

 SqlSessionFactory是一个接口,接口中定义了openSession的不同方式,SqlSessionFactory一但创建后可以重复使用,实际应用时通常设计为单例模式。

 SqlSession

 SqlSession是一个接口,默认使用DefaultSqlSession实现类,sqlSession中定义了数据库操作。

 执行过程如下:

 1、 加载数据源等配置信息

 Environment environment = configuration.getEnvironment();

2、 创建数据库链接

3、 创建事务对象

4、 创建ExecutorSqlSession所有操作都是通过Executor完成,mybatis源码如下:

if (ExecutorType.BATCH == executorType) {     executor = new BatchExecutor(this, transaction);} else if (ExecutorType.REUSE == executorType) {     executor = new ReuseExecutor(this, transaction);} else {     executor = new SimpleExecutor(this, transaction);}if (cacheEnabled) {   executor = new CachingExecutor(executor, autoCommit);}

5、 SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor

结论:每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。

 三.与Hibernate的不同

1.Mybatishibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。 

2.Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

3.Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 

 

本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/4091004.html,如需转载请自行联系原作者

你可能感兴趣的文章
hp 服务器通过串口重定向功能的使用
查看>>
MongoDB CookBook读书笔记之导入导出
查看>>
shell如何快速锁定所有账号
查看>>
HTML 5实现的手机摇一摇
查看>>
此博客不再发表对自己私事的看法
查看>>
导致Asp.Net站点重启的10个原因
查看>>
【PMP】Head First PMP 学习笔记 第一章 引言
查看>>
抓住云机遇编排工作 搞定复杂IT工作流
查看>>
MYSQL的longtext字段能放多少数据?
查看>>
MTK 平台上如何给 camera 添加一种 preview size
查看>>
云计算最大难处
查看>>
关于数据分析思路的4点心得
查看>>
Memcached安装与配置
查看>>
美团数据仓库的演进
查看>>
SAP被评为“大数据”预测分析领军企业
查看>>
联想企业网盘张跃华:让文件创造业务价值
查看>>
记录一次蚂蚁金服前端电话面试
查看>>
直播源码开发视频直播平台,不得不了解的流程
查看>>
Ubuntu上的pycrypto给出了编译器错误
查看>>
聊聊flink的RestClientConfiguration
查看>>