mybatis_study02

1. MyBatis-config.xml配置

1.1 properties属性读取外部资源

例:resource下添加资源文件.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis-44
username=root
password=root

在Mybatis-config.xml中引入jdbc.properties资源文件:

<!-- 引入外部资源文件,resource:相对路径,url:绝对路径(不建议使用) -->
    <properties resource="jdbc.properties" />

通过properties引入外部资源文件之后,就可以通过${xxx}的方式使用资源文件里的参数了

1.2 settings设置

开启驼峰匹配:完成经典的数据库命名到java属性的映射
经典数据库命名:如果多个单词之间,通常使用下划线进行连接。
java中命名:第二个单词首字母大写。
驼峰匹配:相当于去掉数据中的名字的下划线,和java进行匹配

查询数据的时候,查不到userName的信息,原因:数据库的字段名是user_name,POJO中的属性名字是userName,两端不一致,造成mybatis无法填充对应的字段信息。修改方法:在sql语句中使用别名
解决方案1:在sql语句中使用别名
解决方案2:参考驼峰匹配 — mybatis-config.xml

mybatis-config.xml中开启驼峰匹配:

<settings>
        <!-- 开启驼峰匹配:经典的数据库列名(多个单词下划线连接)映射到经典的java属性名(多个单词驼峰连接) -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

1.3 typeAliases类型别名

之前在映射文件中用到java类型时,都是使用类的全路径,书写起来非常麻烦
解决方案:
类型别名是为 Java 类型命名的一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。(官方文档)
1. 方式一:typeAlias (缺点:每个pojo类都要去配置)

<typeAliases>
        <!-- 类型别名:type-pojo类的全路径,alias-别名名称(可随便写,推荐和类名一致) -->
        <typeAlias type="cn.itcast.mybatis.pojo.User" alias="user" />
    </typeAliases>
  1. 方式二:package
<!-- 开启别名包扫描,name:包路径,扫描的别名就是类名,并且大小写不敏感 -->
<package name="cn.itcast.mybatis.pojo"/>

1.4 environments(环境)

MyBatis 可以配置成适应多种环境,例如,开发、测试和生产环境需要有不同的配置;
尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。
虽然,这种方式也可以做到很方便的分离多个环境,但是实际使用场景下,我们更多的是选择使用spring来管理数据源,来做到环境的分离

  • 方式一:environments标签内指定default采用哪个环境
  • 方式二:通过build方法的重载方法.用法:new SqlSessionFactoryBuilder().build(inputStream,”指定的环境”);

2.Mapper XML 文件(映射文件)

2.1 CRUD标签

  • select标签: 查询的statement,
    id:在同一namespace下的唯一标识,使用动态代理之后要求和接口的方法名一致,必须参数
    resultType:结果集的包装类型,和resultMap二选一
    parameterType:参数类型,可省略
    内容:查询的sql
<select id="queryUserById" resultMap="userMap">
        select * from tb_user where id = #{id}
    </select>
  • insert标签: 新增的statement
    id:在同一namespace下的唯一标识,使用动态代理之后要求和接口的方法名一致,必须参数
    parameterType:参数类型,可省略
    useGeneratedKeys:开启主键回写
    keyColumn:主键列名
    keyProperty:主键的属性名
<insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id" >
        INSERT INTO tb_user (
            user_name,
            password,
            name,
            age,
            sex,
            birthday,
            created,
            updated
        )
        VALUES
            (
                #{userName},
                #{password},
                #{name},
                #{age},
                #{sex},
                #{birthday},
                NOW(),
                NOW()
            );
    </insert>
  • update标签:
<update id="updateUser" parameterType="cn.itcast.mybatis.pojo.User">
        UPDATE tb_user
        SET
        user_name = #{userName},
        password = #{password},
        name = #{name},
        age = #{age},
        sex = #{sex},
        birthday = #{birthday},
        updated = NOW()
        WHERE
        (id = #{id});
    </update>
  • delete标签:
<delete id="deleteUserById" parameterType="cn.itcast.mybatis.pojo.User">
        delete from tb_user where id=#{id}
    </delete>

2.3 parameterType传入参数

CRUD标签都有一个属性parameterType,statement通过它指定接收的参数类型。
接收参数的方式有两种:
1、 #{}预编译
2、${}非预编译(直接的sql拼接,不能防止sql注入)
参数类型有三种:
1、 基本数据类型
2、 HashMap(使用方式和pojo类似)
3、 Pojo自定义包装类型

  • 使用 使 {value}获取参数值,
    而#{} 只是表示占位,与参数的名字无关,如果只有一个参数,可以使用任意参数名接收参数值,会自动对应
    但是这并不是一种稳妥的解决方案,推荐在接口方法形参前使用@Param注解指定参数名
    例:
public void queryUsers(@Param("userName")String userName);
  • 在mybatis的mapper中,参数传递方式有两种,一种是#{}一种是${},两者有很大区别:
  • ${}实现的是sql语句的直接拼接,不做数据类型的转换,需要自行判断数据类型,不能防止sql注入
  • #{}实现的是sql语句的预处理参数,之后执行sql语句用?代替,使用时不需要关注数据类型,mybatis自动实现数据类型转换,并且可以防止sql注入
  • 总结:#{}占位符,用于参数传递, ${}用于sql拼接

2.4 resultMap

resultMap是mybatis中最重要最强大的元素,使用resultMap可以解决两大问题:

 - pojp属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式),解决方案:使用resultMap自定义映射(autoMapping="true")
 - 完成高级查询,如一对一,一对多,多对多

配置resultMap:自定义映射关系
id:唯一标识 .type:结果集的包装类型 . autoMapping:开启自动映射,如果开启了驼峰匹配,就以驼峰匹配的形式进行映射
子标签:
id:指定主键映射的,可以提高性能
result:其他的非主键字段
column-表中的字段名
property-对应的java属性名

<resultMap type="User" id="userMap" autoMapping="true">
        <id column="id" property="id"/>
        <!-- <result column="user_name" property="userName"/> -->
</resultMap>

2.5 sql片段(即sql语句的抽取)

  • 使用方式一:sql标签可以定义一个sql片段,在需要使用该sql片段的地方,通过include标签来使用
<sql id="commonSql">
        id,user_name,
            password,
            name,
            age,
            sex,
            birthday,
            created,
            updated
    </sql>
<select id="queryUsersLikeUserName" resultType="User">
        select <include refid="commonSql"></include> from tb_user where user_name like '%' #{userName} '%'
</select>
  • 使用方式二:很多时候同一个sql片段,可能在很多映射文件里都有使用,这就需要添加一个映射文件,用来统一定义sql片段。
    如下,在resource目录下新增CommonSQL.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace(命名空间):映射文件的唯一标识 -->
<mapper namespace="CommonSQL">

    <sql id="commonSql">
        id,user_name,
            password,
            name,
            age,
            sex,
            birthday,
            created,
            updated
    </sql>
</mapper>

首先应该把该映射文件引入到mybatis的全局配置文件中(mybatis-config.xml)
最后在需要使用该sql片段的地方通过include标签的refId属性引用该sql片段:

<select id="queryUsersLikeUserName" resultType="User">
        select <include refid="CommonSQL.commonSql"></include> from tb_user where user_name like '%' #{userName} '%'
    </select>

3. 动态sql

mybatis的一个强大的特性之一通常是它的动态sql能力,提供了ognl表达式动态生成sql的功能,动态sql有:

  1. if
  2. choose,when,otherwise
  3. where,set
  4. foreach
select * from tb_user where sex=1
        <!-- if:判断
            test:OGNL表达式
         -->
        <if test="userName!=null and userName.trim()!=''">
             and user_name like '%' #{userName} '%'
        </if>

select * from tb_user where sex=1 
        <!-- choose:条件选择
            when:test-判断条件,一旦有一个when成立,后续的when都不再执行
            otherwise:所有的when都不成立时,才会执行
         -->
        <choose>
            <when test="userName!=null and userName.trim()!=''">and user_name like '%' #{userName} '%'</when>
            <when test="age != null">and age = #{age}</when>
            <otherwise>and user_name = 'zhangsan' </otherwise>
        </choose>

select * from tb_user
        <!-- 
            自动添加where关键字
            有一定的纠错功能:去掉sql语句块之前多余的一个and|or
            通常结合if或者choose使用
         -->
        <where>
            <if test="userName!=null and userName.trim()!=''">user_name like '%' #{userName} '%'</if>
            <if test="age!=null">and age = #{age}</if>
        </where>
UPDATE tb_user
        <!-- 
            set自动添加set关键字
            也有一定的纠错功能:自动去掉sql语句块之后多余的一个逗号
         -->
        <set>
            <if test="userName!=null and userName.trim()!=''">user_name = #{userName},</if>
            <if test="password!=null and password.trim()!=''">password = #{password},</if>
            <if test="name!=null and name.trim()!=''">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex}</if>
        </set>
        WHERE
            (id = #{id});
select * from tb_user where id in 
        <!-- 
            foreach:遍历集合
            collection:接收的集合参数
            item:遍历的集合中的一个元素
            separator:分隔符
            open:以什么开始
            close:以什么结束
         -->
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>

4. 缓存

4.1 一级缓存

在mybatis中,一级缓存默认是开启的,并且一直无法关闭,作用域:在同一个sqlSession下
在UserMapperTest中添加测试一级缓存的方法:

@Test
    public void testCache(){
        User user1 = this.userMapper.queryUserById(1l);
        System.out.println(user1);
        System.out.println("=================第二次查询======================");
        User user2 = this.userMapper.queryUserById(1l);
        System.out.println(user2);
    }

由于一级缓存的存在,此时在log日志中,应该只会在第一次查询是执行sql语句,第二次查询时直接从缓存中命中,即不再执行sql语句。
使用:sqlSession.clearCache();可以强制清除缓存
在执行第二次查询之前清空缓存,再去执行查询。这时无法从缓存中命中,便会去执行sql从数据库中查询。
执行update、insert、delete的时候,会清空缓存

4.2 二级缓存

mybatis 的二级缓存的作用域:
1、 同一个mapper的namespace,同一个namespace中查询sql可以从缓存中命中。
2、 跨sqlSession,不同的SqlSession可以从二级缓存中命中
怎么开启二级缓存:
1、 在映射文件中,添加标签
2、 在全局配置文件中,设置cacheEnabled参数,默认已开启。
注意:
由于缓存数据是在sqlSession调用close方法时,放入二级缓存的,所以第一个sqlSession必须先关闭
二级缓存的对象必须序列化,例如:User对象必须实现Serializable接口。

开启二级缓存,在映射文件(UserMapper.xml)中添加:
在UserMapperTest中添加二级缓存的测试方法:

@Test
    public void testCache2(){
        User user1 = this.userMapper.queryUserById(1l);
        System.out.println(user1);
        // 注意:关闭sqlSession
        sqlSession.close();
        System.out.println("=================第二次查询======================");
        // 重新打开一个sqlSession会话
        SqlSession sqlSession2 = this.sqlSessionFactory.openSession();
        // 通过sqlSession2重新实例化UserMapper
        this.userMapper = sqlSession2.getMapper(UserMapper.class);
        User user2 = this.userMapper.queryUserById(1l);
        System.out.println(user2);
    }
这个错误通常表示你正在尝试将更改推送到远程仓库时出现了问题。根据引用,你可能遇到了两个问题,一个是“src refspec master does not match any”,另一个是“failed to push some refs”。解决这个问题的方法可能会有所不同,但我可以给你一些常见的解决办法。 首先,关于“src refspec master does not match any”错误,这通常是因为你的本地仓库没有任何提交记录,或者你没有正确指定要推送的分支。根据引用的建议,你可以尝试先使用`git add .`命令将更改添加到暂存区,然后使用`git commit -m "commit message"`命令进行提交。这样就会在本地仓库创建一个提交记录,之后你就可以尝试将更改推送到远程仓库了。 关于“failed to push some refs”错误,这通常表示你的本地仓库与远程仓库之间存在冲突,可能是因为你的本地仓库落后于远程仓库或者有其他人在同时进行推送操作。根据引用的解决办法,你可以先执行`git pull --rebase origin master`命令,将远程仓库的更改合并到你的本地仓库,并解决任何冲突。然后再执行`git push origin master`命令将你的更改推送到远程仓库。 总结一下,解决这个问题的步骤如下: 1. 执行`git add .`命令将更改添加到暂存区 2. 执行`git commit -m "commit message"`命令进行提交 3. 执行`git pull --rebase origin master`命令合并远程仓库的更改 4. 执行`git push origin master`命令将你的更改推送到远程仓库 希望以上解决办法可以帮助你解决问题。如果问题仍然存在,请尝试查看其他引用中的解决方法或者提供更多详细的错误信息以便我能够更好地帮助你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [git push 大坑,错误error: src refspec master does not match any. error: failed to push some refs to](https://blog.csdn.net/qq_43142509/article/details/124182138)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [error: failed to push some refs to 'https://gitee.com/xiao-long](https://download.csdn.net/download/m0_56760139/87455643)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值