首页 > 其他分享 >2022-09-19 张宁杰 第六小组 mybatis(2)

2022-09-19 张宁杰 第六小组 mybatis(2)

时间:2022-09-21 09:45:42浏览次数:78  
标签:张宁 String 传入 19 09 did 缓存 参数 id

如果我们导入依赖出现错误如何处理?

  • 到我们的仓库中删除下载好的jar包,然后重新下载

resultType:

  • 结果集的自动映射,必须写,对象属性名和查询结果的列名必须对应上

parameterType:

  • 参数类型,可以自动解析,可以写不写,如果是我们自定义的引用数据类型,建议写上全类名

@Param的含义

List<User> selectUserByIds(@Param("ids") List<Integer> ids);

使用注解来给参数命名@Param("命名")

dao层方法传入参数的两种策略

1、传入User对象,传入一个参数。
   场景:User类中的属性非常多,id,username,password,realname,profile,gender.....
   User user = new User(null,"admin","123456",null,null,null,null
2、传入username,password两个参数,规范要求,如果需要传入多个参数,参数个数不要超过3个
  • 当我们的mapper接口传入多个参数的时候,尽量保证类型的统一。
  • 参数的类型要么是java内置的数据类型,包装器类型或者是String,要么是集合
  • 正例:
    Integer ,String
    String String
    String List
  • 反例:
    User Student
    User List
    Integer Student
  1. 如果传入的是User对象,在mapper.xml映射文件中,就必须和对象的属性名匹配
  2. 如果传入的是java内置的数据类型的参数,String,Integer..,如果只传一个参数,直接使用#{参数名},#{param1},#{xxx}
  3. 如果传入的是java内置的数据类型的参数,String,Integer..,如果传入多个参数,必须使用#{paramN}.#{arg0},不能用#{参数名}
  • 原理(mybatis传入参数的策略,封装成了一个map集合):
Mybatis在封装参数的时候,封装成了一个Map集合,
如果传入的是User对象,value:{“username”:"admin","password":"123456","id":"1"}
【"username":"admin"】,【"password":"123456"】
如果传入的是一个内置类型的参数,字面量  【"xxxx":"admin"】
如果从传入的是多个参数,【"param1":"admin"】,【"param2":"123456"】,底层封装的map集合,arg0和arg1。起了个默认的别名叫param1,param2
如果传入的是集合,【"param1":"{1,2,3,4,5}"】
dao层中的方法:
User selectUserByUsernameAndPassword(@Param("username") String username,@Param("password") String password);
  • 结论:如果需要传入多个参数,我们希望在mapper.xml中和传入对象一样使用参数的名直接赋值,#{username},使用@Param注解起名,最好还是通过传入对象来解决问题!!!!

测试类规范

  • 测试类的类名,以目标类开头,以Test结尾
  • 测试类中的测试方法,尽量以目标方法的方法名结尾,test目标方法名

mybatis配置文件部分标签

  • typeAliases标签

  • <!--  别名:各类起别名,给实体类起别名  -->
        <!-- 注意事项:typeAliases必须放在environments上面 -->
        <typeAliases>
            <!--  <typeAlias type="com.jsoft.entity.User" alias="user"></typeAlias>-->
            <!--  当前包下的所有的实体类都是以类名的首字母小写来设置别名 -->
            <!-- 场景:当前包下的某个类不想以类名小写来当做别名  -->
            <package name="com.jsoft.entity"/>
        </typeAliases>
    
  • dataSource标签,从外部文件读取相应的配置

  • <!-- 引入外部的资源文件 -->
    <properties resource="db.properties"></properties>
    <dataSource type="com.jsoft.datasource.DruidDataSourceFactory">
                    <!-- property标签中的name属性只需要按照druid的命名规则命名即可  -->
                    <property name="druid.driverName" value="${druid.driverName}"/>
                    <property name="druid.url" value="${druid.url}"/>
                    <property name="druid.username" value="${druid.username}"/>
                    <property name="druid.password" value="${druid.password}"/>
    </dataSource>
    <!--资源文件-->
    package com.jsoft.datasource;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.apache.ibatis.datasource.DataSourceFactory;
    
    import javax.sql.DataSource;
    import java.util.Properties;
    
    public class DruidDataSourceFactory implements DataSourceFactory {
    
        private Properties properties;
    
        @Override
        public void setProperties(Properties properties) {
            // 直接把mybatis-config中的参数封装成properties
            this.properties = properties;
        }
    
        @Override
        public DataSource getDataSource() {
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.configFromPropety(properties);
            return druidDataSource;
        }
    }
    
    
  • settings标签,mybatis的其他配置文件,此标签要放在properties下

  • <settings>
            <!-- 数据库的字段名以下划线命名的自动转换成小驼峰 -->
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <!-- 日志实现:记录发生过的事情,主要是记录在本地,后期运营维护,配置文件log4j.properties中 -->
            <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    

数据库表(实体类)关系

  • 一对一、一对多

多表查询的问题

  • 使用SQL99语法

  • sql语句应该使用左连接还是内连接?

    • 无论主表中的数据是否和从表有关联关系,主表中的数据都需要显示出来(主从关系),此时不使用内连接
    • 只要有关联的数据,必须用inner join
    • 如果两张表中的数据都是有关联的(并列关系),推荐使用inner join,效率高于left join
  • resultMap:自定义结果集映射

  • 一对一

    • 第一种方式
  • <resultMap id="employeeResult" type="employee">
            <id property="id" column="eid"></id>
            <result property="name" column="ename"></result>
        //dept的封装策略
            <association property="dept" javaType="dept">
                <id property="id" column="did"></id>
                <result property="name" column="dname"></result>
            </association>
     </resultMap>
    <select id="findEmployeeById" resultMap="employeeResult">
            select e.id eid,e.name ename,d.id did,d.name dname
            from employee e
            inner join dept d
            on e.did = d.id
            where e.id = #{id}
    </select>
    
    • 第二种方式(分页查询)
  • id->员工->did->部门

  • <resultMap id="employeeResult" type="employee">
            <!--如果列名和类中的属性名相同,id,result可以省略的-->
            <!-- 分步查询,dept的封装策略,前提条件,在对应的对象的mapper接口中,恰好有要查询的数据 -->
            <association property="dept" javaType="dept" 								       select="com.jsoft.dao.DeptMapper.findDeptById" column="did"></association>
    </resultMap>
    <select id="findEmployeeById" resultMap="employeeResult">
            select id,name,did from employee where id = #{id}
        </select>
    <!--这种写法不规范,因为在DeptMapper中可能有一个根据部门号查询数据的方法,最好不要这样书写-->
        <select id="findDeptById" resultType="dept">
            select id,name from dept where id = #{id}
        </select>
    <!--这块代码应该存在于DeptMapper中-->
    

    一对多

    • did->部门->did->员工

    • <!--在EmployeeMapper.xml中-->
      <select id="getEmpByDid" resultType="com.jsoft.entity.Employee">
              select id,name,did from employee where did = #{did}
      </select>
      <!--在DeptMapper.xml中-->
      <resultMap id="deptEmpResult" type="dept">
              <id property="id" column="did"></id>
              <result property="name" column="dname"></result>
              <collection property="employees" ofType="employee" select="com.jsoft.dao.EmployeeMapper.getEmpByDid" column="id">
          	</collection>
       </resultMap>
       <select id="findAllDepts" resultMap="deptEmpResult">
              select
                  id,name
              from
                  dept
        </select>
      

一级缓存:sqlSession级别的缓存

  • 执行流程:第一次发起查询sql查询用户id为3的用户,先去缓存中查看是否有id为3的用户,如果没有,再去数据库中查询,
  • 如果查到了,则把这条记录放进缓存中。
  • 如果session执行了插入,更新,删除操作,以及缓存会被清空
  • mybatis是默认开启一级缓存
  • 一级缓存失效的情况:
    * 1、sqlSession不同
    * 2、当sqlSession对象相同,查询的数据不同。
    * 3、当sqlSession对象相同,两次查询之间进行插入,修改,删除的操作
    * 4、当sqlSession对象相同,两次查询之间手动清除了一级缓存

二级缓存:mapper级别的缓存,接口级别的。

  • 多个sqlSession去操作同一个mapper的sql语句,多个sqlSession可以共用二级缓存,所得到的数据会存在二级缓存中
  • 二级缓存是跨sqlSession的
  • 二级缓存相比一级缓存范围更大。多个sqlSession可以共享一个二级缓存
  • 当session关闭时,会把数据提交到二级缓存
  • 查询时,从二级缓存中获取到的是数据的镜像,并不是真实的数据
  • <!-- 开启二级缓存 -->
        <!--
            eviction:缓存满了的淘汰机制
                1.LRU:最近最少使用的,最长时间不适用的
                2.FIFO:先进先出
                3.SOFT:软引用,基于垃圾回收器状态的软引用规则
                4.WEAK:弱引用,基于垃圾回收机状态的弱引用规则
           flushInterval:刷新时间间隔,单位毫秒
           size:缓存最多可以存多少个对象,一般情况下1024个,不宜设置过大
           redOnly:只读,默认是false,不允许修改缓存
        -->
        <cache eviction="LRU" flushInterval="10000" ></cache>
    

延迟加载(懒加载):什么时候用,什么时候再去加载,不用的时候,不加载。

标签:张宁,String,传入,19,09,did,缓存,参数,id
From: https://www.cnblogs.com/ZhangNJ/p/16714479.html

相关文章

  • IDE//VS//VS2017,VS2019没有代码提示的问题解决
    IDE//VS//VS2017,VS2019没有代码提示的问题解决小小菜鸡于2022-07-2815:24:44发布235 收藏文章标签:idec++visualstudio版权开始菜单-->所有程序–>VisualStudi......
  • VS2019编译项目出现:“错误: 值不能为 null”“参数名: path1”问题
    问题:VS2019编译项目出现以下问题:1>错误:值不能为null。1>参数名:path1解决方法:解决方案资源管理器里卸载项目,再重新加载。......
  • JAVA进阶--XML、XML解析、XPath、设计模式--2022年9月19日
    第一节1、XML是什么?XML的全称为(EXtensibleMarkupLanguage),是一种可扩展的标记语言它是一种数据表示格式,可以用于自定义数据格式2、......
  • 220920 总结
    220920总结预计:\(100+100+100\)实际:\(100+100+10\)T1注意到\(K\leq100\)所以写了个类似dp的东西复杂度大概是\(O(NMK)\)?此时大概过去了30min#include<bits/......
  • 归档 220920 | CSP-J 复习
    所以为什么要复习J组所以为什么我连J组都不会,哭唧唧A.加工零件一开始的想法是,如果点\(x\)离\(1\)的距离大于等于\(L\),且与\(L\)奇偶性相同,那么就可行。然......
  • Test 2022.09.20
    2022年9月20日的测试(SCOI2005专场)T1扫雷思考起来很简单,对于任意一个输入的\(a[i]\),它会约束的格子只有\(i-1,i,i+1\)三个,也就是只要算出当前在\(i-1,i\)位置摆放的情......
  • 20220920祭
    20220920t1[SCOI2005]扫雷最初思路显然,对于数值为3或0的格子只有一种情况。考虑从已经确定的摆放情况向周围拓展,直至无法拓展。此时就将所有可以确定的摆放确定,最后只......
  • 解决Python报错OSError: [WinError 193] %1 不是有效的 Win32 应用程序
    解决Python调试OSError:[WinError193]%1不是有效的Win32应用程序今天在练习selenium运行后报错,网上找了很多方法,最终终于解决。我的问题是 chromeDriver驱动不匹......
  • Codeforces Round #819 (Div. 1 + Div. 2) and Grimoire of Code Annual Contest 2022
    Preface明天的CF一定打啊(绝对不咕),今天白天补现代作业,英语作业到哭,而且还要准备四六级,每天逼着自己背单词A.MainakandArray不难发现换中间的数不会影响答案,因此操作......
  • 20220920
    Get和Post的区别post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中)post发送的数据更大(get有url长度限制)post能发送更多的数据类型(get......