一.传统的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. //获取预处理statement
  15. 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 block
  33. e.printStackTrace();
  34. }
  35. }
  36. if(preparedStatement!=null){
  37. try {
  38. preparedStatement.close();
  39. } catch (SQLException e) {
  40. // TODO Auto-generated catch block
  41. e.printStackTrace();
  42. }
  43. }
  44. if(connection!=null){
  45. try {
  46. connection.close();
  47. } catch (SQLException e) {
  48. // TODO Auto-generated catch block
  49. 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配置数据库连接池:

  1. <dataSource type="POOLED">
  2.   <property name="driver" value="com.mysql.jdbc.Driver" />
  3.   <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
  4.   <property name="username" value="root" />
  5.   <property name="password" value="mysql" />
  6. </dataSource>

问题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配置模板:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!-- namespace的作用比ibatis升级了 -->
  6. <mapper namespace="test">
  7. <!-- 根据用户id查询用户信息
  8. <select:Mapped statement封装对象封装的sql语句
  9. id:sql语句的唯一标识,批到一个sql方法:通过namespace加上id:namespace+findUserById找到一个sql语句
  10. 把id叫做statement的id
  11. parameterType:设置输入参数的类型为int
  12. #{value}:将输入参数的值设置在占位符上,#{}表示一个点位符,value表示输入参数的值
  13. resultType:sql查询结果集要映射成的java对象(po类),规则:sql查询出来的列名和resultType指定类中的属性名一至,才可以映射
  14. -->
  15. <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
  16. select id,username,birthday,sex,address,detail,score from user where id=#{value}
  17. </select>
  18.  
  19. <!-- 自定义查询条件查询用户信息
  20. resultType:指定单条记录映射的类型
  21. ${}:表示将输入参数内容拿过来拼接到sql中,将内容不加任何修饰拼接在sql
  22. #{}:表示将输入参数内容拿过来拼接到sql中,不用考虑参数类型,比如如果拼接是字符,自动在参数加单引号
  23. -->
  24. <select id="findUserList" parameterType="cn.itcast.mybatis.po.User"
  25. resultType="cn.itcast.mybatis.po.User">
  26. select id,username,birthday,sex,address,detail,score from user
  27. WHERE username LIKE #{username} AND sex=#{sex}
  28. </select>
  29.  
  30. <!-- 添加用户
  31. parameterType:指定插入用户对象user,
  32. #{username}:#{}表示一个占位符,username表示parameterType指定的po类中的属性名
  33. -->
  34. <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
  35. <!-- 主键返回
  36. keyProperty:表示将主键值存储到User对象的哪个属性中
  37. order: SELECT LAST_INSERT_ID()执行时机,插入语句执行之后
  38. resultType:取到id的类型
  39. LAST_INSERT_ID:在mysql中执行insert语句通过此函数得到自增主键的值
  40. -->
  41. <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
  42. SELECT LAST_INSERT_ID()
  43. </selectKey>
  44. insert into user(username,birthday,sex,address,detail,score) values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
  45. </insert>
  46.  
  47. <!-- 根据主键id删除用户
  48. 如果parameterType为简单类型,#{}里边的名称可以任意,不限定为value
  49. -->
  50. <delete id="deleteUserById" parameterType="java.lang.Integer">
  51. delete from user where id=#{id}
  52. </delete>
  53.  
  54. <!-- 根据id更新用户信息
  55. parameterType:传入更新的用户的id,传入要更新的用户的信息
  56. -->
  57. <update id="updateUserById" parameterType="cn.itcast.mybatis.po.User">
  58. update user set username=#{username},sex=#{sex},birthday=#{birthday}
  59. where id=#{id}
  60. </update>
  61. </mapper>

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中的配置不同:

  1. 添加用户:
  2. mysql数据库的user表添加一条记录。
  3. <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
  4. <!-- 主键返回
  5. keyProperty:表示将主键值存储到User对象的哪个属性中
  6. order SELECT LAST_INSERT_ID()执行时机,插入语句执行之后
  7. resultType:取到id的类型
  8. LAST_INSERT_ID:在mysql中执行insert语句通过此函数得到自增主键的值
  9. -->
  10. <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
  11. SELECT LAST_INSERT_ID()
  12. </selectKey>
  13. insert into user(username,birthday,sex,address,detail,score) values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
  14. </insert>
  15.  
  16. mysql实现:
  17. <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
  18. SELECT LAST_INSERT_ID()
  19. </selectKey>
  20. oracle实现:
  21. <selectKey resultType="java.lang.Integer" order="BEFORE"
  22. keyProperty="id">
  23. SELECT 自定义序列.NEXTVAL FROM DUAL
  24. </selectKey>

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

  1. public class Mybatis_insert {
  2. public static void main(String[] args) throws IOException {
  3. //创建的会话工厂SqlsessionFactory
  4. String resource = "SqlMapConfig.xml";
  5. InputStream inputStream = Resources.getResourceAsStream(resource);
  6. //创建的会话工厂SqlsessionFactory
  7. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  8. //通过工厂得到Sqlsession
  9. SqlSession sqlSession = sqlSessionFactory.openSession();
  10. try {
  11. //由于在SqlMapConfig.xml加载mapper.xml,selectOne方法中可以找到statement的id
  12. //通过SqlSession操作数据库
  13. //第一个参数:指定statement的id
  14. //第二个参数:要传入的输入参数
  15. //插入user对象
  16. User user = new User();
  17. user.setUsername("张三丰");
  18. user.setSex("1");
  19. sqlSession.insert("test.insertUser", user);
  20. //获取对象的主键值
  21. System.out.println(user.getId());
  22. //提交事务
  23. sqlSession.commit();
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }finally{
  27. //关闭Sqlsession
  28. sqlSession.close();
  29. }
  30. }
  31. }

上面代码中常用类的介绍

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、 创建Executor,SqlSession所有操作都是通过Executor完成,mybatis源码如下:

  1. if (ExecutorType.BATCH == executorType) {
  2. executor = new BatchExecutor(this, transaction);
  3. } else if (ExecutorType.REUSE == executorType) {
  4. executor = new ReuseExecutor(this, transaction);
  5. } else {
  6. executor = new SimpleExecutor(this, transaction);
  7. }
  8. if (cacheEnabled) {
  9.    executor = new CachingExecutor(executor, autoCommit);
  10. }

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

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

三.与Hibernate的不同

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

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

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

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

关于MyBatis的工作流程的更多相关文章

  1. Mybatis的工作流程

    MyBatis工作流程 1:加载配置文件(mybatis-config.xml . *...Mapper.xml)并初始化, 将SQL的配置信息加载成为一个个MappedStatement对象(包括了 ...

  2. 关于MyBatis的工作流程和与JDBC的比较与Hibernate的比较

    一.传统的JDBC的方式 1.从一个jdbc程序开始 public static void main(String[] args) { Connection connection = null; Pr ...

  3. MyBatis的几个重要概念和工作流程

    MyBatis 几个重要的概念 Mapper 配置: Mapper 配置可以使用基于 XML 的 Mapper 配置文件来实现,也可以使用基于 Java 注解的 MyBatis 注解来实现,甚至可以直 ...

  4. mybatis(五)mybatis工作流程

    转载:https://www.cnblogs.com/wuzhenzhao/p/11103017.html 先来看一下MyBatis 的编程式使用的方法: public void testMapper ...

  5. Mybatis第一篇【介绍、快速入门、工作流程】

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

  6. springmvc 运行原理 Spring ioc的实现原理 Mybatis工作流程 spring AOP实现原理

    SpringMVC的工作原理图: SpringMVC流程 . 用户发送请求至前端控制器DispatcherServlet. . DispatcherServlet收到请求调用HandlerMappin ...

  7. MyBatis 工作流程及插件开发

    1. MyBatis 框架分层架构 2. MyBatis 工作流程 获取 SqlSessionFactory 对象: 解析配置文件(全局映射,Sql映射文件)的每一个信息,并保存在Configurat ...

  8. SpringMVC的工作流程?Mybatis和hibernate区别?

    SpringMVC的工作流程?1. 用户发送请求至前端控制器DispatcherServlet2. DispatcherServlet收到请求调用HandlerMapping处理器映射器.3. 处理器 ...

  9. Mybatis工作流程及其原理与解析

    Mybatis简介:    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBat ...

随机推荐

  1. 统计计算与R语言的资料汇总(截止2016年12月)

    本文在Creative Commons许可证下发布. 在fedora Linux上断断续续使用R语言过了9年后,发现R语言在国内用的人逐渐多了起来.由于工作原因,直到今年暑假一个赴京工作的机会与一位统 ...

  2. sprintf的缓冲区溢出

    sprintf的缓冲区溢出 分类: 技术2010-03-07 15:26 362人阅读 评论(0) 收藏 举报 今天,调试sector的时候遇到一个特奇怪的问题,程序会在取string的c_str() ...

  3. 零基础学习hadoop到上手工作线路指导

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

  4. Bzoj-2190 仪仗队 欧拉函数

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2190 简单的欧拉函数题,实际上就是求gcd(x,y)=1, 0<=x,y<=n ...

  5. mysql 查询多个id

    select * from b1 where find_in_set('4',id); select * from b1 where id in (1,2,3,22);

  6. Bugs及解决方案列表

    Bugs及解决方案列表(以下实例默认运行环境都为Standard mode): 如何在IE6及更早浏览器中定义小高度的容器? 方法: #test{overflow:hidden;height:1px; ...

  7. 查看linux中的TCP连接数【转】

     转自:http://blog.csdn.net/he_jian1/article/details/40787269 查看linux中的TCP连接数 本文章已收录于:   计算机网络知识库  分类: ...

  8. JavaScript 要点(十六)RegExp 对象

    RegExp:是正则表达式(regular expression)的简写. RegExp 对象 正则表达式是描述字符模式的对象. 正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大 ...

  9. HTML超出文本多行截取代码

    HTML超出文本多行截取代码如下: HTML: <div class="sytm-text-1">      <p>           沈阳网页制作公司有 ...

  10. cocos2d-x中,简单html富文本显示

    作者:HU 转载请注明,原文链接:http://www.cnblogs.com/xioapingguo/p/4037414.html  虽然自从cocos2d-x更新到3.0后,使用freetype, ...