给“小白”漫画+图示讲解MyBatis原理,就问香不香!

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cb/cbc1b08f8d1a2cfc496dfcbe233d5fd3.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MyBatis一款后起之秀的持久层框架ORM,支持自定义SQL、存储过程和高级映射,相对于Hibernate算是半自动化的框架,在国内行业内非常流行。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d4/d4aaff018182af74259257f0bed01548.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bd/bdb1781347e6b1bc8061e326a3bafee8.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常规的JDBC操作,配置相应的数据库连接的信息,比如账户密码等,应用加载数据库驱动并手动创建数据库连接,编写业务sql并设置其入参生成Statement对象用于执行,获取结果数据集,及时释放持有资源,再对结果集进行数据处理。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1c/1cafbfb7b0bd372f74a75d0c60ea9d83.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"加载驱动、创建连接、返回结果、释放资源等等都是重复的体力活,为了不把自己忙碌成代码的搬运工,这些都可以封装由框架去做,而自己关注最核心的业务层,也就是sql相关的逻辑。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6a/6aec10c36da11b719dc9d51046b384a0.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/20/20bffd818b5b279be2d13de44b1cbfdf.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"把业务相关的sql逻辑配置在mapper.xml文件中,包括入参和返回的结果集,这其中会涉及到数据库中的字段和Java对象的字段之间的映射,一般如果字段名和类型相同可以通过MyBatis的自动映射即可,如果差别较大,则需要手动映射,甚至自定义类型处理typeHandlers。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每个MyBatis的应用都会以一个SqlSessionFacotry的实例为核心的,SqlSessionFacotryBuilder通过build加载核心配置文件mybatis-config.xml,从而创建SqlSessionFacotry,再由SqlSessionFacotry创建SqlSession。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"核心配置文件mybatis-config.xml包含mapper.xml文件,在SqlSessionFacotryBuilder加载核心配置文件时一同加载进来,形成Configuration实例,其中mapper.xml的每个select/update/insert/delete节点都会最终生成MappedStatement对象,简单理解就是对应的完整sql语句,类似JDBC的Statement角色。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"实际上核心配置文件除了包含mapper.xml,还包含数据库连接、事务、类型别名、类型处理器、插件、环境配置等等。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/99/999abb41ac6e67946921b9e598d671ec.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/da/da0a56a85b28f923ad43897886431517.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"1. 准备工作:创建数据库和项目"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建数据库脚本"}]},{"type":"codeblock","attrs":{"lang":"sql"},"content":[{"type":"text","text":"CREATE DATABASE `mybatisdemo`;\nUSE mybatisdemo;\nCREATE TABLE `user` (\n`id` int(11) NOT NULL AUTO_INCREMENT,\n`name` varchar(20) DEFAULT NULL,\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建maven项目,并在pom中添加mybatis和mysql驱动依赖包"}]},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n org.mybatis\n mybatis\n 3.5.5\n\n\n MySQL\n mysql-connector-java\n 5.1.40\n"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.添加核心配置文件mybatis-config.xml"}]},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\nn PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"\n \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"3. UserMapper.xml的配置 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"包含了插入数据的insert和查询数据的select,其中插入式通过设置useGeneratedKeys为true,返回自增id。"}]},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\nn PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n \n \n insert into user(name) values(#{name})\n \n \n \n \n \n \n \n \n"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"4. UserMapper.xml相对应Dao"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"UserMapper.java的代码如下,包含了相应插入和查询接口"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"package com.zhaiqianfeng.user;\n\npublic interface UserMapper {\n User getUserById(int id);\n int insertUser(User user);\n}"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"5. 创建SqlSession并验证"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一切都准备好之后,开始创建SqlSession并执行"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public static void main( String[] args ) throws IOException {\n String config= \"mybatis-config.xml\";\n InputStream inputStream= Resources.getResourceAsStream(config);\n //SqlSessionFactoryBuilder加载核心(+mapper)配置文件并创建SqlSessionFactory\n SqlSessionFactory sqlSessionFactory= \n new SqlSessionFactoryBuilder().build(inputStream);\n\n //创建SqlSession\n try(SqlSession sqlSession=sqlSessionFactory.openSession()) {\n //获取mapper\n UserMapper mapper = sqlSession.getMapper(UserMapper.class);\n\n User user = new User();\n user.setName(\"chris\");\n\n //执行操作\n mapper.insertUser(user);\n sqlSession.commit(); //flush\n System.out.println(\"获取自增id:\" + user.getId());\n\n user = mapper.getUserById(user.getId());\n System.out.println(\"刚刚入库的user对象\" + user);\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此时的项目结构是这样的"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/59/598fff757f68f67e0769824b1a68e101.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"运行main之后打印"}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"获取自增id:1 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"刚刚入库的user对象User(id=1, name=chris)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"查看数据库"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/07/07953203a0fcd83aadabb986dda3a91f.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"优化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于本例中的数据库表字段和Java对象的字段名一致,所以在UserMapper.xml中的resultMap可以省略,直接用resultType,mybatis会悄悄自动映射生成resultMap,省略后如"}]},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\nn PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n \n insert into user(name) values(#{name})\n \n \n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"还可以再简化,比如使用别名替换权限定名(com.zhaiqianfeng.user.User)等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"PS:本篇文章主要是通过漫画和图并结合对比常规JDBC来讲解MyBatis的原理和设计目标,比较适合新手阅读,感谢阅读。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":9}}],"text":"源码地址:https://github.com/zhaiqianfeng/codeceo-demo/tree/master/mybatis/mybatis-demo-1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(完)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最新、更多漫画请关注微信公众号:"},{"type":"text","marks":[{"type":"strong"}],"text":"码农神说"},{"type":"text","text":"。转载开白可联系助手,微信号:codeceo-01"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"相关阅读"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/81029df24c99eb5911edf3bbb","title":""},"content":[{"type":"text","text":"辟谣:程序员不配谈恋爱?你错的可以!真相来了"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/41846b3fa362bbef382c6babf","title":null},"content":[{"type":"text","text":"面试官:CAP 都搞不清楚,别跟我说你懂微服务!"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/b7195f780e45dd68a827dffb1","title":null},"content":[{"type":"text","text":"看看吧!28岁退休的程序员和P8都干了啥"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/56c1c92104e7b4e0ae67ddfca","title":null},"content":[{"type":"text","text":"千万不能让程序员给娃娃取名字"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/8dfe1ea299db76c33e37a4056","title":null},"content":[{"type":"text","text":"漫画 | 啊哈,给我一碗孟婆汤"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/c2c7ecc71c17ec054e9c62fd3","title":null},"content":[{"type":"text","text":"漫画 | 人工智能之机械基"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章