以下所有的示例都将操作user、orders、orderdetail表

| Table | Create Table
| user  | CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) NOT NULL COMMENT '用户名称',`sex` char(1) DEFAULT NULL COMMENT '性别',`address` varchar(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8         |+----+-----------+------+--------------+
| id | username  | sex  | address      |
+----+-----------+------+--------------+
|  1 | 王五      | 1    | NULL         |
| 10 | 张三      | 1    | 北京市       |
| 16 | 张小明    | 1    | 陕西西安     |
| 22 | 陈小明    | 1    | 陕西西安     |
| 24 | 张三丰    | 1    | 陕西西安     |
| 25 | 陈小明    | 1    | 陕西西安     |
| 26 | 王五      | NULL | NULL         |
+----+-----------+------+--------------+| orders | CREATE TABLE `orders` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL COMMENT '下单用户id',`number` varchar(32) NOT NULL COMMENT '订单号',`createtime` datetime NOT NULL COMMENT '创建订单时间',`note` varchar(100) DEFAULT NULL COMMENT '备注',PRIMARY KEY (`id`),KEY `FK_orders_1` (`user_id`),CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8                |+----+---------+---------+---------------------+------+
| id | user_id | number  | createtime          | note |
+----+---------+---------+---------------------+------+
|  3 |       1 | 1000010 | 2015-02-04 13:22:35 | NULL |
|  4 |       1 | 1000011 | 2015-02-03 13:22:41 | NULL |
|  5 |      10 | 1000012 | 2015-02-12 16:13:23 | NULL |
+----+---------+---------+---------------------+------+| orderdetail | CREATE TABLE `orderdetail` (`id` int(11) NOT NULL AUTO_INCREMENT,`orders_id` int(11) NOT NULL COMMENT '订单id',`items_id` int(11) NOT NULL COMMENT '商品id',`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',PRIMARY KEY (`id`),KEY `FK_orderdetail_1` (`orders_id`),KEY `FK_orderdetail_2` (`items_id`),CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8           |+----+-----------+----------+-----------+
| id | orders_id | items_id | items_num |
+----+-----------+----------+-----------+
|  1 |         3 |        1 |         1 |
|  2 |         3 |        2 |         3 |
|  3 |         4 |        3 |         4 |
|  4 |         4 |        2 |         3 |
+----+-----------+----------+-----------+

mybatis介绍

什么是mybatis

mybatis是一个半ORM(对象关系映射),优秀的持久性框架。mybatis的出现极大的简化了JDBC编码过程中存在的硬编码、设置参数、获取结果集。mybatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

mybatis优缺点

优点:

  • 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;
  • 提供XML标签,支持编写动态SQL语句,并可重用与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接。
  • 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持),提供映射标签,支持对象与数据库的ORM字段关系映射;
  • 提供对象关系映射标签,支持对象关系组件维护能够与Spring很好的集成。

缺点:

  • 当字段和关联表比较多的时候对开发的人员编写SQL语句的功底要求比较高。
  • SQL语句依赖于数据库,不可随意更换数据库。

mybatis实现原理

mybatis的三层架构

  • API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  • 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
  • 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

mybatis原理图


执行过程
1)读取 mabatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 mabatis 的数据源、事务、映射

2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 mabatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

3)构造会话工厂:通过 mabatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

5)Executor 执行器:mabatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。

6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。

SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。 因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式。

JDBC编程

getConnection方法

public static Connection connection;public static Connection getConnection(){try {//加载驱动程序Class.forName("com.mysql.jdbc.Driver");System.out.println("数据库驱动加载成功!");connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/stuscore","root","123456");if (connection != null){System.out.println("数据库连接成功");return connection;}} catch (Exception e) {e.printStackTrace();}return null;}

查询过程

//查询操作public static void search(){Connection connection = ConnectionDemo.getConnection();String sql = "select *from student where SID = ?";try {PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,2);ResultSet resultSet = preparedStatement.executeQuery();while(resultSet.next()){int sid = resultSet.getInt("SID");String sname = resultSet.getString("Sname");int sage = resultSet.getInt("Sage");String ssex = resultSet.getString("Ssex");System.out.println("SID:"+sid+" Sname:"+sname+" Sage:"+sage+" Ssex:"+ssex);}preparedStatement.close();resultSet.close();} catch (SQLException e) {e.printStackTrace();}finally {try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}

JDBC编码过程中存在的问题

解决方法

  1. 使用连接池概念每次启动都不用去加载类和驱动包路径、只需要获取一个connection对象
  2. 将SQL和java代码解耦合、将SQL语句放进xml文件之中,只需要在xml文件之中修改SQL语句
  3. mybatis 自动将java对象映射
  4. 将数据库中的字段映射java对象

mybatis 具体操作

查询id = 1的字段

1.Maven中需要引入的依赖

<!--mysql操作--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.40</version></dependency><!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.1</version></dependency>

2.配置主配置文件 并引入依赖(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根标签-->
<configuration><!--数据源配置--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments></configuration>

Tip1:3306后面需要跟的是操作表所在库名
Tip2:这里需要注意在配置的过程不要将属性名与value值打错否则会报错

3.POJO对象(user.java)

public class user{private Integer id;private String username;private String sex;private  String address;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "User7{" +"id=" + id +", username='" + username + '\'' +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}
}

4.mapper接口文件(UserMapper.java)

public interface UserMapper{user getUserById(Integer id);
}

5.配置映射文件 (UserMapper.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace: 一般为接口的全限定类名当不使用的时候:id不能重复,当使用namespace使用的时候:id可以重复 --><mapper namespace="com.pojo.StudentMapper"><!--查询标签:select   id:接口中的方法名  返回值resultType返回指定结果集的类型--><select id="selectStudentById" resultType="com.pojo.user" >select * from student where SID = #{sid}</select>
</mapper>

6.在主配置文件之中配置映射关系

<!--配置映射--><mappers><!-- resource:单个mapper映射,xml和接口可以不再一个目录下在StudentMapper.xml中定义namespace为mapper接口的地址,映射文件通过namespace来找到mapper接口文件 --><!--以下两种不使用本例只使用第一种--><mapper resource="mapper/UserMapper.xml"></mapper><!--单个mapper映射:单个mapper映射,指定mapper接口的地址遵循规则将mapper.xml和mapper.java放在同一个目录下,且文件名相同--><mapper class="com.dao.UserMapper"></mapper><!--package方式:批量的mapper映射遵循的规则:将mapper.xml和mapper.java 放在同一个目录下,且文件名相同--><package name="com.tulun.dao"/></mappers>

映射文件之中还有以下标签

以上三种标签不一一演示我直接贴出之前打过的代码

 <!--插入标签 : insert id:接口方法名  输入参数parameterType值可以忽略useGenerateKeys:true为自增--><insert id="insertUser" parameterType="user">insert into user(id,username,sex,address) values (#{id},#{username},#{sex},#{adress})</insert><!--修改标签resultType不是必须存在的parameterType也可以省略--><update id="updateUser">update user set username= #{username} where id= #{id}</update><!--删除标签resultType、parameterType可以被忽略--><delete id="deleteStudent">delete from user where id = #{id}</delete>

resultType与resultMap

resultType:只能在映射过程之中java对象和数据库的字段必须一致,否则映射不成功。
resultMap:高级映射:当发现java对象的属性名和数据库的字段名不一致的时候可以在xml中定义一个resultMap与之java对象一一对应即可。resultMap还可以实现一对一单表查询以及一对多多表联合查询。

resultMap的使用

<!--处理显性的结果集映射id=作为结果集的标识type指定要映射的Java结果集的全限定类名--><resultMap id="userMap" type="user"><!--column:数据库表对应的行property:Java对象对应的属性--><id column="id" property="id"></id><result column="username" property="name"></result><result column="sex" property="sex"></result><result column="adress" property="adress"></result></resultMap><!--查询标签:select   id:接口中的方法名  返回值resultType返回指定结果集的类型--><select id="selectStudentById" resultMap="userMap" >select * from student where SID = #{sid}</select>

Tip:注意上面代码username部分的变化

一对一映射 association

将user表映射到order表

<resultMap type="com.pojo.Orders" id="OrdersUserResultMap"><!-- 配置映射的订单信息 --><!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个idcolumn:订单信息的唯 一标识 列property:订单信息的唯 一标识 列所映射到Orders中哪个属性--><id column="id" property="id"/><result column="user_id" property="userId"/><result column="number" property="number"/><result column="createtime" property="createtime"/><result column="note" property=note/><!-- 配置映射的关联的用户信息 --><!-- association:用于映射关联查询单个对象的信息property:要将关联查询的用户信息映射到Orders中哪个属性--><association property="user"  javaType="com.pojo.user"><!-- id:关联查询用户的唯 一标识column:指定唯 一标识用户信息的列javaType:映射到user的哪个属性--><id column="user_id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="address" property="address"/></association>
</resultMap>

一对多映射 collection

<resultMap type="com.pojo.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap"><!-- 订单信息 --><!-- 用户信息 --><!-- 使用extends继承,不用在中配置订单信息和用户信息的映射 --><!-- 订单明细信息一个订单关联查询出了多条明细,要使用collection进行映射collection:对关联查询到多条记录映射到集合对象中property:将关联查询到多条记录映射到cn.itcast.mybatis.po.Orders哪个属性ofType:指定映射到list集合属性中pojo的类型--><collection property="orderdetails" ofType="com.pojo.Orderdetail"><!-- id:订单明细唯 一标识property:要将订单明细的唯 一标识 映射到cn.itcast.mybatis.po.Orderdetail的哪个属性--><id column="orderdetail_id" property="id"/><result column="items_id" property="itemsId"/><result column="items_num" property="itemsNum"/><result column="orders_id" property="ordersId"/></collection>
</resultMap>

半夜写出来的东西 可能有的地方知识不够齐全。后面会写一篇自定义mybatis的文章。(跟着B站大佬搞出来的东西)还有好多知识没写出来。

Mybatis从头学到jio(一)相关推荐

  1. mybatis从头学到jio(二)

    前情回顾 mybatis从头学到jio(一) 这里写目录标题 前情回顾 ${} 与 #{}区别 #{} ${} typeAliases标签 动态SQL if标签 trim标签 where标签 fore ...

  2. 数据分析从头学_数据新闻学入门指南:让我们从头开始构建故事

    数据分析从头学 by Mina Demian 由Mina Demian 数据新闻学入门指南:让我们从头开始构建故事 (A Beginner's Guide to Data Journalism: Le ...

  3. 记事本写python怎么运行-从头学Python之编写可执行的.py文件

    Python可是真强大.但他具体是怎么强大的,让我们一点一点来了解吧(小编每天晚上下班回家会抽时间看看教程,多充实下自己也是好的). 废话不多说,就讲一下这个背景吧: 事情是这个样子的~本着好学的精神 ...

  4. Linux 从头学 01:CPU 是如何执行一条指令的?

    摘自:Linux 从头学 01:CPU 是如何执行一条指令的? 作者:IOT物联网小镇 发布时间:2021-07-02 08:22:43 网址:https://blog.csdn.net/jchen1 ...

  5. 33岁想从头学做网页设计_从头开始设计精美的移动应用

    33岁想从头学做网页设计 by Harshita Arora 通过Harshita Arora 从头开始设计精美的移动应用 (Designing beautiful mobile apps from ...

  6. 33岁想从头学做网页设计_从头开始设计字体-并在24小时内将其提交给Google字体...

    33岁想从头学做网页设计 by James Barnard 詹姆斯·巴纳德(James Barnard) 从头开始设计字体-并在24小时内将其提交给Google字体 (Designing a font ...

  7. Linux从头学09:x86 处理器如何进行-层层的内存保护?

    作 者:道哥,10+年的嵌入式开发老兵. 转 载:欢迎转载文章,转载需注明出处. 文章目录 实模式:bootloader 为程序计算段的基地址 保护模式:bootloader 为自己创建段描述符 确定 ...

  8. 【caffe2从头学】:3.3.Brewing Models(快速构建模型)

    本片文章是我的[caffe2从头学]系列中的一篇,如果想看其他文章,请看目录: 0.目录 1.快速开始 1.1.什么是caffe2 ? 1.2.安装caffe2 2.学习caffe2 3.caffe2 ...

  9. 从头学前端-35:溢出处理

    大家好,我是一碗周,一个不想被喝(内卷)的前端.如果写的文章有幸可以得到你的青睐,万分有幸~ 这是[从头学前端]系列文章的第三十五篇-<溢出处理> 本篇文章介绍CSS中内容溢出的处理,主要 ...

最新文章

  1. 一本可能提升思考水平 10 倍的书
  2. vim7.4官方源码在vs2013的编译方法及问题总结
  3. 如何选择正确的HTTP状态码
  4. .Net Core 2.2升级3.1的避坑指南
  5. [bzoj3994] [SDOI2015]约数个数和
  6. 《SQL Server 必知必会》读书笔记
  7. C#获取IP和整数IP方法
  8. coreldraw x4忽略视图样式补丁_80%的人都忽略了PPT画布之外的用法,但这6点真的很实用...
  9. [微软中国]秋季校园招聘开启了(可内推)
  10. STM32F103_study57_The punctual atoms(STM32 Port multiplexing and remapping configuration)
  11. linux dd销毁数据,dd命令详解(清除硬盘数据)
  12. 数据交换方式(电路交换、数据报交换、分组交换)
  13. 汇编语言 使用按键控制51单片机的数码管显示0~F
  14. 如何自动生成表关联关系关系图 或 实体关系模型图------EER图
  15. 以麒麟音乐为例,教你如何构建专属自己的音乐播放器
  16. 了解一个人最好的方式就是和他(她)去旅行,
  17. docker logs 查看docker容器日志详解
  18. 药品的泡罩包装技术介绍
  19. Python中的单行、多行、中文注释
  20. Tomcat下log4j日志文件 配置过程

热门文章

  1. Nature:清华唐传祥团队成功进行“稳态微聚束”首个原理验证实验
  2. NE564锁相环使用心得
  3. CCSA学习笔记 第一节 思科安全解决方案综述
  4. P1265 公路修建(Prim最小生成树)
  5. Win7系统下如何成功安装 Microsoft Applocale (附安装软件技巧)
  6. 基于全局和局部对比自监督学习的高分辨率遥感图像语义分割day3 - 网络结构
  7. MobLink网页跳转app指定界面技术简介之 URL Scheme
  8. SSM的医药管理系统ssm医药系统ssm药品管理系统ssm医药进销存系统医院JSP药品管理系统ssm药品进销存系统
  9. Scrum 学习篇 -- Backlog之浅析 (三)
  10. 240320俄罗斯方块java,java 俄罗斯方块 游戏源码