Mybatis
2021-10-14 14:35:20 31 举报
AI智能生成
Mybatis
作者其他创作
大纲/内容
多表查询
一对一(多对一)
举例
举例:
人和身份证号就是一对一, 一个人只能有一个身份证号
一个身份证号只能属于一个人
特例:
如果拿出每一个账户,他都只能属于一个用户。
所以Mybatis就把多对一看成了一对一。
人和身份证号就是一对一, 一个人只能有一个身份证号
一个身份证号只能属于一个人
特例:
如果拿出每一个账户,他都只能属于一个用户。
所以Mybatis就把多对一看成了一对一。
//从表实体应该包含一个主表实体的对象引用
Account实体类中含:private User user;
Account实体类中含:private User user;
映射文件使用assocation标签
一对多
举例
一个用户可以有多个账户
一个账户只能属于一个用户(多个账户也可以属于同一个用户)
一个账户只能属于一个用户(多个账户也可以属于同一个用户)
一对多关系映射:主表实体应该包含从表实体的集合引用
User实体类中含:private List accounts;
User实体类中含:private List
设计步骤
1、建立两张表:用户表,账户表
让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
2、建立两个实体类:用户实体类和账户实体类
让用户和账户的实体类能体现出来一对多的关系
3、建立两个配置文件
用户的配置文件
账户的配置文件
4、实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息
当我们查询账户时,可以同时得到账户的所属用户信息(一对一)
让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
2、建立两个实体类:用户实体类和账户实体类
让用户和账户的实体类能体现出来一对多的关系
3、建立两个配置文件
用户的配置文件
账户的配置文件
4、实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息
当我们查询账户时,可以同时得到账户的所属用户信息(一对一)
映射文件代码
collection是用于建立一对多中集合属性的对应关系,property值为主表中集合引用的名字 ofType用于指定集合元素的数据类型
UserDao.xml
<resultMap id="userAccountMap" type="com.aaa.domain.User">
<id property="userId" column="id"></id>
......
<result property="userBirthday" column="birthday"></result>
<collection property="accounts" ofType="account">
<id property="id" column="aid"></id>
注意从表的column值不能与主表的id一样,否则会出现封装为null值,需要起别名
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
UserDao.xml
<resultMap id="userAccountMap" type="com.aaa.domain.User">
<id property="userId" column="id"></id>
......
<result property="userBirthday" column="birthday"></result>
<collection property="accounts" ofType="account">
<id property="id" column="aid"></id>
注意从表的column值不能与主表的id一样,否则会出现封装为null值,需要起别名
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
多对多
举例
用户和角色
一个用户可以有多个角色
一个角色可以赋予多个用户
一个用户可以有多个角色
一个角色可以赋予多个用户
//多对多关系映射:各自包含对方一个集合引用
User实体类中含:private List<Role> roles;
Account实体类中含:private List<User> users;
User实体类中含:private List<Role> roles;
Account实体类中含:private List<User> users;
设计步骤
1、建立两张表:用户表,角色表
让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
2、建立两个实体类:用户实体类和角色实体类
让用户和角色的实体类能体现出来多对多的关系
各自包含对方一个集合引用
3、建立两个配置文件
用户的配置文件
角色的配置文件
4、实现配置:
当我们查询用户时,可以同时得到用户所包含的角色信息
当我们查询角色时,可以同时得到角色的所赋予的用户信息
让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
2、建立两个实体类:用户实体类和角色实体类
让用户和角色的实体类能体现出来多对多的关系
各自包含对方一个集合引用
3、建立两个配置文件
用户的配置文件
角色的配置文件
4、实现配置:
当我们查询用户时,可以同时得到用户所包含的角色信息
当我们查询角色时,可以同时得到角色的所赋予的用户信息
映射文件代码
同一对多
在UserDao.xml和AccountDao.xml都需要写<collection>标签
注意:实体类名和数据库名如果不一致 要定义ResultMap
表之间的column值不能一致,否则会出现封装为null值,需要起别名
在UserDao.xml和AccountDao.xml都需要写<collection>标签
注意:实体类名和数据库名如果不一致 要定义ResultMap
表之间的column值不能一致,否则会出现封装为null值,需要起别名
连接池与事务深入
MyBatis使用自己的数据源
UNPOOLED 不使用连接池的数据源
POOLED 使用连接池的数据源
JNDI 使用JNDI实现的数据源
事务
Mybatis中事务的提交方式,本质上就是调用JDBC的setAutoCommit()来实现事务控制
MyBatis默认手动提交事务
增删改都要session.commit()
开启自动提交事务
session = factory.openSession(true);
MyBatis查询缓存
说明
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
mybaits提供一级缓存,和二级缓存。
一级缓存
工作原理
使用场景
二级缓存
工作原理
分支主题
说明
二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。
每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
二级缓存是以序列化的形式存储的,存放的内容是数据而不是对象,所以通过两个不同session对象得到的dao结果集不等
开启二级缓存
mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。
禁用二级缓存
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
刷新缓存
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
<insert id="insertUser" parameterType="com.mybaits.entity.User" flushCache="true">
Mybatis Cache参数
lushInterval(刷新间隔)
可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)
可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)
可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
eviction(收回策略)
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
示例
二级缓存应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,
业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
二级缓存的局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好
MyBatis延迟加载
延迟加载
优点
在需要用到数据时才进行加载,不需要用到数据时就不加载数据。
延迟加载也称懒加载.
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,
因为查询单表要比关联查询多张表速度要快
延迟加载也称懒加载.
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,
因为查询单表要比关联查询多张表速度要快
缺点
因为只有当需要用到数据时,才会进行数据库查询,
这样在大批量数据查询时,因为查询工作也要消耗时间,
所以可能造成用户等待时间变长,造成用户体验下降
这样在大批量数据查询时,因为查询工作也要消耗时间,
所以可能造成用户等待时间变长,造成用户体验下降
一对多,多对多:通常情况下我们都是采用延迟加载。
多对一,一对一:通常情况下我们都是采用立即加载。
多对一,一对一:通常情况下我们都是采用立即加载。
实现
一对一延迟加载
使用association中的select指定延迟加载去执行的statement的映射id(即唯一标识)
<!-- 它是用于指定从表方的引用实体属性的 -->
column : 填写我们要传递给 select 映射的参数
<association
property="user"
javaType="user"
select="com.google.dao.UserDao.findById"
column="uid">
</association>
column : 填写我们要传递给 select 映射的参数
<association
property="user"
javaType="user"
select="com.google.dao.UserDao.findById"
column="uid">
</association>
一对多延迟加载
使用collection中的select指定延迟加载去执行的statement的映射id
<!-- collection 是用于建立一对多中集合属性的对应关系
ofType 用于指定集合元素的数据类型
select 是用于指定查询账户的唯一标识(账户的 dao 全限定类名加上方法名称)
column 是用于指定使用哪个字段的值作为条件查询
-->
<collection
property="accounts"
ofType="account"
select="com.google.dao.AccountDao.findByUid"
column="id">
</collection>
ofType 用于指定集合元素的数据类型
select 是用于指定查询账户的唯一标识(账户的 dao 全限定类名加上方法名称)
column 是用于指定使用哪个字段的值作为条件查询
-->
<collection
property="accounts"
ofType="account"
select="com.google.dao.AccountDao.findByUid"
column="id">
</collection>
使用association实现延迟加载
使用association中的select指定延迟加载去执行的statement的id。
在mybatis核心配置文件中的配置
mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。
基本步骤
1.加入maven依赖
2.创建Dao接口:定义了操作数据库的方法
3.创建mapper文件,也叫sql映射文件:写sql语句的,和接口方法对应的sql语句
4.创建mybatis的主配置文件:1)连接数据库 2)指定mapper文件的位置(target/classes下)
5.使用Mybatis的对象 SqlSession执行sql语句
CRUD
增强的jdbc,访问数据库,执行crud
使用配置文件xml开发
模糊查询
<!-- "%"#{username}"%" 只能用双引号
或者用like concat('%', #{username},'%')
-->
或者用like concat('%', #{username},'%')
-->
自己实现Dao
使用动态代理Dao
注解开发
注意:一个Dao中只能选择一种开发方式,要使用注解开发,则该dao目录下不能含有xml文件
常用注解
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与
@Result 一起使用,封装多个结果集
@ResultMap:实现引用
@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与
@Result 一起使用,封装多个结果集
@ResultMap:实现引用
@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
实体类名与数据库名不一致
@Result:实现结果集封装
@Results:可以与
@ResultMap:实现引用
@Results:可以与
@ResultMap:实现引用
代码
多表查询
一对一
关系映射:实体类从表方应该包含一个主表方的对象引用
使用@One
select:唯一标识
fetchType:LAZY(延迟加载),EAGER(立即加载),DEFAULT
select:唯一标识
fetchType:LAZY(延迟加载),EAGER(立即加载),DEFAULT
一对多
关系映射:实体类包含一个对方的对象集合引用
使用@Many
select:唯一标识
column:数据库表主键名称
fetchType:
select:唯一标识
column:数据库表主键名称
fetchType:
多对多
关系映射:实体类各自包含一个对方的对象集合引用
使用@Many
select:唯一标识
column:数据库表主键名称
fetchType:
select:唯一标识
column:数据库表主键名称
fetchType:
一级缓存默认开启
开启二级缓存
1.主配置文件配置setting
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2.Dao接口使用@CacheNamespace注解
使用动态代理Dao完成CRUD
动态代理:mybatis自动创建dao接口的实现类,在实现类中调用SqlSession执行sql语句
使用动态代理的方式
1.获取SqlSession对象,SqlSessionFactory.openSession()
2.使用sqlSession.getMapper(接口.class)方法获取某个接口的对象
3.使用Dao接口的方法,调用方法就执行了mapper文件中sql语句
使用动态代理方式的要求
1.Dao接口和mapper文件放在一起,同一个目录
2.Dao接口和mapper文件名称一致
3.mapper文件中的namespace的值是dao接口的全限定名称
4.mapper文件中的<select>,<insert><update><delete>等的id是接口的方法名称
5.Dao接口中不要使用重载方法,不要使用同名的,不同参数的方法
理解传参
从java代码把实际的值传入到mapper中
1.一个简单类型的参数:#{任意字符}
2.多个简单类型的参数:使用@Param("自定义名称")
3.使用一个java对象,对象的属性值作为mapper文件找到参数,#{java对象的属性名}
4.使用参数的位置,语法#{arg0},#{arg1}
5.使用Map作为参数,#{map的key}
#和$的区别
1.#是占位符,表示列值的,放在等号右侧
2.$也是占位符,表示字符串的连接,把sql语句连接成一个字符串
3.#占位符使用的jdbc指定PrepareStatement对象执行sql语句,效率高,没有sql注入的风险
4.$使用的是Statement执行sql,效率低,有sql注入的风险
mybatis返回结果
resultType
表示sql语句的执行结果,转为java对象的类型
1.实体类对象类型的全限定名称
2.别名,在mybatis主配置文件定义别名
1.使用<typeAlias>
2.使用<package name="包名" />,类名就是别名
resultMap
自定义列名和java实体类对象的属性名对应关系
列名和属性名不一致的解决的方式
使用列名as 别名
使用resultMap
like
在java代码中指定like的内容 ,例如%张%
在mapper文件中拼接like
动态SQL
根据条件,能够得到不同的sql语句,使用mybatis的标签,例如 if,where,foreach等
if
判断条件,条件为true,会把if之间的sql加入到主sql之后
判空和长度
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="username!=null and username != '' ">
and username like #{username}
</if>
where 1=1 的作用
where
<where>标签里面是多个if,如果有一个if判断为true,会在sql的后面加入where关键字,会去掉无用的and,or等字符
<select id="findByCondition" parameterType="user" resultMap="userMap">
select * from user
<where>
<if test="userName !=null">
and username=#{userName}
</if>
<if test="userSex !=null">
and sex=#{userSex};
</if>
</where>
</select>
select * from user
<where>
<if test="userName !=null">
and username=#{userName}
</if>
<if test="userSex !=null">
and sex=#{userSex};
</if>
</where>
</select>
foreach
循环数组,list集合
SQL 语句:
select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
代码
select * from user
<where>
<if test="ids!=null and ids.size()>0">
<foreach collection="ids" open="id in(" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
select * from user
<where>
<if test="ids!=null and ids.size()>0">
<foreach collection="ids" open="id in(" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
抽取sql代码片段:复用部分sql语句
<!-- 定义抽取重复的语句代码片段 -->
<sql id="defaultSql">
select * from user
</sql>
<sql id="defaultSql">
select * from user
</sql>
<!-- include标签引用 -->
<select id="findById" resultType="user" parameterType="int">
<include refid="defaultSql"></include>
where id = #{uid}
</select>
<select id="findById" resultType="user" parameterType="int">
<include refid="defaultSql"></include>
where id = #{uid}
</select>
mybatis配置文件
1.主配置文件SqlMapConfig.xml
SqlMapConfig.xml中配置的内容和顺序
-properties(属性)
--property
-settings(全局配置参数)
--setting
-typeAliases(类型别名)
--typeAliase
--package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境子属性对象)
---transactionManager(事务管理)
---dataSource(数据源)
-mappers(映射器)
--mapper
--package
--property
-settings(全局配置参数)
--setting
-typeAliases(类型别名)
--typeAliase
--package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境子属性对象)
---transactionManager(事务管理)
---dataSource(数据源)
-mappers(映射器)
--mapper
--package
properties(属性)
1.在主配置文件中<dataSource>使用<property>直接指定数据库连接信息
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/表名"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/表名"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
2.使用properties配置连接数据库的信息
1.在内部标签配置
<properties>
<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="root"/>
</properties>
<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="root"/>
</properties>
dataSource标签中的property标签value值使用${key名}
2.在resources目录下定义属性配置文件jdbcConfig.properties
resource属性:用于执行配置文件的位置,是按照类路径的写发来写,并且必须存在于类路径下
<properties resources="jdbcConfig.properties"></properties>
dataSource标签中的property标签value值使用${key名}
typeAliases(类型别名)
Mybatis支持的默认别名
会出现控制台乱码问题
<typeAliases>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.google.domain"/>
<package name="其它包"/>
</typeAliases>
<typeAliases>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.google.domain"/>
<package name="其它包"/>
</typeAliases>
乱码
<!-- 单个别名定义 不区分大小写-->
<typeAliases>
<typeAlias alias="User" type="com.aaa.domain.User"/>
</typeAliases>
<typeAliases>
<typeAlias alias="User" type="com.aaa.domain.User"/>
</typeAliases>
mappers(映射器)
基于XML的自定义mybatis框架
<mapper resource=" " />
<mapper resource=" " />
使用相对于类路径的资源 如:<mapper resource="com/google/dao/UserDao.xml" />
基于注解方式定义Mybatis框架
<mapper class=" " />
<mapper class=" " />
使用mapper接口类路径 如:<mapper class="com.google.dao.UserDao"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
<package name=" "/>
注册指定包下的所有mapper接口 如:<package name="com.google.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
2.mapper配置文件(Dao.xml)
实体类名与数据库名不一致
要配置resultMap对应关系
PageHelper:分页
功能:实现数据库的分页
使用步骤
1.加入maven依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.1</version>
</dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.1</version>
</dependency>
2.在mybatis主配置文件加入plugin
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3.在查询方法前,加入PageHelper方法的调用
PageHelper.startPage(2,5);
0 条评论
下一页