MyBatis动态SQL_多表查询_延迟加载_缓存

POJO包装传递对象

//POJO实体
public class QueryConditionObject {private User user;//user get,set方法
}//Dao 接口
public interface UserMapper{List<User> findByCondition(QueryConditionObject qco);
}//UserMapper.xml中的select标签
<select id="findByCondition" resultType="com.regotto.domain.User"parameterType="com.itheima.domain.QueryVo"><!--此处使用OGNL表达式, 传递select查询的条件-->select * from user where username like #{user.username};
</select>

resultType or resultMap配置结果参数

MyBatis封装resultSet结果集时, 使用反射机制, 因此, 必须保证resultSet结果集中的属性名称与实体的名称保持一致, 因此使用 resultType 遵循以下规则:

  1. 数据库的列名与实体属性名保持一致(在Windows下MySQL不区分大小写, 在Linux下MySQL区分大小写, 一定要注意保持包括大小写也一致)
  2. 若数据库列名与实体属性名不一致, 使用select name as userName…, 来保持resultSet结果集属性的值与实体中的属性值一样, 保证反射属性封装成功.
  3. 使用resultMap定义表列名与实体属性的对应关系.

typeAliases(类型别名)

使用类型别名后, 在parameterType, resultType中就不用写很长的类路径, 直接简写
例如: 以前 => resultType=“com.regotto.domain.User” 后来 => resultType=“user”

<typeAliases><!--对单个实体进行--><typeAlias alias="user" type="com.regotto.domain.User"><!--扫描当前包下的类, 自动别名设定为类名(首字母大小写都行)--><package name="com.regotto.domain">
</typeAliases>

mappers映射器(指定Mapper.xml或者注解修饰的类)

使用Mapper.xml (最常用)
<mapper resource="com/regotto/dao/UserMapper.xml">
使用注解
<mapper class="com.regotto.dao.UserMapper">
mapper接口与Mapper.xml文件在同一个目录中, 且文件名相同
<package name="com.regotto.dao">

MyBatis数据源配置

MyBatis数据源种类: UNPOOLED(不使用连接池), POOLED(使用连接池), JNDI(从JNDI上查找DataSource)
使用连接池, 提高数据库操作性能, 通常MyBatis使用的数据源为POOLED

<dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/>
</dataSource>

MyBatis使用工厂模式创建DataSource, 源码如下:

public interface DataSourceFactory {void setProperties(Properties var1);DataSource getDataSource();
}import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
//UnpooledDataSourceFactory implements DataSourceFactory
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {public PooledDataSourceFactory() {this.dataSource = new PooledDataSource();}
}

根据源码PooledDataSource中popConnection(String username, String password)方法可得出, 当执行Sql语句的时候, 才会从连接池中获得一个Connection, 使用完毕后, 再归还连接池.

MyBatis事务控制

JDBC事务提交: connection.setAutoCommit(boolean b).
MyBatis中事务提交源码:

	//SqlSessionFactory.class代码如下:public SqlSession openSession() {return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);}public SqlSession openSession(boolean autoCommit) {return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(),(TransactionIsolationLevel)null,autoCommit);}private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)

可使用SqlSessionFactory.openSession(true)设置自动提交. 或者使用session.commit进行手动提交.

动态SQL

对paramType中的参数进行判断, 条件成立, 则拼装Sql, 不成立, 不拼装Sql

  • if标签(条件判断, where 1=1用于if条件不成立, 导致sql执行错误)
<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>
  • where标签(简化where 1=1的写法)
<select id="findByUser" resultType="user" parameterType="user"> select * from user<where> <if test="username!=null and username != '' ">and username like #{username}</if> <if test="address != null">and address like #{address}</if>	</where>
</select>
  • foreach标签(等价于for循环, 重复执行Sql)
class Query{private List<Integer> ids;//ids get set方法...
}
<!-- 查询所有用户在 id 的集合之中 --> 
<select id="findInIds" resultType="user" parameterType="com.regotto.Query">
<!-- select * from user where id in (1,2,3,4,5); -->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>SQL 语句:select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:collection:代表要遍历的集合元素,注意编写时不要写#{}open:代表语句的开始部分close:代表结束部分item:代表遍历集合的每个元素,生成的变量名sperator:代表分隔符

MyBatis多表查询

  • 一对一(多对一)
    User <=> Account
1. 编写sql语句: select * from user, account where user.id = account.id;
2. 定义实体(可以使用int, String等基本属性定义, 定义的实体内容决定了Mapper.xml中select标签的编写方式)class AccountUser{private User user;private String id;private String name;//......//get, set方法}
3. 定义dao接口interface AccountUserMapper{AccountUser findAccountUser();}
4. 定义AccountUserMapper.xml文件resultMap建立查询结果与AccountUser属性的对应关系<resultMap type="account" id="accountMap"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/><!-- 它是用于指定从表方的引用实体属性的 --> <association property="user" javaType="user"> <id column="id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><result column="address" property="address"/></association></resultMap> <select id="findAll" resultMap="accountMap">select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;</select>
  • 一对多
    User <=> 多个Account
1. 编写sql: select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid
2. 定义实体class User{private String id;private String name;private List<Account> accounts;//get, set方法}
3. 定义dao接口方法: List<Account> findAll();
4. UserMapper.xml
<resultMap type="user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型--> <collection property="accounts" ofType="account"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/></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>

相比于一对一, 若实体属性是集合等结构, 则使用collection标签

  • 多对多
    多个Role <=> 多个User, 中间表USER_ROLE
1.编写sql:SELECT r.*,u.id uid, u.username username FROM ROLE rINNER JOIN USER_ROLE ur	ON ( r.id = ur.rid)	INNER JOIN USER u ON (ur.uid = u.id);
2.编写实体:class Role {private id;private name;List<User> users;//get set方法}
3.dao接口:List<Role> findAll();
4.编写Mapper.xml<!--定义 role 表的 ResultMap--><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><collection property="users" ofType="user"><id column="id" property="id"></id><result column="username" property="username"></result><result column="address" property="address"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result></collection></resultMap><!--查询所有--><select id="findAll" resultMap="roleMap">select u.*,r.id as rid,r.role_name,r.role_desc from role r

将多对多的关系拆分为两个一对多的关系处理

MyBatis延迟加载

一定程度上提高查询性能, 但是造成的问题是: 当存在大量查询需要立即获得数据, 导致用户体验下降.
在SqlMapperConfig.xml配置文件中开启延迟加载:

<settings> <setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/>
</settings>
  • association实现延迟加载
    account <=> 多个user
AccountUserMapper.xml文件内容
<!-- 建立对应关系 --> <resultMap type="account" id="accountMap"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/><!-- 对user进行查询的时候,  指定需要延迟加载的User方法, 对应方法参数名称--> <association property="user" javaType="user" select="com.itheima.dao.IUserDao.findById" column="uid"/></resultMap> <select id="findAll" resultMap="accountMap">select * from account</select>
association属性:
select: 填写我们要调用的 select 映射的 id 
column : 填写我们要传递给 select 映射的参数
  • collection实现延迟加载
    user <=> 多个account
AccountUserMapper.xml:
<resultMap type="user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型select 是用于指定查询账户的唯一标识(账户的 dao 全限定类名加上方法名称)column 是用于指定使用哪个字段的值作为条件查询--> <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findByUid" column="id">
</collection>
</resultMap>
<!-- 配置查询所有操作 --> 
<select id="findAll" resultMap="userMap">select * from user
</select>
<collection>标签:主要用于加载关联的集合对象select 属性:用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 idcolumn 属性:用于指定 select 属性的 sql 语句的参数来源,上面的参数来自于 user 的 id 列,所以就写成 id 这一个字段名

**结论: **使用association或者collection进行延迟加载, 需要指定select, column, association与collection的区别: association使用property, javaType; collection使用property, ofType; property都是指定实体中属性的名称, javaType, ofType是指定集合泛型.

MyBatis缓存

一级缓存(SqlSession级别, Session存在缓存就存在)

在映射文件中设定查询结果的缓存有效:

<!-- 根据 id 查询 --> 
<select id="findById" resultType="UsEr" parameterType="int" useCache="true">select * from user where id = #{uid}
</select>useCache: 设定缓存是否有效

执行查询操作之后, 结果放入一级缓存中, 下次查询, 数据还是存缓存中获取.

二级缓存(Mapper映射级别, 多个Session共用一个缓存)

1.在SlqMapperConfig.xml中开启二级缓存

MyBatis默认开启二级缓存
<settings><!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/>
</settings>

2.在select标签上配置useCache标签值
注: 使用缓存存储对象, 实体必须实现 Serializable接口

MyBatis注解开发不具有灵活性, 不使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2019 高考填报志愿建议

2019 高考填报志愿建议1、城市很关键&#xff0c;在大城市上学和小地方上学会有很大的不同&#xff0c;现在很多毕业生毕业后会往北上广深跑&#xff0c;很多原因是因为这里的就业机会多&#xff0c;薪资比内地好太多了&#xff0c;如果你大学就能在这样的地方上学&#xff0c;…

纸机器人的折法_好神奇!他们竟用一张纸折成了一个机器人

一张纸&#xff0c;折成一只青蛙&#xff0c;或者一双腿、一条毛毛虫&#xff0c;装上一个电机&#xff0c;就能在桌子上爬行走动、蹦蹦跳跳。一群来自新加坡的大一学生&#xff0c;最近在浙江大学上了3星期的工业设计课&#xff0c;他们交出的作业就是外形多样且有着丰富运动形…

韦东山:闲鱼与盗版更配,起诉到底绝不和解!

之前很多人问&#xff0c;我和韦老师是什么关系&#xff0c;我们是本家人&#xff0c;至于更深的关系&#xff0c;我也不知道&#xff0c;这次事件受老师委托&#xff0c;帮忙发文支持&#xff0c;看到的朋友&#xff0c;也希望给予转发支持&#xff0c;感激不尽~大学的时候&am…

Windows下搭建FTP服务器

一、什么是ftp? FTP 是File Transfer Protocol&#xff08;文件传输协议&#xff09;的英文简称&#xff0c;而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时&#xff0c;它也是一个应用程序&#xff08;Application&#xff09;。基于不同的操作系统有不…

Redis常见数据类型_Redis通用指令

Redis常见数据类型 redis本身就是一个Map结构, 所有数据都采用key:value的形式, redis中的数据类型指的是value的类型, key部分永远是字符串 string(类似Java String) string基本操作: set key value //存储数据 get key value //获取数据 del key value //删除数据 mset …

h3c交换机重启_h3c交换机重置命令_h3c交换机如何初始化

h3c交换机重置命令_h3c交换机如何初始化reset saved-configurationThe saved configuration file will be erased. Are you sure? [Y/N]: y // 提示是否擦除配置文件Configuration in the device is being cleared.Please wait ......Configurat…

我关注的学习公众号

在这个激烈竞争的社会&#xff0c;职场上还有“一招鲜”么&#xff1f;面对35岁的“魔咒”&#xff0c;提升自我的路很多&#xff0c;学习是其中最为捷径的一条。只有不断学习新知识&#xff0c;才能保持进步。今天为大家整理了8个公众号&#xff0c;分别为各个领域的佼佼者&am…

我对ThreadLocal的理解

声明&#xff1a;小弟菜狗一个。对ThreadLocal的描写叙述和理解难免有所偏差 近期由于须要深入的了解android的handler消息机制而去查看了Looper的源代码。众所周知在主线程中是不须要在程序猿在代码新建一个Looper对象的&#xff0c;由于在主线程创建时它就被创建出来了。所以…

如何让开关打开_安卓手机如何打开USB调试模式

点击上方“手机互联” 关注我吧&#xff01;什么是USB调试模式&#xff1f;USB调试模式是 安卓手机提供的一个用于开发工作的功能。使用该功能可在设备和安卓手机之间复制数据、在移动设备上安装应用程序、读取日志数据等等。默认情况下&#xff0c;USB 调试模式是关闭的&#…

Redis持久化_Redis事务_Redis删除策略

Redis持久化 Redis包含3中持久化方案: RDB, AOF, RDB与AOF混合使用 RDB RDB: 将内存中数据生成快照形式, 将其保存到.rdb文件中, 关注点是数据 使用命令执行RDB过程 在保存.rdb文件之前还需要修改redis.conf配置文件, 修改项如下: dbfilename dump.rdb //配置.rdb文件名, …

第一次线下活动总结

公众号建立有了一段时间了&#xff0c;今天是我们筹划的第一次线下聚会活动&#xff0c;活动发起人是公众号的一个读者&#xff0c;是我们的前辈&#xff0c;也是这次活动的赞助商&#xff0c;非常感谢&#xff0c;支付了聚餐了费用&#xff0c;这次第一届活动&#xff0c;当然…

初学者选黑卡还是微单_零基础,一篇读懂单反和微单

许多小白在选购相机时&#xff0c;常常会纠结选微单还是选单反。那么这次就来一篇通俗讲解&#xff1a;单反和微单有什么区别&#xff1f;谁更好&#xff1f;应该怎么选择&#xff1f;一、单反和微单有什么区别&#xff1f;在了解单反和微单的区别之前&#xff0c;我们先要了解…

Redis核心配置_Redis高级数据类型使用

Redis核心配置 服务端配置 daemonize yes|no //服务器是否已守护进程方式运行 bind 127.0.0.1 //绑定主机 port 6379 //设置端口 databases 16 //设置数据库数量 loglevel debug|verbose|notice|warning //设置日志级别 logfile 端口号.log //设置日志文件名 maxclients 1 //…

xcode8注释快捷键失效问题

1. 首先按上图的指示&#xff0c;查看Add Documentation后面的快捷键是不是optioncommand/。 2. 如果发现不是默认的快捷键&#xff0c;可按快捷键command&#xff0c;打开Xcode偏好设置窗口&#xff0c;选中Key Bindings&#xff0c;搜索Add Documentation&#xff0c;便可修…

vant组件搜索并选择_Vant Weapp - 有赞出品的免费开源微信小程序组件库

轻量可靠的小程序UI组件库&#xff0c;主流移动组件库 Vant 的微信小程序版本。Vant Weapp 和 Vant 的区别之前推荐过的移动端web组件库 Vant 是 Vue.js 版本的&#xff0c;其对内承载了有赞所有核心业务&#xff0c;对外有十多万开发者在使用&#xff0c;一直是业界主流的移动…

走了,又回来了

今天换了个大的办公室&#xff0c;从100平增加到了300平&#xff0c;从宝安到南山&#xff0c;从旧环境到新环境&#xff0c;不是新的开始&#xff0c;是新的环境和心情。突然有点感慨&#xff0c;那时候从科技园出发&#xff0c;跟HP从深圳坐高铁去广州&#xff0c;在广州小蛮…

Flink-Java版单词计数(批处理流处理)

创建工程 pom.xml文件依赖如下: <dependencies><dependency><groupId>org.apache.flink</groupId><artifactId>flink-java</artifactId><version>1.10.1</version></dependency><!--依赖的一些组件需要 Scala 环境…

怎么做批注_BIM平台是什么?有何用?怎么用?

原标题&#xff1a;BIM平台是什么&#xff1f;有何用&#xff1f;怎么用&#xff1f;随着BIM技术的深入应用&#xff0c;我们也不再拘泥于单单BIM软件的使用&#xff0c;在BIM技术的广泛应用之下&#xff0c;BIM平台也逐渐成为了BIM技术的最佳体现&#xff0c;也成为了众多工程…

重入的问题

抛出个问题 有一个定时器,定时时间是1秒,然后里面有一个执行函数,里面的函数有时候执行500毫秒,有时候执行2秒,如果是这样的话,有没有问题,如果有问题,要怎么解决? 先说上面中断的问题 我之前写过一篇文章,专门说中断的,我又想起来之前说的那个重入和不重入的问题…

web前端性能优化

一、什么是前端性能优化从用户访问资源到资源完整的展现在用户面前的过程中&#xff0c;通过技术手段和优化策略&#xff0c;缩短每个步骤的处理时间从而提升整个资源的访问和呈现速度。二、为什么要做前端性能优提升网站性能&#xff0c;提升用户体验三、前端性能优化的原则1、…