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