mysql与mybatis

本文详细介绍了MySQL的增删改查操作,包括单表查询的多种条件、排序、分组函数,以及连表查询和子查询。同时,深入探讨了MyBatis的核心配置、Mapper文件中的手动/自动映射、动态SQL、缓存机制和分页实现,涵盖了多对一、一对多和多对多关系的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql

新增

Insert into 表名(字段,。。。。) values (值,…………)

insert into
emp (empno,ename,job,mgr,hiredate,sal,comm,deptno) 
values
(9999,'zhangsan','MANAGER', null, null,3000, 500, 10);

修改

修改数据,可以根据条件修改数据

update 表名 set 字段名称1 = 需要修改的值1, 字段名称2 = 需要修改的值2 where …….

//将job为manager的员工的工资上涨10%
update emp set sal=sal+sal*0.1 where job='MANAGER';

删除

删除数据,可以根据条件删除数据

Delete from表名 where 。。。。。

//删除津贴为500的员工
delete from emp where comm = 500;

单表查询

简单查询

Select语句后面跟的是字段名称,select是关键字,select和字段名称之间采用空格隔开,from表示将要查询的表,它和字段之间采用空格隔开

查询多个字段,select中的字段采用逗号间隔即可,最后一个字段,也就是在from前面的字段不能使用逗号了。

select ename from emp;
select empno, ename from emp;
//将查询出来的字段显示为中文(别名)
//可以采用as关键字重命名表字段,其实as也可以省略
select empno as "员工编号", ename  "员工姓名", sal*12  "年薪" from emp;

条件查询

条件查询需要用到where语句,where必须放到from语句表的后面

运算符说明
=等于
<>或!=不等于
<小于 字符 <
<=小于等于
>大于 字符 >
>=大于等于
between … and ….两个值之间,等同于 >= and <=
is null为null(is not null 不为空)
and并且
or或者
in包含,相当于多个or(not in不在这个范围中)
notnot可以取非,主要用在is 或in中
likelike称为模糊查询,支持%或下划线匹配%匹配任意个字符下划线,一个下划线只匹配一个字符
小于  使用字符表示  &lt;
大于  使用字符表示  &gt;     
等号操作符**
//查询job为MANAGER的员工
select empno, ename from emp where job="manager";
<>操作符
//查询薪水不等于5000的员工
select empno, ename, sal from emp where sal <> 5000;
1.1 between and ***…***操作符

关于between … and …,它是包含最大值和最小值的

//查询薪水为1600到3000的员工
select empno, ename, sal from emp where sal >= 1600 and sal <= 3000;
is null

Null为空,但不是空串,为null可以设置这个字段不填值

//查询津贴为空的员工
select * from emp where comm=null;
//以上也无法查询出符合条件的数据,因为null类型比较特殊,必须使用 is来比较
select * from emp where comm is null;
and

and表示并且的含义,表示所有的条件必须满足

//工作岗位为MANAGER,薪水大于2500的员工
select * from emp where job='MANAGER' and sal > 2500;
or

只要满足条件即可,相当于包含

//查询出job为manager或者job为salesman的员工
select * from emp where job='MANAGER' or job='SALESMAN';
表达式的优先级
//查询薪水大于1800,并且部门代码为20或30的(正确的写法)
select * from emp where sal > 1800 and (deptno = 20 or deptno = 30);
in

in表示包含的意思,完全可以采用or来表示,采用in会更简洁一些

//查询出job为manager或者job为salesman的员工
select * from emp where job in ('manager','salesman');
//查询出薪水包含1600和薪水包含3000的员工
select * from emp where sal in(1600, 3000);
not
//查询出薪水不包含1600和薪水不包含3000的员工
select * from emp where sal <> 1600 and sal <> 3000;
select * from emp where not (sal = 1600 or sal = 3000);
select * from emp where sal not in (1600, 3000);
like

Like可以实现模糊查询,like支持%和下划线匹配

Like中%和下划线的差别?

%匹配任意字符出现的个数

下划线只匹配一个字符

Like 中的表达式必须放到单引号中|双引号中

//查询姓名以M开头所有的员工
select * from emp where ename like 'M%';
//查询姓名以N结尾的所有的员工
select * from emp where ename like '%N';
//查询姓名中包含O的所有的员工
select * from emp where ename like '%O%';
//查询姓名中第二个字符为A的所有员工
select * from emp where ename like '_A%';

排序

排序采用order by子句,order by后面跟上排序字段,排序字段可以放多个,多个采用逗号间隔,order by默认采用升序,如果存在where子句那么order by必须放到where语句的后面,(系统默认由小到大)

如果包含where语句order by必须放到where后面,如果没有where语句order by放到表的后面

//按照薪水由小到大排序
select * from emp order by sal;
select * from emp where job='MANAGER' order by sal;
//按照多个字段排序,如:首先按照job排序,再按照sal排序
select * from emp order by job,sal;
//手动指定按照薪水由小到大排序
select * from emp order by sal asc;
//手动指定按照薪水由大到小排序
select * from emp order by sal desc;
//多个字段排序
//如果采用多个字段排序,如果根据第一个字段排序重复了,会根据第二个字段排序
//按照job和薪水倒序
select * from emp order by job desc, sal desc;

分组函数/聚合函数/多行处理函数

count取得记录数
sum求和
avg取平均
max取最大的数
min取最小的数

注意:分组函数自动忽略空值,不需要手动的加where条件排除空值。

select count(*) from emp where xxx; 符合条件的所有记录总数。

select count(comm) from emp; comm这个字段中不为空的元素总数。

分组函数不能直接使用在where关键字后面

count
//取得所有的员工数
//Count(*)表示取得所有记录,忽略null,为null的值也会取得
select count(*) from emp;
//采用count(字段名称),不会取得为null的记录
select count(distinct job ) from emp;
//取得津贴不为null员工数
select count(comm) from emp;
sum

Sum可以取得某一个列的和,null会被忽略

//取得薪水的合计
select sum(sal) from emp;
//取得薪水的合计(sal+comm)
select sum(sal+comm) from emp;
//以上做法不正确,原因在于comm字段有null值,所以无法计算,sum会忽略掉,正确的做法是将comm字段转换成0
select sum(sal+IFNULL(comm, 0)) from emp;
avg

取得某一列的平均值

//取得平均薪水
select avg(sal) from emp;
max

取得某个一列的最大值

//取得最高薪水	
select max(sal) from emp;
//取得最晚入职得员工
select max(str_to_date (hiredate, '%Y-%m-%d')) from emp;
min

取得某个一列的最小值

//取得最低薪水
select min(sal) from emp;
组合聚合函数

可以将这些聚合函数都放到select中一起使用

select count(*),sum(sal),avg(sal),max(sal),min(sal) from emp;
分组查询

分组函数的执行顺序:

根据条件查询数据

分组(单独查某项)

采用having过滤,取得正确的数据

group by

如果使用了order by,order by必须放到group by后面

//取得每个工作岗位的工资合计,要求显示岗位名称和工资合计
select job, sum(sal) from emp group by job;

having

如果想对分组数据再进行过滤需要使用having子句

//取得每个岗位的平均工资大于2000
select job, avg(sal) from emp group by job having avg(sal) >2000;

select语句总结

select 字段
from 表名
where …….(条件)
group by ……..(分组查询)
having …….(就是为了过滤分组后的数据而存在的—不可以单独的出现)
order by ……..(排序)

以上语句的执行顺序

  1. 首先执行where语句过滤原始数据

  2. 执行group by进行分组

  3. 执行having对分组数据进行操作

  4. 执行select选出数据

  5. 执行order by排序

原则:能在where中过滤的数据,尽量在where中过滤,效率较高。having的过滤是专门对分组之后的数据进行过滤的。

连表查询

内连接

表1 inner join 表2 on 关联条件

做连接查询的时候一定要写上关联条件

inner 可以省略

//显示薪水大于2000的员工信息,并显示所属的部门名称
select e.ename, e.sal, d.dname from emp e join dept d on e.deptno=d.deptno where e.sal>2000;
//或
select e.ename, e.sal, d.dname from emp e inner join dept d on e.deptno=d.deptno where e.sal>2000;
//在实际中一般不加inner关键字
外连接

左外连接

表1 left outer join 表2 on 关联条件

做连接查询的时候一定要写上关联条件

outer 可以省略*右外连接

表1 right outer join 表2 on 关联条件

做连接查询的时候一定要写上关联条件

outer 可以省略

左外连接(左连接)和右外连接(右连接)的区别:

左连接以左面的表为准和右边的表比较,在左表中相等的不相等都会显示出来,右表只有符合条件的显示,不符合条件的不显示

右连接恰恰相反,以上左连接和右连接也可以加入outer关键字,但一般不建议这种写法,

:显示员工信息,并显示所属的部门名称,如果某一个部门没有员工,那么该部门也必须显示出来

右连接:right join

左连接:left join

//右连接:
select e.ename, e.sal, d.dname from emp e right join dept d on e.deptno=d.deptno;
//左连接:
select e.ename, e.sal, d.dname from dept d left join emp e on e.deptno=d.deptno;
//以上两个查询效果相同

子查询

distinct 去除重复行

子查询就是嵌套的select语句,可以理解为子查询是一张表

在where语句中使用子查询,也就是在where语句中加入select语句

//查询员工信息,查询哪些人是管理者,要求显示出其员工编号和员工姓名
select empno, ename from emp where empno in(select mgr from emp where mgr is not null);
//取得大于平均薪水的员工
select empno, ename, sal from emp where sal > (select avg(sal) from emp);

在from语句中使用子查询,可以将该子查询看做一张表

//查询员工信息,查询哪些人是管理者,要求显示出其员工编号和员工姓名
首先取得管理者的编号,去除重复的
select distinct mgr from emp where mgr is not null;
//将以上查询作为一张表,放到from语句的后面
select e.empno, e.ename from emp e join (select distinct mgr from emp where mgr is not null) m on e.empno=m.mgr;

union

union可以合并集合(相加)

合并结果集的时候,需要查询字段对应个数相同。在Oracle中更严格,不但要求个数相同,而且还要求类型对应相同

//查询job包含MANAGER和包含SALESMAN的员工
//方式1
select * from emp where job in('MANAGER', 'SALESMAN');
//方式2,使用union
select * from emp where job='MANAGER'
union
select * from emp where job='SALESMAN'

limit

limit ,主要用于提取前几条或者中间某几行数据

//其中m是指记录开始的index,从0开始,表示第一条记录
//n是指从第m+1条开始,取n条。
select * from table limit m,n
//即取出第3条至第6条,4条记录
select * from tablename limit 2,4

//取得前5条数据
select * from emp  limit 5;

mybatis

mysql核心配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    
    <!--引入第三方的properties
    resource: 读取第三方的properties,配置文件位置,从classpath
    url: 读取第三方的properties,配置文件位置,从操作系统的文件系统中读取(C:/..)
    -->
    <properties resource="db.properties"></properties>

    <!--全局参数设置 -->
    <settings>
        <!--二级缓存的开关: 默认是开启状态-->
        <setting name="cacheEnabled" value="true"/>
        
        <!--开启下划线转驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--类型别名-->
    <typeAliases>
        <!--单个配置(类名)
         name:类名
         alias:别名
        -->
        <!--<typeAlias type="com.bjpowernode.entity.Dept" alias="abc"/>-->
        <!--批量配置(包名)
        每种类型配置两个别名:一个与类名一致,一个类名首字母小写
        -->
        <package name="com.bjpowernode.entity"/>
    </typeAliases>
    
    <!--插件-->
    <plugins>
        <!--分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    
    <!--数据库环境,可以配置多个,配置哪个就使用哪个-->
	<environments default="mysql">
        
        <!--配置数据库-->
        <environment id="mysql">
            
            <!--使用JDBC的事务管理-->
            <transactionManager type="JDBC"></transactionManager>
            
            <!--数据源,连接池对象POOLED-->
            
            <dataSource type="POOLED">
                
                <!--数据库驱动-->
                <property name="driver" value="${jdbc.mysql.drvierClassName}"></property>
                <property name="url" value="${jdbc.mysql.url}"></property>
                <property name="username" value="${jdbc.mysql.username}"></property>
                <property name="password" value="${jdbc.mysql.password}"></property>
            </dataSource>
            
        </environment>
        
        <environment id="oracle">
            
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                
                <property name="driver" value="oracle.jdbc.driver.OralceDriver">                         </property>
                
                <property name="url" value="jdbc:oracle:thin:localhost:1521:orcl">                       </property>
                
                <property name="username" value="sys"></property>
                
                <property name="password" value="123456"></property>
                
            </dataSource>
            
        </environment>
        
    </environments>

    <!--加载-->
    <mappers>
        <mapper resource="mapper/AdminMapper.xml"/>
        <mapper resource="mapper/StudentMapper.xml"/>
        <mapper resource="mapper/ClassesMapper.xml"/>
        <!--
        加载接口: sql语句通过注解方式编写在接口中
        -->
        <mapper class="com.bjpowernode.dao.AccountDao"/>
    </mappers>
</configuration>

Mapper文件

<?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">

<!--命名空间,与接口的全限定名保持一致-->

<mapper namespace="com.bjpowernode.dao.EmpDao">
    
    <!--开启当前mapper中所有查询语句的二级缓存-->
    <cache/> 
    
    <!--
    #{变量名称}在mybatis中表示占位符
    如果传入参数为简单类型(基本数据类型, 字符串, 日期...)
    变量名称可以随意编写
    在占位符中编写变量名称的过程,可以理解为设置占位符
    parameterType:参数类型
    resultType:返回结果类型
    sql语句的id也称为statementId = namespace值.语句标签id值
    -->
    
    <select id="selectById" parameterType="int" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=#{empno}
    </select>
    
    <select id="selectById2" parameterType="int" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=${value}
    </select>
    
    <!--
    resultType结果映射类型: 映射是一条数据存放的Java实体类类型
    -->
    
    <!--
    当传入参数类型为简单类型时:
    #{}中设置占位符的变量名称可以随便编写
    ${}中的变量名称固定为value

    当传入参数类型为pojo对象类型时:
     #{}中设置占位符的变量名称为pojo对象中属性名称
     ${}中设置占位符的变量名称为pojo对象中属性名称

     #{}是占位符: 推荐占位符
     String sql = "select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where          empno=?";
     ${}语句拼接符:会引起sql注入
     String sql = "select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where          empno=" + value;
    -->
    
    <select id="select" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    </select>
    
    <!--
    如果参数映射类型为实体类类型,
    占位符中填写变量不能随便, 实体对象中的属性名称保持一致,包括大小写
    -->
    
    <insert id="insert" parameterType="com.bjpowernode.entity.Emp">
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>
    
</mapper>

手动/自动映射

<!--
    自动映射:结果集中字段名称与实体类中的属性名称必须保持一致,如果不一致,可以通过别名来解决
    手动映射:resultMap
    -->
    <resultMap id="BaseResultMap" type="emp">
        <!--id,表中主键-->
        <id column="empno" property="empno"/>
        <!--其他属性-->
        <!--
          column:结果集(数据库)中某个属性
          property:实体中某个属性
        -->
        <result column="ename" property="ename"/>
        <result column="job" property="job"/>
        <result column="mgr" property="mgr"/>
        <result column="hiredate" property="hiredate"/>
        <result column="sal" property="sal"/>
        <result column="comm" property="comm"/>
        <result column="deptno" property="deptno"/>
    </resultMap>
    
    <!--resultMap:手动映射-->
    
    <select id="select2" resultMap="BaseResultMap">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    </select>

模糊查询

like concat( ‘%’ , #{条件} , ‘%’ )

<!--模糊查询-->
    
    <!--不会引起sql语句注入,但只能用mysql数据库-->
    <select id="selectByEname" parameterType="string" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like             concat('%',#{ename},'%')
    </select>
    
    <!--会引起sql语句注入,任意数据库可用-->
    <select id="selectByEname2" parameterType="string" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like             '%${value}%'
    </select>

动态查询

<!--动态查询-->
    
    <select id="selectUseIf" parameterType="emp" resultType="emp">
        select
        empno,ename,job,mgr,hiredate,sal,comm,deptno
        from emp
        <!--
        <where>标签替代where关键字
        1.在sql语句中当条件成立时自动拼接where关键字
        2.当条件中and与where关键字相遇时会自动剔除,<where>标签会自动剔除仅挨着它的and或or关键字
        3.如果所有条件都不成立时,不会拼接where关键字
        -->
        <where>
            <if test="ename != null and ename != ''">
                ename like '%${ename}%'
            </if>
            <if test="deptno != null">
                and deptno = #{deptno}
            </if>
            <if test="sal != null">
                and sal >= #{sal}
            </if>
        </where>
    </select>

动态修改

<!--动态修改-->
    
    <update id="updateUseSet" parameterType="emp">
        update emp
        <!--
        <set>标签替代set关键字
        1.在sql语句中当条件成立时自动拼接set关键字
        2.<set>标签会自动剔除离它最远的逗号
        3.如果所有条件都不成立时,sql语句会报错
        -->
        <set>
            <if test="ename != null">
                ename=#{ename},
            </if>
            <if test="job != null">
                job=#{job},
            </if>
            <if test="mgr != null">
                mgr=#{mgr},
            </if>
            <if test="hiredate != null">
                hiredate=#{hiredate},
            </if>
            <if test="sal != null">
                sal=#{sal},
            </if>
            <if test="comm != null">
                comm=#{comm},
            </if>
            <if test="deptno != null">
                deptno=#{deptno}
            </if>
        </set>
        where empno=#{empno}
    </update>

批量新增

<!--批量插入-->
    
   <insert id="batchInsert" parameterType="list">
       <!--
        1.collection 待循环的容器
         如果参数为数组,collection=array
         如果参数为List集合,collection=list
         如果参数为pojo对象,collection=pojo对象中可遍历的属性名称
        2.item 指代 每次循环容器中的元素
        3.open 开始循环是拼接字符串
        4.close 循环结束拼接字符串
        5.separator 每次循环之间拼接的字符串
        6.index 循环索引(可不用)
        -->
      <foreach collection="users" item="user" 
        open= "  insert into user (name,pwd) values "
        close = ", ('循环结束','99999')" 
        separator="," >
        (#{user.name},#{user.pwd})
      </foreach>
   </insert>

批量删除

<!--动态批量删除-->

    <delete id="deleteBatch" parameterType="int">
        delete from emp where empno in
        <!--
        1.collection 待循环的容器
         如果参数为数组,collection=array
         如果参数为List集合,collection=list
         如果参数为pojo对象,collection=pojo对象中可遍历的属性名称
        2.item 指代 每次循环容器中的元素
        3.open 开始循环是拼接字符串
        4.close 循环结束拼接字符串
        5.separator 每次循环之间拼接的字符串
        6.index 循环索引(可不用)
        -->
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

sql语句片段

<!--sql片段-->
    
    <sql id="colName">
        empno,ename,job,mgr,hiredate,sal,comm,deptno
    </sql>

    <select id="selectById" parameterType="int" resultType="emp">
        select <include refid="colName"></include> from emp where empno=#{empno}
    </select>

主键返回

注意

返回到参数对象中,不是返回值!!!!

<!--
      useGeneratedKeys:打开主键返回
      keyProperty:主键返回属性位置
      keyColumn:声明主键,主键与属性名一致可不配
    -->
    
    <insert id="insertReturnPK" parameterType="emp" useGeneratedKeys="true"                            keyProperty="empno" keyColumn="empno">
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>

修改日期格式

DATE_FORMAT( #{日期} , ‘日期格式’ )

例如:DATE_FORMAT(#{orderDate},‘%Y-%m-%d’)

<update id="updateOrderSettingByOrderDate" parameterType="com.bjpowernode.pojo.OrderSetting">
          update t_ordersetting
          set number = #{number}
          where orderDate = DATE_FORMAT(#{orderDate},'%Y-%m-%d')
    </update>

使用工具类也可以

A

 //获取时间
 Date orderDate = new Date();
 //设置时间格式
 orderDate = DateUtils.parseDate2String(orderDate,"yyyy-MM")

B

 //获取时间
 Date orderDate = new Date();
 //设置日期格式
 SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
 //获取格式化后的日期
 Date parse = format.parse(format.format(orderDate));

懒加载

<resultMap id="findByIdMap" type="com.bjpowernode.pojo.Order">
        <id property="id" column="id"></id>
        <result property="memberId" column="memberId"></result>
        <result property="orderDate" column="orderDate"></result>
        <result property="orderType" column="orderType"></result>
        <result property="orderStatus" column="orderStatus"></result>
        <!--
            property="checkGroups" :此对象中的属性名
            ofType="checkGroups":属性对应的集合的泛型或属性类型
            select="com.bjpowernode.mapper.CheckGroupMapper.selectCheckGroupBySetmealId":调用的sql
            column="id":调用的sql时传入的参数
        -->
        <collection property="setmealId" 
                    ofType="com.bjpowernode.pojo.Setmeal"
                    select="com.bjpowernode.dao.SetmealDao.findById"
                    column="id"></collection>
    </resultMap>
    <select id="findById" parameterType="int" resultMap="findByIdMap">
        select * from t_order id = #{id}
    </select>

mybatis

package com.bjpowernode.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * Mybatis工具类
 * 1.向外界提供一个静态的返回SqlSession对象的方法
 * 2.加载核心配置文件,初始化sqlSessionFactory对象
 */
public class MybatisUtil {

    //sql工厂
    private static SqlSessionFactory sessionFactory;
    //静态块
    static {
        try {
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            sessionFactory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSession(){
        return sessionFactory.openSession();
    }
}

缓存

实体对象

需实现可序列化接口

/**
 * 开启二级缓存查询中使用的实体对象必须实现可序列化接口
 */
public class Admin implements Serializable {}

mapper文件

一级缓存,默认自动开启,关不掉

需要使用时,只需开启二级缓存,也是默认开启的

<?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">
<!--命名空间-->
<mapper namespace="com.bjpowernode.dao.AdminDao">
    <!--开启当前mapper中所有查询语句的二级缓存-->
    <cache/>

    <!--
    useCache是否开启当前sql语句的二级缓存,默认值为true开启
    -->
    <select id="selectById" parameterType="int" resultType="com.bjpowernode.entity.Admin" useCache="true">
        select id, username, password from admin where id=#{id}
    </select>
</mapper>

一级缓存

@Test
    public void firstCache(){
        SqlSession sqlSession = MybatisUtil.getSession();
        /**
         * 在同一个sqlSession中
         * 当进行第一次查询时,mybatis会先查询一级缓存,但是没有在缓存查询到数据,所以发送SQL语句查询数            据库
         * 当进行第二次查询时,mybatis也会先查询一级缓存,并在在缓存中查询到数据(缓存命中),无需查询数            据库直接返回数据。
         *
         * 注意:一级缓存(内存式)没有开关,必须使用。
         */
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        System.out.println("================第一次调用===============");
        Admin admin1 = adminDao.selectById(2);
        System.out.println(admin1);

        // 清除缓存,提交时会重新缓存
        // sqlSession.commit();

        System.out.println("================第二次调用===============");
        Admin admin2 = adminDao.selectById(2);
        System.out.println(admin2);

        sqlSession.close();
    }

二级缓存

还需在mapper接口中开启二级缓存

<!--开启当前mapper中所有查询语句的二级缓存-->
    <cache/> 

分页

mapper文件

引入第三方分页插件

<!--插件-->
    <plugins>
        <!--分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

实例

@Test
    public void testSelectPage(){
        SqlSession sqlSession = MybatisUtil.getSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        //1.设置当前页码和每页条数
        PageHelper.startPage(2, 5);
        //2.直接调用分页sql语句
        List<Emp> list = empDao.selectPage();
        for (Emp emp : list) {
            System.out.println(emp);
        }
        //3.工具类中封装了各种分页的数据
        PageInfo<Emp> pageInfo = new PageInfo<>(list);
        System.out.println("当前页码:" + pageInfo.getPageNum());
        System.out.println("每页条数:" + pageInfo.getPageSize());
        System.out.println("总记录数:" + pageInfo.getTotal());
        System.out.println("总页数:" + pageInfo.getPages());
        System.out.println("上一页:" + pageInfo.getPrePage());
        System.out.println("下一页:" + pageInfo.getNextPage());
        System.out.println("是否有上一页:" + pageInfo.isHasPreviousPage());
        System.out.println("是否有下一页:" + pageInfo.isHasNextPage());
        System.out.println("是否为首页:" + pageInfo.isIsFirstPage());
        System.out.println("是否为末页:" + pageInfo.isIsLastPage());
        System.out.println("页码数组:" + Arrays.toString(pageInfo.getNavigatepageNums()));
        sqlSession.close();
    }

连表查询

多对一

类似于很多学生在同一个班级,班级不能为空

@Data
public class Student {
    private Integer id;
    private String sname;
    private Integer cid;
    /**
     * 关系属性:描述表中主外键关系
     * 多对一关联关系,一对一关系
     *
     * 属性为一个实体或pojo对象
     */
    private Classes classes;
}    

配置文件中手动映射

使用

<resultMap id="BaseResultMap" type="com.bjpowernode.entity.Student">
        <!--主键映射关系-->
        <id column="id" property="id"/>
        <!--普通字段映射关系-->
        <result column="sname" property="sname"/>
        <result column="cid" property="cid"/>
    </resultMap>
    <!--resultMap标签的继承,继承配置-->
    <resultMap id="SelectResultMap" type="com.bjpowernode.entity.Student"                                extends="BaseResultMap">
        <!--一对一,多对一关系属性的映射关系,javaType为Java中实体中属性类型-->
        <association property="classes" javaType="com.bjpowernode.entity.Classes">
            <id column="cid" property="id"/>
            <result column="cname" property="cname"/>
        </association>
    </resultMap>

一对多

单次查询

类似于一个班级里有很多学生,学生可以为空

@Data
public class Classes {
    private Integer id;
    private String cname;    
    /**
     * 一对多,多对多关联关系属性
     * 属性类型为一个List集合
     */
    private List<Student> studentList;
}    

配置文件中手动映射

使用

    <resultMap id="BaseResultMap" type="com.bjpowernode.entity.Classes">
        <id column="id" property="id"/>
        <result column="cname" property="cname"/>
    </resultMap>
    <resultMap id="SelectByIdResultMap" type="com.bjpowernode.entity.Classes" 
               extends="BaseResultMap">
        <!--描述多对多,一对多关系属性的标签
        ofType表示关系属性List集合中存放元素的类型
        -->
        <collection property="studentList" ofType="com.bjpowernode.entity.Student">
            <id column="sid" property="id"/>
            <result column="sname" property="sname"/>
        </collection>
    </resultMap>
多次查询

运用在一对多查询中

    <resultMap id="SelectOneResultMap" type="com.bjpowernode.entity.Classes" 
                   extends="BaseResultMap">
        <!--
        在查询关联数据时,并不是从当前sql中获取,而是执行另一个sql语句
        select:再次查询的sql语句全限定名
        column:传入的查询条件,当前查询语句中的属性
        -->
        <collection property="studentList" ofType="com.bjpowernode.entity.Student"
                    select="com.bjpowernode.dao.StudentDao.selectByCid" column="id">             </collection>
    </resultMap>
    <select id="selectOne" parameterType="int" resultMap="SelectOneResultMap">
        select id, cname from classes where id=#{id}
    </select>

多对多

类似一个学生有多个课程,一个课程有多个学生

设置一个关系表,转换为一对多

对象属性类型也是使用集合

注解

了解即可,只适用简单查询

public interface AccountDao {

    @Select("select id, acc_name, balance from account")
    List<Account> select();

    @Insert("insert into account(acc_name, balance) values(#{accName}, #{balance})")
    void insert(Account entity);

    @Update("update account set acc_name=#{accName},balance=#{balance} where id=#{id}")
    void update(Account entity);

    @Delete("delete from account where id=#{id}")
    void delete(Integer id);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值