第二章-sql映射文件详解
分类: ssm 专栏: ssm框架课 标签: sql映射文件
2022-11-28 11:13:11 979浏览
1.sql映射文件
mybatis框架的主要思想是将sql语句从程序代码中分离出来,对jdbc访问数据库的代码进行封装,从程序中消除了所有sql参数设置以及处理结果集的jdbc代码。从而大量减少数据访问层的编码量,并且,sql语句与代码解耦,可以最大限度地实现对sql语句的灵活管理,方便sql调优以保证性能。
2.mybatis框架的条件查询
2.1实现单一的条件查询
示例1:根据用户的真实姓名模糊匹配查询用户信息
<select id="getUsersByRealName" resultType="cn.cvs.pojo.SysUser" parameterType="string"> select * from t_sys_user where realName like CONCAT('%',#{realName},'%') </select>
2.2实现多条件查询
1.将查询条件封装成Java对象作为入参
<select id="getUsersByPojo" resultType="cn.cvs.pojo.SysUser" parameterType="cn.cvs.pojo.SysUser"> select * from t_sys_user where realName like CONCAT('%',#{realName},'%') and roleId = #{roleId} </select>
SysUser user = new SysUser(); user.setRealName("李"); user.setRoleId(3); List<SysUser> users = sqlSession.getMapper(SysUserMapper.class).getUsersByPojo(user);
2.将查询条件封装成map对象作为入参
<select id="getUsersByMap" resultType="cn.cvs.pojo.SysUser" parameterType="map"> select * from t_sys_user where realName like CONCAT('%',#{rName},'%') and roleId = #{rId} </select>
Map<String,Object> map = new HashMap<>(); map.put("rName","赵"); map.put("rId",2); List<SysUser> sysUserList = sqlSession.getMapper(SysUserMapper.class).getUsersByMap(map);
3.使用@Param注解实现多参数入参
public List<SysUser> getUsersByParam(@Param("realName") String realName,@Param("roleId") int roleId);
List<SysUser> sysUsers = sqlSession.getMapper(SysUserMapper.class).getUsersByParam("赵", 2);
2.3实战训练
在724系统中实现查询入库记录表的功能
3.mybatis框架的结果映射
3.1使用resultMap元素自定义结果映射
查询用户信息列表,需要展示的字段包括账号 真实姓名 性别 电话 用户角色,注意:用户角色要显示角色名称而不是角色ID
SysUser实体类中增加属性:
private String userRoleName;//角色名称
<resultMap id="userWithRoleName" type="cn.cvs.pojo.SysUser"> <id property="id" column="id"></id> <result property="userRoleName" column="roleName"></result> </resultMap> <select id="getUsersWithRoleName" resultType="cn.cvs.pojo.SysUser" resultMap="userWithRoleName"> SELECT u.*,r.roleName FROM t_sys_user u LEFT JOIN t_sys_role r on u.roleId =r.id WHERE u.realName LIKE CONCAT( '%', #{realName},'%') and u.roleId = #{roleId} </select>
分析:resultMap元素包含以下属性:
- id:映射规则集的唯一标识,可以被select元素的resultMap属性引用
- type:映射的结果类型,一般指的是实体类的全类名
resultMap元素包含以下子元素
- id:指定和数据表主键字段对应的标识属性,设置此项可提升mybatis的性能
- result:指定结果集字段和实体类属性的映射关系
3.2实战训练
查询入库记录以及相关的供应商名称
3.3嵌套结果映射
1.association元素
association元素用来处理has-one类型的关系,如用户类内部“有一个”用户角色类型的属性。
例子:根据用户的角色id查询出用户的姓名,角色ID 角色编码和角色名称。
<resultMap id="usersByRoleId" type="cn.cvs.pojo.SysUser"> <id property="id" column="id"></id> <result property="realName" column="realName"></result> <association property="sysRole" javaType="cn.cvs.pojo.SysRole"> <id property="id" column="rid"></id> <result property="code" column="code"></result> <result property="roleName" column="roleName"></result> </association> </resultMap> <select id="getUsersByRoleId" parameterType="integer" resultMap="usersByRoleId"> SELECT u.*,r.id as rid, r.code, r.roleName FROM t_sys_user u LEFT JOIN t_sys_role r on u.roleId =r.id WHERE u.roleId = #{roleId} </select>
@Test public void getUsersByRoleId(){ SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.createSqlSession(); List<SysUser> usersByRoleId = sqlSession.getMapper(SysUserMapper.class).getUsersByRoleId(2); for(SysUser user: usersByRoleId){ logger.debug("用户名:"+user.getRealName()+"roleId:"+user.getSysRole().getId() + "角色编号"+user.getSysRole().getCode() +"角色名称:"+user.getSysRole().getRoleName()); } }catch (Exception e){ e.printStackTrace(); }finally { MyBatisUtil.closeSqlSession(sqlSession); } }
association元素的主要属性如下:
- property:实体类中用来映射查询结果子集的属性
- JavaType:property指定的属性的数据类型
association元素包含如下子元素
- d:指定和数据表主键字段对应的标识属性,设置此项可提升mybatis的性能
- result:指定结果集字段和实体类属性的映射关系
2.collection元素
和association非常相似,association是一对一或者多对一,而collection是一对多。即实体类内部嵌套的是一个集合类型的属性。
例子:要求获取指定用户的信息和地址列表
<resultMap id="userAndAdressByUserId" type="cn.cvs.pojo.SysUser"> <id column="id" property="id"></id> <result property="account" column="account"></result> <result property="realName" column="realName"></result> <collection property="addressList" ofType="cn.cvs.pojo.Address"> <id column="aid" property="id"></id> <result property="contact" column="contact"></result> <result property="addressDesc" column="addressDesc"></result> <result property="postCode" column="postCode"></result> <result property="tel" column="tel"></result> </collection> </resultMap> <select id="getUserAndAdressByUserId" resultMap="userAndAdressByUserId" parameterType="integer"> SELECT u.*,a.id as aid, a.contact, a.addressDesc,a.postCode,a.tel FROM t_sys_user u LEFT JOIN t_address a on a.userId =u.id WHERE u.id = #{userId} </select>
sqlSession = MyBatisUtil.createSqlSession(); SysUser user= sqlSession.getMapper(SysUserMapper.class).getUserAndAdressByUserId(2); logger.debug("用户账号account:"+user.getAccount()+"用户名称:"+user.getRealName()); //遍历用户地址 for(Address address : user.getAddressList()){ logger.debug("address----->id:"+address.getId() +",contact:"+address.getContact() +",addressDesc:"+address.getAddressDesc() +",postCode:"+address.getPostCode() +",tel:"+address.getTel() ); }
collection元素有如下常用属性
- property:实体类中用来映射查询结果子集的集合属性
- ofType:property指定的集合属性中的元素的数据类型,可以使用Java的全类名
3.4resultType和resultMap小结
resultType适用于比较简单,直接的数据封装场景。
resultMap处理结果集字段名与实体类属性名不一致,或需要对连接查询结果使用嵌套映射等较为复杂的问题。
3.5实战训练
- 在724系统中使用association元素查询入库记录表,在之前的基础上实现嵌套结果映射,查询并展示入库记录编码,商品名称,供货商编码,供货商名称,联系人,联系电话,商品总额,支付状态。
- 在724系统中使用collection查询供货商及相关入库记录
3.6resultMap的自动映射行为
resultMap自动映射的默认行为是对于没有嵌套映射的resultMap使用自动映射,对于有嵌套映射的resultMap则不使用自动映射,仅为手工映射的属性赋值。
可以在mybatis框架的核心配置文件中进行设置,修改自动映射的行为,
<!--设置自动映射行为--> <setting name="autoMappingBehavior" value="FULL"/>
自动映射的三种行为:
- NONE:禁用自动映射,仅为手工映射的属性赋值
- PARTIAL:默认行为,对于没有嵌套映射的resultMap使用自动映射,而对于有嵌套映射的resultMap不使用自动映射,仅为手工映射的属性赋值
- FULL:全部使用自动映射,对有嵌套的resultMap也会自动映射。
4.mybatis的增,删,改操作
4.1执行insert语句
增加用户的方法,参数为要添加的用户实例。
<insert id="add" parameterType="cn.cvs.pojo.SysUser"> insert into t_sys_user ( account, realName, password, sex, birthday, phone, address, roleId, createdUserId, createdTime, updatedUserId, updatedTime ) VALUES ( #{account}, #{realName}, #{password}, #{sex}, #{birthday}, #{phone}, #{address}, #{roleId}, #{createdUserId}, #{createdTime}, #{updatedUserId}, #{updatedTime} ) </insert>
@Test public void testAdd(){ SqlSession sqlSession = null; int count = 0; try{ sqlSession = MyBatisUtil.createSqlSession(); SysUser user = new SysUser(); user.setAccount("mayun"); user.setRealName("马云"); user.setRoleId(1); user.setAge(45); user.setPassword("123456"); count=sqlSession.getMapper(SysUserMapper.class).add(user); // int i=2/0; sqlSession.commit(); }catch (Exception e){ e.printStackTrace(); sqlSession.rollback(); count =0; }finally { MyBatisUtil.closeSqlSession(sqlSession); } logger.debug("add user count:"+count); }
4.2执行update语句
根据用户ID修改用户信息的功能,
<update id="update" parameterType="cn.cvs.pojo.SysUser"> update t_sys_user set `account` = #{account}, `realName` = #{realName}, `password` = #{password}, `sex` = #{sex}, `birthday` = #{birthday}, `phone` = #{phone}, `address` = #{address}, `roleId` = #{roleId}, `updatedUserId` = #{updatedUserId}, `updatedTime` = #{updatedTime} WHERE (`id` = #{id}); </update>
4.3执行delete语句
根据用户ID删除用户
<delete id="delete" parameterType="integer"> delete from t_sys_user where id = #{id} </delete>
4.4实战训练
在724系统中实现对供货商表的增,删, 改操作
5.mybatis框架的缓存
5.1缓存分类
1.一级缓存
基于PerpetualCache的hashMap本地缓存,默认是sqlsession级别的缓存,在sqlsession的生命周期内有效,当sqlsession关闭后,该sqlsession中所有的一级缓存会被清空。mybatis框架的一级缓存默认是开启的。
2.二级缓存
是sqlSessionFactory级别的,作用域超出了一个sqlsession的范围,缓存中的数据可以被所有sqlsession共享,mybatis框架的二级缓存默认是关闭的,使用的时候需要在mybatis框架的核心配置文件中设置开启。
5.2二级缓存的使用方法
1.在mybatis的核心配置文件中设置全局开启二级缓存。
<!--开启二级缓存--> <setting name="cacheEnabled" value="true"/>
2.即使全局开启了二级缓存,默认情况下也是不使用二级缓存的,可以根据需要在sql映射文件中配置,为当前namespace启用二级缓存。
<mapper namespace="cn.cvs.dao.SysUserMapper"> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" > </cache>
cache元素中各种属性的作用如下:
- eviction:选择缓存回收策略(FIFO:先进先出,按照对象进入缓存的顺序来移除他们,这里推荐使用LRU策略:最近最少使用的)
- flushInterval:设定缓存刷新间隔,以毫秒为单位设定缓存多长时自动刷新一次,默认不自动刷新。
- size:设定缓存中最多存放多少个对象,默认是1024
- readOnly:设定缓存数据是否只读,默认是false,表示缓存数据会用于读写操作,true表示缓存数据只用于读操作。
3.在sql映射文件中配置支持二级缓存后,如需对个别查询进行调整,可以在select元素中单独设置
<select id="count" resultType="integer" useCache="false"> …… </select>
注意:二级缓存开启后,实体类一定要实现序列化接口,因为缓存要读取到内存中。
一级缓存默认开启,怎么演示:
查询两次一模一样的sql语句
List<SysUser> all =sysUserDao.getUserAndAdressByUserId(2L); System.out.println("======================================="); List<SysUser> all2 =sysUserDao.getUserAndAdressByUserId(2L);
一级缓存失效,一级缓存不能跨sqlsession
List<SysUser> all =sysUserDao.getUserAndAdressByUserId(2L); MybatisUtils.closeSession(sqlSession); System.out.println("======================================="); sqlSession=MybatisUtils.getSession(); sysUserDao = sqlSession.getMapper(SysUserDao.class); List<SysUser> all2 =sysUserDao.getUserAndAdressByUserId(2L);
当开启二级缓存的时候,就可以跨sqlsession了。
6.课堂视频教程
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客