使用MyBatis进行简单的更新与查询

MyBatis增删改查的用法

sql映射文件

sql映射文件中的顶级元素说明

元素说明
mappersql映射文件的根元素
只有一个属性namespace,用于区分不同的mapper,必须全局唯一。
cache为给定命名空间配置缓存
cache-ref引用其他命名空间的缓存配置
resultMap用于描述查询结果集中的字段荷Java实体类属性的对应关系
sql定义可重用的sql语句块,可以在其他语句映射中引用
insert映射insert语句
update映射update语句
delete映射delete语句
select映射select语句

使用规则

​ 1,sql映射文件与该mapper接口同名(实体类名+mapper),并放置在同意包路径下。

​ 2,要以映射的mapper接口的完全限定名(包名+类名)作为namespace属性的值。

​ 3,接口中的方法名与映射文件中sql语句映射的ID一一对应。

​ 4,在不同的sql映射文件中,子元素的id可以相同。

myBatis框架的缓存

缓存分类
一级缓存基于PerperualCache的HashMap本地缓存,默认是SQL Session级别的缓存,
在SQL Session的一个生命周期中有效。
MyBatis框架的一级缓存默认是开启的。
二级缓存二级缓存是SQL Session Factory级别的,其缓存中的数据可以被所有SQL session共享。
MyBatis框架的二级缓存**默认是关闭的。**使用时需要在其核心配置文件中设置开启。
二级缓存的使用方法
1>在核心配置文件中设置全局开启二级缓存
<settings>
    <setting name="cacheEnabled" value="true" />
</settings>
2>根据需要在sql映射文件中配置缓存,为当前namespace启用二级缓存
<!--在mapper标签内-->
<!--缓存设置-->
<cache 
       eviction="FIFO"
       flushInterval="60000" 
       size="512"
       readOnly="true" />

cache元素中各种属性的作用

eviction选择缓存回收策略
LRU:默认选项,最近最少回收,移除最长时间不被使用的缓存对象。
FIFO:先进先出,按照对象缓存的顺序来移除他们。
SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象。
WEAK:弱引用,更积极的移除基于来及回收器和若以用规则的对象。
flushInterval设定缓存刷新间隔,以ms为单位设定多久自动刷新一次缓存
默认不自动刷新
size设定缓存中最多存放的对象数,
默认1024
readOnly设定缓存是否只读。
默认false,表示缓存数据会用于读写操作
true:表示缓存数据值用于读操作。
3>在sql映射文件中配置支持二级缓存后,如需对个别查询进行调整,可在select元素中单独设置
<select id="selectAll" resultType="SysUser" 
        useCache="true">
....
</select>

myBatis框架的新增

新增,使用insert元素来映射插入语句。


	//接口中的方法

   /**
     * 新增的方法
     * @param smbmsUser	 smbmsUser对象
     * @return 返回受影响的行数
     */
    int insertUserInfo(SmbmsUser smbmsUser);
<!--对应的mapper标签-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<insert id="insertUserInfo" parameterType="com.pojo.SmbmsUser">
    <!--sql语句中 #{xxx} 中xxx均为实体类中的属性名一致-->
        insert into smbms_user (userName,userPassword,userCode)values (#{userName},#{userPassword},#{userCode})
    </insert>

myBatis框架的更新

	
	//接口中的方法
	/**
     * 更新信息的方法
     * @param smbmsUser	 smbmsUser对象
     * @return  返回受影响的行数
     */
    int updateUserInfo(SmbmsUser smbmsUser);
<!--对应的mapper标签-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<update id="updateUserInfo" parameterType="com.pojo.SmbmsUser">
      <!--sql语句中 #{xxx} 中xxx均为实体类中的属性名一致-->
        Update smbms_user set userName=#{userName} where id=#{id}
    </update>

myBatis框架的删除

 	
	//接口中的方法
	/**
     * 根据id删除的方法
     * @param id  要删除的id
     * @return		返回受影响的行数
     */
    int deleteUserInfoById(@Param("id")int id);
<!--对应的mapper标签-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
 <delete id="deleteUserInfoById" parameterType="int">
     <!--此时#{xxx}参数中xxx可以不与对应Mapper类方法中的形参一直-->
        delete from smbms_user where id=#{id}
    </delete>
注意总结

1>对于增删改这类操作,数据库本身默认返回执行sql所影响的行数,所以DAO层的Mapper接口方法的返回值一般设置为int类型。

2>insert , update, delete元素中均没有resultType/resultMap属性。

myBatis框架的简单查询

基本数据类型—实现单一条件查询
	
	//接口中的方法
	/**
     * 根据用户名模糊查的方法
     * @param userName 用户名
     * @return  集合
     */
    List<SmbmsUser>  listByUserName(String userName);
<!--对应的mapper标签-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<!--属性resultType的值为返回结果的类型,要使用完全限定名或别名(这里用了完全限定名) -->
<select id="listByUserName"  parameterType="string" resultType="com.pojo.SmbmsUser">
     <!--此时#{xxx}参数中xxx可以不与对应Mapper类方法中的形参一直-->
    SELECT u.*,r.`roleName` FROM smbms_user  AS u  INNER JOIN `smbms_role` AS r ON
    u.`userRole`=r.`id` WHERE userName LIKE CONCAT('%',#{param},'%')
</select>

select标签中的parameterType属性 ,表示为向sql语句传入的参数类型,使用完全限定名(包名+类名)或别名,支持基础数据类型和复杂数据类型。

被映射的sql语句中,参数的表示方法为*#{参数名},此参数名不需要**和Mapper接口中方法的形参刻意匹配,因为myBatis框架将映射的sql语句自动转换成 “?” 占位符的sql语句并实现赋值。*

mybatis框架内建的部分别名与java数据类型的映射关系

映射类型别名映射类型别名
BooleanbooleanStringstring
BytebyteBigDecimalbigdecimal或decimal
LonglongDatedate
ShortshortMapmap
Integerint或integerHashMaphashmap
DoubledoubleListlist
FloatfloatArrayListarraylist
基本数据类型—实现多条件查询
使用@Param注解实现多参数入参
	//接口中的方法
    /**
     * 根据商品名和id查询商品通过注解的方式
     * @param name  商品名
     * @param id     id
     * @return      返回一个商品对象
     */
    SmbmsProvider getByNameAndIdInNote(@Param("proName")String name,@Param("id")int id);
	//注解中的参数名,将用于Sql映射文件中的对应select标签的sql语句中的参数值
 <!--对应的mapper标签中-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<!--属性resultType的值为返回结果的类型,要使用完全限定名或别名(这里用了完全限定名) -->
 <select id="getByNameAndIdInNote" resultType="com.pojo.SmbmsProvider">
  select * from smbms_provider where proName like CONCAT('%',#{proName},'%') and id=#{id}
 </select>

注意:

​ 1,当输入的参数类型为基本数据类型时,select标签中的parameterType属性可省略(无论单参还是多参)

​ 2,注解中定义的参数名称要和sql语句占位符中的参数名称一致

实现多条件查询
将查询条件封装成java对象作为入参

	//接口中的方法
    /**
     * 根据输入参数查询商品信息
     * @param provider 对象
     * @return 商品对象
     */
    List<SmbmsProvider> getAll(SmbmsProvider provider);
 <!--对应的mapper标签中--> 

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<!--属性resultType的值为返回结果的类型,要使用完全限定名或别名(这里用了完全限定名) -->
<select id="getAll" resultType="com.pojo.SmbmsProvider" parameterType="com.pojo.SmbmsProvider">
     <!--sql中的#{xxx}中的xxx要和实体类中的属性名一致-->
    select * from smbms_provider where proName like CONCAT('%',#{proName},'%')
</select>

将查询条件封装成Map对象作为入参

	//接口中的方法
	/**
     * 根据商品名和id查询商品的方法
     * @param map  map集具体合对象中存有商品名和id的值
     * @return    返回一个具体对象
     */
    SmbmsProvider getByNameAndId(Map<String,Object> map);
 <!--对应的mapper标签中-->

<!--属性id的值为对应的Mapper接口中的方法名 ,属性parameterType的值为此方法形参的类型 -->
<!--属性resultType的值为返回结果的类型,要使用完全限定名或别名(这里用了完全限定名) -->
<select id="getByNameAndId"  parameterType="map" resultType="com.pojo.SmbmsProvider">
    <!--sql中的#{xxx}中的xxx要和map集合中的key一致-->
  select * from smbms_provider where proName like CONCAT('%',#{proName},'%') and id=#{id}
</select>
//测试类中 

@Test
    void getByNameAndId() {
        SqlSession session= MyBatisUtil.getSqlSession();
        ProviderMapper providerMapper=session.getMapper(ProviderMapper.class);
        Map<String,Object> map=new HashMap<>() ;
        //注意添加的key
        map.put("proName","北京");
        map.put("id",6);
        SmbmsProvider smbmsProvider= providerMapper.getByNameAndId(map);
        System.out.println(smbmsProvider.getProName());
    }

使用Map类型传递多个参数,绑定的sql语句中使用#{Map的key}来取得参数值。使用Map传参的方式更加灵活,不受域模型(实体类)设计的限制,可以更加灵活的组织查询所需的条件。

MyBatis框架的结果映射

使用resultMap元素定义结果映射,对名称不同的结果集字段和实体类属性进行映射。

resultMap元素包含的属性
名称说明
id映射规则集的唯一标识,可以被select元素中的resultMap属性引用,便于找到对应规则集。
type映射的结果类型。
resultMap元素包含的子元素
名称说明
id指定和数据表主键字段对应的标识属性。
可提高框架的性能,特别是应用缓存和嵌套结果映射的时候。
result指定结果集字段和实体类属性的映射关系。

eg:


<!--使用resultMap元素定义结果映射--> 
<resultMap id="userWithRoleName" type="com.pojo.SmbmsUser">
        <id property="id" column="id"></id>
        <result property="userRoleName" column="roleName"></result>
</resultMap>
<!--使用resultMap元素定义的规则封装查询结果-->
<select id="listByUserName"  parameterType="string" resultMap="userWithRoleName">
    SELECT u.*,r.`roleName` FROM smbms_user  AS u
INNER JOIN `smbms_role` AS r ON u.`userRole`=r.`id`
WHERE userName LIKE CONCAT('%',#{userName},'%')
</select>

注意

​ 1,select元素中的resultMap属性的值要与resultMap元素中id属性的值一致。

​ 2,select元素中的parameterType属性的值要与resultMap元素中type属性的值一致。

​ 3,resultMap元素中的id子元素是数据表主键字段的列, 其中property属性是相应实体类中的对应属性,其中column属性是结果集中列的名称。

​ 4,resultMap元素中的result子元素是用来映射其他的列, 其中property属性是相应实体类中的对应属性,其中column属性是结果集中列的名称。

resultMap的自动映射行为

可以在核心配置文件中进行设置

    <settings>
        <!-- 设置自动映射行为       -->
        <setting name="autoMappingBehavior" value="FULL"/>
    </settings>

其上value的值有3种

说明
NONE禁用自动映射,仅为手工映射的属性赋值。
PARTIAL默认行为,没嵌套的resultMap使用自动映射,有嵌套的则不使用。
FULL全部使用自动映射,有嵌套的也会使用自动映射。

自动映射行为对resultType和resultMap的影响

自动映射行为resultType(不支持嵌套映射)没有嵌套映射的resultMap有嵌套映射的resultMap
NONE失效手工映射手工映射
PARTUAL自动映射自动映射手工映射
FULL自动映射自动映射自动映射

注意

1, resultType不支持嵌套映射,无论autoMappingBehavior设置为PARTIAL还是FULL,实体类都会自动映射,而实体类中的关联属性都不会被初始化,始终未null.

2,resultType完全依赖自动映射,如果autoMappingBehavior设置为NONE,resultType会失效,无法初始化实体类对象而返回null,此时返回 查询只能使用resultMap手工映射。

嵌套结果映射
1,association元素

​ ------------此元素用来处理‘’has-one‘’类型的关系(复合类型)。

​ 处理:多对一或一对一

association元素包含的属性

名称说明
property实体类中用来映射查询结果子集的属性
javaTypeproperty指定的属性的数据类型,可以使用java完全限定类名或别名。
如果property指定的属性是javaBean,则框架能自行检测出。
如果property指定的属性是HashMap,则应通过javaType属性明确指定其数据类型。
resultMap引用外部resultMap

association元素包含的子元素

名称说明
id指定和数据表主键字段对应的标识属性。
result指定结果集字段和实体类属性的映射关系。

eg:

//用户实体类中,添加一个角色类型的属性

private SmbmsRole smbmsRole;//系统角色实体类类型的属性

    public SmbmsRole getSmbmsRole() {
        return smbmsRole;
    }

    public void setSmbmsRole(SmbmsRole smbmsRole) {
        this.smbmsRole = smbmsRole;
    }
 //接口中添加相应的查询方法
	/**
     * 根据roleId查找信息--使用嵌套方式
     * @param roleId
     * @return
     */
    List<SmbmsUser> listByRoleId(@Param("roleId")Long roleId);
	
<!--相应的mapper文件中-->

  <resultMap id="showRoleName" type="com.smbms.pojo.SmbmsUser">
        <id property="id" column="id"/>
      <!---->
        <association property="smbmsRole" javaType="com.smbms.pojo.SmbmsRole">
            <id property="id" column="rid" />
            <result property="roleName" column="roleName"/>
            <result property="roleCode" column="roleCode"/>
        </association>
      
    </resultMap>

    <select id="listByRoleId" parameterType="long" resultMap="showRoleName">
      SELECT u.*,r.id AS rid,r.`roleName`,r.`roleCode`
      FROM `smbms_user` AS u
      INNER JOIN `smbms_role` AS r ON u.`userRole`=r.id
    </select>

//测试类


    @Test
    void listByRoleId() {
        List<SmbmsUser> list=userMapper.listByRoleId(3L);
        for (SmbmsUser smbmsUser : list) {
            System.out.println(smbmsUser.getUserName()+"\t"+
                    smbmsUser.getSmbmsRole().getRoleName());
        }
        
     //结果---
        赵燕	普通员工
        赵敏	打工人
        ss	打工人

注意:

​ 1,因为结果映射的需要,要确保所有列名都是唯一的

​ 2,id子元素在嵌套结果映射中扮演了重要的角色。最好选择尽量少的属性来表示唯一结果。

对上述Mapper文件可修改为

<!--相应的mapper文件中-->

<!--把其单独提取出来,便于重用-->
  <resultMap id="showRoleInfo" type="com.smbms.pojo.SmbmsRole">
	 <id property="id" column="rid" />
     <result property="roleName" column="roleName"/>
     <result property="roleCode" column="roleCode"/>

  </resultMap>


  <resultMap id="showRoleName" type="com.smbms.pojo.SmbmsUser">
        <id property="id" column="id"/>
      <!---->
        <association property="smbmsRole" javaType="com.smbms.pojo.SmbmsRole" resultMap="showRoleInfo">
           
        </association>
      
    </resultMap>

    <select id="listByRoleId" parameterType="long" resultMap="showRoleName">
      SELECT u.*,r.id AS rid,r.`roleName`,r.`roleCode`
      FROM `smbms_user` AS u
      INNER JOIN `smbms_role` AS r ON u.`userRole`=r.id
    </select>

2,collection元素

​ ---------实体类内部嵌套的是一个集合类型的属性

collection元素包含的属性

名称说明
property实体类中用来映射查询结果子集的集合属性
ofTypeproperty指定的集合属性中的元素的数据类型,可以使用java完全限定类名或别名。
resultMap引用外部resultMap

collection元素包含的子元素

名称说明
id指定和数据表主键字段对应的标识属性。
result指定结果集字段和实体类属性的映射关系。

eg:

	//用户的实体类中 添加属性

	private List<SmbmsAddress> addressList;//用户地址列表

    public List<SmbmsAddress> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<SmbmsAddress> addressList) {
        this.addressList = addressList;
    }

	//相应接口中编写方法
	 /**
     * 根据永用户id查询用户及相关地址
     * @param id
     * @return
     */
    List<SmbmsUser> listUserAndAddressesByUserId(@Param("userId")int id);
<!--相应的mapper文件中-->

  <resultMap id="show" type="com.smbms.pojo.SmbmsUser">
    <id property="id" column="id"></id>
      
        <collection property="addressList" ofType="com.smbms.pojo.SmbmsAddress">
            <id property="id" column="aid"></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="listUserAndAddressesByUserId" parameterType="int" resultMap="show">
      SELECT u.*,a.id AS aid,a.`addressDesc`,a.`contact`,a.`postCode`,a.`tel`
      FROM `smbms_user` AS u
      INNER JOIN `smbms_address` AS a ON u.id=a.`userId`
      WHERE u.id=#{userId}

    </select>
	//测试类

  @Test
    void listUserAndAddressesByUserId() {
        List<SmbmsUser> list=userMapper.listUserAndAddressesByUserId(1);
        for (SmbmsUser smbmsUser : list) {
            System.out.println(smbmsUser.getUserName()+"\t");
            //找到此用户的地址集合并打印
            for (SmbmsAddress smbmsAddress : smbmsUser.getAddressList()) {
                System.out.println(smbmsAddress.getAddressDesc());
            }
        }
    }

	//结果
        系统管理员	
        北京市东城区东交民巷44号
        北京市海淀区丹棱街3号
        北京市东城区美术馆后街23

resultType和resultMap总结

resultTyperesultMap
相同均基于Map数据结构均基于Map数据结构
不同1直接指定结果类型,依靠自动映射
用于比较简单,直接的数据封装场景
对外部resultMap定义的引用,可自由控制结果映射规则和封装范围
用于处理结果集字段名与实体类属性名不一致,或者需要对连接查询结果使用嵌套映射等复杂问题。
不同2框架会先将查询的结果集存储在map结构中,以字段名作为key,
当select元素使用此属性指定结果类型时,框架会自动将Map中的键值对对应赋值给实体类中与key同名的属性
框架会先将查询的结果集存储在map结构中,以字段名作为key,
当select元素使用此属性时,则根据所引用的resultMap元素中定义的映射规则把Map中的键值对赋值给指定的实体类属性。

每日一句: 每一个不曾起舞的日子,都是对生命的一种辜负!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值