mybatis复习(二)
简介
mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql语句本身,
而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
MyBatis工作原理
1.读取配置文件,配置文件配置的是数据库连接的信息
2.加载映射文件(Mapper) 文件里面配置了sql语句
3.构建会话工厂
4.构造会话对象 由会话工厂创建SqlSession对象,该对象包含了执行SQL的所有方法
5.根据sqlSession创建dao(指的是查询的一个接口)接口的代理对像 通过代理对象执行(自己定义的)增删改查方法
MyBatis的核心对象
1.SqlSessionFactory对象线程安全,一旦被创建在整个执行期间都会存在.主要作用就是构建SqlSession,SqlSessionFactory对象是通过
SqlSessionFactoryBuilder读取xml配置文件配置创建的.
2.SqlSession他是应用程序与持久层之间执行交互操作的一个单线程对象,主要作用执行持久化操作,线程不安全使用范围最好在一个方法
或一次请求中,不可以放到一个类的静态字段,使用完后及时关闭.
映射文件的主要元素(xml)
<resultMap id="userMap" type="user" > ----id唯一标识 -----type 表示是封装到哪个实体类 这里是Account类
<id property="id" column="id"></id> -----id表示哪一列是主键
<result property="username" column="username"></result>property是实体类Account类的字段 column是数据库字段
一对一 在pojo中 将一方的对象作为另一方的属性
<association property="user" javaType="user"><!--property表示封装哪个对象,colum表示通过那个字段封装-->
<id property="id" column="id"></id>-----id表示哪一列是主键
<result column="username" property="username"></result>property是实体类Account类的字段 column是数据库字段
</association >
一对多 将多的一方的封装为List<多的一方> 作为一的一方pojo的属性
<collection>
.............
</collection>
</resultMap>
xml方式 映射文件中的属性和sql注入问题
--resultType 属性: 用于指定结果集的类型。
--parameterType 属性 用于指定传入参数的类型。如果为我们要传入的是一个类的对象,所以类型就写类的全
名称。
--如果插入数据时某个字段自增 可以使用keyProperty接收主键返回值,id指的是自增字段
keyProperty="id" useGeneratedKeys="true" 设置主键自僧
模糊查询时 不直接在sql语句中使用% 而是在方法中拼接%
--sql 语句中使用#{}字符: 它代表占位符,相当于原来
jdbc 部分所学的,都是用于执行语句时替换实际的数
据。 具体的数据是由#{}里面的内容决定的。
#{}中内容的写法: 由于数据类型是基本类型,所以此处可以随意写。
--sql语句拼接时不建议使用${} 会引起sql注入, 建议使用 #{} 表示一个占位符号
例如 :模糊查询 select * from user where username like '%${value}%'
正确写法 select * from user where username like concat( '%' ,#{value} ,'%') 使用concat()函数拼接
开启注解 不再写xml
使用注解 不再使用resource而使用class
配置文件
<mappers>
<mapper class="dao.IUserDao"/>
</mappers>
Mybatis 与 JDBC 编程的比较
1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。 解决: 在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
2.Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。 解决: 将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
3.向sql语句传参数麻烦,因为sql语句的where 条件不一定,可能多也可能少,占位符需要和参数对应。 解决: Mybatis自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的 类型。
4.对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对 象解析比较方便。 解决: Mybatis自动将 sql执行结果映射至 java 对象,通过statement中的resultType 定义输出结果的 类型
实体类和数据库字段不一致
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称
动态sql
----<if> 判断语句,用于单条件分支判断 例如
<select id="findByUser" resultType="user" parameterType="user">
select * from user where 1=1
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null">
and address like #{address}
</if>
</select>
----<choose><when><otherwise> 相当于javaz中swit-ch...case...default语句.
例如
select * from user where 1=1
<choose>
<when test="username!=null and username !='' " >
and username like concat('%',#{username},'%')
</when>
<when>.........</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
----为了简化上面 where 1=1 的条件拼装,我们可以采用<where>标签来简化开发。
------SQL 语句:实现 select * from user WHERE id in (41,42,43); 这样的功能
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
-------<bind> 模糊查询拼接%
关联映射
一对一
<!-- 一对一-->
<mapper namespace="dao.IAccuntDao">
<!--定义封装account和user两个表-->
<resultMap id="Map" type="account"> <!--type 表示是封装到哪个实体类 这里是Account类-->
<id property="ID" column="AID"></id><!--property是实体类Account类的字段 column是数据库字段-->
<result property="UID" column="UID"></result>
<result property="MONEY" column="MONEY"></result>
<!--一对一关系映射,封装user内容-->
<association property="user" javaType="user"><!--property表示封装哪个对象,colum表示通过那个字段封装-->
<id property="id" column="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
</association>
</resultMap>
<!--查询所有账户 同时包含用户名和地址信息 那么包含两张表一个是user表一个是account表-->
<select id="findAllAccount" resultMap="Map">
SELECT u.*,a.ID as aid,a.MONEY from account a, user u WHERE a.UID = u.id;
</select>
</mapper>
一对多
在 多的一方添加一的一方的主键作为外键<collection>标签
用户---订单
<!-- 1对多 -->
<mapper namespace="dao.IUserDao">
<!--定义user的map-->
<resultMap id="userMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!--配置list集合映射-->
<collection property="accounts" ofType="account"><!--accounts 是User类里面的字段-->
<id column="aid" property="ID"></id>
<result column="UID" property="UID"></result>
<result column="MONEY" property="MONEY"></result>
</collection>
</resultMap>
<!-- 配置查询所有操作( //查询所有用户 同时获取到用户下所有账户信息 一对多)-->
<select id="findAll" resultMap="userMap">
select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid
</select>
<!-- 根据用户id查询用户(一)对应的账户(多)信息 -->
<select id="findById" parameterType="Integer" resultMap="userMap">
select u.*,a.id as aid ,a.uid,a.money from user u ,account a where u.id =a.uid and u.id=#{id};
</select>
</mapper>
多对多 产生中间表,引入两张表的主键作为外键
订单------商品
<!-- 多对多 -->
<mapper namespace="dao.IRoleDao">
<!--定义roleMap 因为使用了map所以实体类 Role类的字段可以和数据库字段不一致-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="ROLE_NAME"></result>
<result property="roleDesc" column="ROLE_DESC"></result>
<!--封装user-->
<collection property="users" ofType="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
/*-- 左外连接(多对多 需要中间表)*/
select u.*,r.ID as rid,r.ROLE_NAME,r.ROLE_DESC from role r left outer join user_role ur on r.ID=ur.RID
left outer join user u on u.id = ur.UID;
</select>
</mapper>
延迟加载sql缓存
-----一级缓存
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
关闭SqlSession .close 再创建缓存消失
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除. commit(),close()等方法时,
就会清空一级缓存
---------二级缓存
二级缓存是 mapper 映射级别的缓存,多个 SqlSession
去操作同一个 Mapper 映射的 sql 语句,多个 SqlSession
可以共用二级缓存,二级缓存是跨 SqlSession 的。
注解开发
@Results 注解 代替的是标签<resultMap>
@Result 中 属性介绍: id 是否是主键字段 column
数据库的列名 property 需要装配的属性名 one 需
要使用的@One 注解(@Result(one=@One)
())) many 需要使用的@Many 注解(@Result(many=@many)()))
@One 注解(一对一) 代替了<assocation>标签,
是多表查询的关键,在注解中用来指定子查询返回单一
对象。 @One 注解属性介绍: select 指定用来多表查询的 sqlmapper
@Many 注解(多对一) 代替了<Collection>标
签,是是多表查询的关键,在注解中用来指定子查询返
回对象集合。 注意:聚集元素用来处理“一对多”的
关系。需要指定映射的 Java 实体类的属性,属性的 ja
vaType (一般为 ArrayList
mybatis复习(二)的更多相关文章
- MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致
MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致 使用ResultMap节点配置信息 在映射文件中 ...
- MyBatis笔记二:配置
MyBatis笔记二:配置 1.全局配置 1.properites 这个配置主要是引入我们的 properites 配置文件的: <properties resource="db.pr ...
- (原创)mybatis学习二,spring和mybatis的融合
mybatis学习一夯实基础 上文介绍了mybatis的相关知识,这一节主要来介绍mybaits和spring的融合 一,环境搭建 1,jar包下载,下载路径为jar包 2,将包导入到java工程中 ...
- 33、mybatis(二)
第十六章回顾SQL99中的连接查询 1)内连接 2)外连接 3)自连接 第十七章回顾hibernate多表开发 1)一对一 2)一对多 3)多对多 第十八章 mybatis一对一映射[学生与身份证] ...
- MyBatis复习
一.对JDBC的总结 1.数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能. 解决方案:使用数据库连接池管理数据库连接. 2.将sql语句硬 ...
- mybatis(二)接口编程 、动态sql 、批量删除 、动态更新、连表查询
原理等不在赘述,这里主要通过代码展现. 在mybatis(一)基础上,新建一个dao包,并在里面编写接口,然后再在xml文件中引入接口路径,其他不变,在运用阶段将比原始方法更节约时间,因为不用再去手动 ...
- MyBatis之二:简单增删改查
这一篇在上一篇的基础上简单讲解如何进行增删改查操作. 一.在mybatis的配置文件conf.xml中注册xml与注解映射 <!-- 注册映射文件 --> <mappers> ...
- Java框架之Mybatis(二)
本文主要介绍 Mybatis(一)之后剩下的内容: 1 mybatis 中 log4j的配置 2 dao层的开发(使用mapper代理的方式) 3 mybatis的配置详解 4 输入输出映射对应的类型 ...
- springboot集成mybatis(二)
上篇文章<springboot集成mybatis(一)>介绍了SpringBoot集成MyBatis注解版.本文还是使用上篇中的案例,咱们换个姿势来一遍^_^ 二.MyBatis配置版(X ...
- spring boot整合mybatis方式二
方式二: pom文件导入maven依赖: <dependency> <groupId>org.springframework.boot</groupId> < ...
随机推荐
- 【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
问题描述 Azure Redis Cluster 在增加分片数时失败,错误消息为: ResponseBody: { "error": { "details": ...
- 文心一言 VS 讯飞星火 VS chatgpt (208)-- 算法导论15.4 5题
五.设计一个 O($n^2$) 时间的算法,求一个 n 个数的序列的最长单调递增子序列.要写代码的时候,请用go语言. 文心一言,抛panic: 在 Go 语言中设计一个 O(n^2) 时间复杂度的算 ...
- Java 多线程------多线程的创建(2),方式一:继承于Thread类
1 package com.bytezero.threadexer; 2 3 /** 4 * 创建两个分线程,其中一个线程遍历100以内的偶数,另一个线程遍历100以内的奇数 5 * 6 * 7 * ...
- node.js在win7下安装,并测试是否安装成功
1.node.js去官网下载,下载完,像平时安装软件一样 2.把下面的测试文件,放到安装目录下,本文是放到:D:\Program Files\nodejs下 var http = require(&q ...
- springboot多数据源配置理解
今天研究项目的多数据源配置,产生了一点疑惑,有很多地方没有指定数据源,那么spring如何知道连接哪一个呢?让我们从头开始梳理吧. 首先是数据源配类 其中使用到了两个数据源,项目采用读写分离,一个主库 ...
- obs 录制教程 手机录屏用 向日葵 手机投屏 能用有线用有线的连接
obs 录制教程 手机录屏用 向日葵 手机投屏 稍微有点卡 华为手机有个投屏 笔记本不支持这个 miracast 淘宝有卖 投屏设备的,搜 miracast 100多米 免费的就用向日葵就得了. 最新 ...
- ubuntu重启网卡
1.关闭接口:sudo ifconfig eth0 down 2.然后打开:sudo ifconfig eth0 up
- 【jQuery】(8)---jquery Ajax
jquery ajax 一.AJAX 概述 1.什么是 AJAX? 特点 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使 ...
- C++保证线程安全的方式
1.互斥量 可以确保同一时间只有一个线程访问临界区,防止出现竞态条件. 2.原子操作 std::atomic<int> mutex(1); 对原子变量的操作是线程安全的. 3.读写锁 st ...
- C++ 派生类对象的构造与析构过程
C++ 派生类对象的构造与析构过程 因为基类的成员变量和派生类的成员变量在内存中的连续的(下面程序会验证这一点),如下图所示: 所以构造派生类对象的时候,构造成员变量的过程就像入栈一样: 那么很自然, ...