当前位置: 首页 > news >正文

2024年9月23日---关于MyBatis框架(2)

4.7 不同返回值类型的查询

4.7.1 返回基本数据类型

/**查询student表中的记录个数 */
int selectCount();
<select id="selectCount" resultType="_int">select count(*) from student;
</select>

4.7.2 返回引用类型(实体类)

/**返回值为实体类的*/
Student findById(Integer id);
<!-- 属性resultType:书写方法的返回值类型 代理对象通过sql语句进行查询,然后将查询到的结果自动封装成返回值类型的实例 -->
<select id="findById" resultType="Student">select * from student where id = #{arg0};
</select>

4.7.3 返回List类型

List<Student> findByPage(@Param("offset") int offset, @Param("pageSize") int pageSize);
<!--返回值类型: 如果方法的返回值类型是List,那么在属性resultType上只需要指定集合的元素类型的名字即可-->
<select id="findByPage" resultType="Student">select * from student limit #{offset},#{pageSize}
</select>

4.7.4 返回Map类型

Map<String,Object> findByName(String name);
<!--应用场景:  就是将从数据库查询出来的数据,封装成Map对象字段名作为key字段值作为value   -->
<select id="findByName" resultType="map">select * from student where name = #{name}
</select>

4.7.5 返回Map实例的集合

/**应用场景: 一条记录封装一个Map实例,多个Map实例封装到List集合中
*  条件: 通过性别,可以查询出来多条记录,封装到List集合中,泛型为Map   */
List<Map<String,Object>>  findByGender(@Param("gender")String gender);
<select id="findByGender" resultType="map">select * from student where gender = #{gender}
</select>

4.7.6 返回Map的另一种情况

/*** 1001  => {address=江南, gender=m, name=刘备, age=40, sid=1001}* 1002  => {address=上海, gender=m, name=关羽, age=35, sid=1002}* 1003  => {address=长春, gender=m, name=赵云, age=27, sid=1004}*/
@MapKey("sid")
Map<Integer,Object>  findByGender2(@Param("gender")String gender);
<select id="findByGender2" resultType="map">select * from student where gender = #{gender}
</select>

4.7.7 返回Set集合

/** 应用场景:  数据库里的记录可能有重复数据,  然后再进行查询时,想要进行去重操作,我们就可以设计方法的* 返回值为Set,  泛型为该表的实体类   注意:  实体类必须重写equals方法和hashCode方法。* */
Set<Student> findAllByDistinct();

<select id="findAllByDistinct" resultType="student">select * from student
</select>

4.8 特殊SQL的查询

4.8.1 模糊查询

like  '%${username}%'
like concat('%',#{username},'%')
like "%"#{username}"%"

4.8.2 批量删除

使用${},不能使用#{}

4.8.3 动态指定表名

4.8.4 主键返回

  • 自增长类型主键

1)在接口StudentMapper里添加如下方法

    int insertStudent(Student s);

2)在StudentMapper.xml里添加如下内容

<!-- int insertEmployee(Employee employee); -->
<!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
<!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="id" parameterType="student">
   insert into student
   (name, age, gender, id_card, address)
   values
   (#{name},#{age},#{gender},#{idcard},#{address})
</insert>

3)测试

@Test
public void test12() throws IOException {InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);SqlSession sqlSession = factory.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​Student student = new Student("张鲁一",40,"男","2222233333","北京");mapper.insertStudent(student);System.out.println(student.getId());
​sqlSession.commit();sqlSession.close();
​
}
  • 非自增长类型主键
use mybatis_db;
drop table if exists computer;
create table if not exists computer(id varchar(100) primary key,brand varchar(20),model varchar(20),price double
);
​
insert into computer values (1, 'ThinkPad','X1',12000);
insert into computer values (2, 'Mi','p1',6500);
insert into computer values (3, 'lenove','s1',4000);
​
commit;
​
select * from computer;

而对于不支持自增型主键的数据库(例如 Oracle)或者字符串类型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用!

使用 selectKey 帮助插入UUID作为字符串类型主键示例:

<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="java.lang.String"
        order="BEFORE">
        SELECT UUID() as id
    </selectKey>
    INSERT INTO user (id, username, password) 
    VALUES (
        #{id},
        #{username},
        #{password}
    )
</insert> 

在上例中,我们定义了一个 insertUser 的插入语句来将 User 对象插入到 user 表中。我们使用 selectKey 来查询 UUID 并设置到 id 字段中。

通过 keyProperty 属性来指定查询到的 UUID 赋值给对象中的 id 属性,而 resultType 属性指定了 UUID 的类型为 java.lang.String。

需要注意的是,我们将 selectKey 放在了插入语句的前面,这是因为 MySQL 在 insert 语句中只支持一个 select 子句,而 selectKey 中查询 UUID 的语句就是一个 select 子句,因此我们需要将其放在前面。

最后,在将 User 对象插入到 user 表中时,我们直接使用对象中的 id 属性来插入主键值。

使用这种方式,我们可以方便地插入 UUID 作为字符串类型主键。当然,还有其他插入方式可以使用,如使用Java代码生成UUID并在类中显式设置值等。需要根据具体应用场景和需求选择合适的插入方式。

4.9 级联查询

4.9.1 多对一查询

多对一,指的是表与表之间的记录关系,比如学生信息表(S_IDS_NAME,……,T_ID)与教师(班主任)信息表(T_IDT_NAME,……)。多个学生是一个老师教的。通过学生信息表里的任意一条记录,都可以找到教师信息表里的对应的老师信息。

第一种写法:字段映射

第二种写法:association(关联,联合)

第三种写法:分步写法

//查询7369这个员工的员工信息和其所在部门信息
select * from emp e join dept d on  e.deptno = d.deptno where empno = 7369;
​
​
select * from emp where empno = 7379;
select * from dept where deptno = 

4.9.2 一对多查询

一对多,其实就是多对一的反向操作。教师信息表是主表,学生信息表是副表,通过教师信息表的任意一条记录,都可以在学生信息表里找到该教师的多个学生信息。

//查询10号部门的信息及其所有员工信息
select * from dept d left join emp e on d.deptno = e.deptno where d.deptno = 10;

第一种写法:collection

第二种写法:分步写法

第一步:查询accounting部门的信息select * from dept where dname = 10;
第二步:在员工表里查询,select * from emp where deptno = ?

4.9.3 多对多查询

一般多对多,都会涉及到第三张表。 学生信息表(每个学生的信息都是唯一的一条记录), 课程信息表(每个科目也都是唯一的一条记录),学生课程表(一个学生可以选择多个科目进行学习,一个科目可以被多个学生选择学习)。学生信息表和课程信息表通过学生课程表进行的对应关系,就是多对多的关系。

CREATE TABLE `course`  (
  `c_id` int(0) NOT NULL AUTO_INCREMENT COMMENT '课程ID',
  `c_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程名称',
  `t_id` int(0) NOT NULL COMMENT '授课教师ID',
  `c_academy` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '所属学院',
  `c_note` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程备注',
  PRIMARY KEY (`c_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES (1, '高数', 1, '信息学院', '高等数学,微积分');
INSERT INTO `course` VALUES (2, '英语', 2, '工程学院', '英语选修');
INSERT INTO `course` VALUES (3, 'JAVA', 3, '信息学院', '面向对象的编程语言');
INSERT INTO `course` VALUES (4, '食品安全', 1, '食品学院', '民以食为天');
INSERT INTO `course` VALUES (5, '土木建筑', 2, '工程学院', '桥梁,观景房');
INSERT INTO `course` VALUES (6, '体育', 2, '工程学院', '健身强体...');

CREATE TABLE `score`  (
  `s_id` int(0) NOT NULL COMMENT '学生ID',
  `c_id` int(0) NOT NULL COMMENT '课程ID',
  `score` int(0) NULL DEFAULT NULL COMMENT '课程分数',
  PRIMARY KEY (`s_id`, `c_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of score
-- ----------------------------
INSERT INTO `score` VALUES (1001, 1, 80);
INSERT INTO `score` VALUES (1001, 2, 90);
INSERT INTO `score` VALUES (1001, 3, 99);
INSERT INTO `score` VALUES (1002, 1, 70);
INSERT INTO `score` VALUES (1002, 2, 60);
INSERT INTO `score` VALUES (1002, 3, 80);
INSERT INTO `score` VALUES (1003, 1, 80);
INSERT INTO `score` VALUES (1003, 2, 80);
INSERT INTO `score` VALUES (1003, 4, 80);
INSERT INTO `score` VALUES (1004, 3, 50);
INSERT INTO `score` VALUES (1004, 4, 30);
INSERT INTO `score` VALUES (1004, 5, 20);
INSERT INTO `score` VALUES (1005, 5, 76);
INSERT INTO `score` VALUES (1005, 6, 87);
INSERT INTO `score` VALUES (1006, 5, 31);
INSERT INTO `score` VALUES (1006, 6, 34);
INSERT INTO `score` VALUES (1007, 4, 89);
INSERT INTO `score` VALUES (1007, 6, 98);

需求: 查询每个学生的学号,姓名,年龄,所学科目名称,及其成绩

select s.id,s.name,s.age,c.c_name,sc.score
from student s , course c,  score sc
where s.id = sc.s_id and c.c_id = sc.c_id
​
select s.id,s.name,s.age,c.c_name,sc.score
from student s 
left join score sc  on  s.id = sc.s_id
left join course c  on  c.c_id = sc.c_id
​
select s.id,s.name,s.age,c.c_name,sc.score
from student s 
left join score sc 
left join course c  
on  c.c_id = sc.c_id and s.id = sc.s_id

4.9.4 延迟加载

延迟加载,就是在使用数据时,进行查询操作,不使用时,不提前加载。可以节省内存,提高查询效率。

第一种方式: 局部配置(映射文件)

在
<association> 标记里
配置如下属性:
fetchType="lazy"          lazy: 延迟加载   eager: 不延迟加载
​
如下:<association property="dept"  fetchType="eager" .....

第二种方法:全局配置(核心配置文件)

<settings><setting name="logImpl" value="STDOUT_LOGGING"/><!--全局的延迟加载开关, value设置为true,表示开启全局延迟加载, 不写value属性,默认就是false--><setting name="lazyLoadingEnabled" value="true"/>
</settings>

4.10 分页查询

4.10.1 简介

在开发过程中,分页查询是一个常见的需求。为了简化分页查询的操作,我们可以使用 Mybatis 的分页插件,如 PageHelper

分页插件的概念

分页查询时,通常需要传入页数(page)*和*每页条数(pageSize)。返回的数据包括页面数据总条数总页数当前页面每页条数等。使用分页插件可以快速帮助我们获取这些数据。

分页插件的核心原理

分页查询的核心原理是通过 SQL 语句中的 LIMIT 关键字,根据传入的参数(当前页码、每页显示条数)来控制返回的当前页的内容范围

4.10.2 步骤

1)添加依赖

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version>
</dependency>

2)在MyBatis的核心配置文件( mybatis-config.xml)中配置插件

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

4.10.3 分页的应用

1)开启分页功能

在查询功能之前使用 PageHelper.startPage(int pageNum, int pageSize) 开启分页功能,传入当前页码和每页显示的条数:

  • pageNum:当前页的页码

  • pageSize:每页显示的条数

2)打印方法的返回值,查看

Page<Object> page = PageHelper.startPage(1, 3);
System.out.println(page);
Page{
count=true, 
pageNum=2, 
pageSize=3, 
startRow=3, 
endRow=6, 
total=19, 
pages=7, 
reasonable=false, 
pageSizeZero=false}[Student{id=1002, name='关羽', gender='m', age=35, address='上海', scores=[Score{sid=1002, cid=1, score=70}, Score{sid=1002, cid=2, score=60}, Score{sid=1002, cid=3, score=80}]', courses=[Course{cid=1, cname='高数', tid=1, academy='信息学院', note='高等数学,微积分', students=null}, Course{cid=2, cname='英语', tid=2, academy='工程学院', note='英语选修', students=null}, Course{cid=3, cname='JAVA', tid=3, academy='信息学院', note='面向对象的编程语言', students=null}]}]

3)另外一个API:

PageInfo 这个类型封装的信息更多一些,包括了导航分页的信息。 用于在查询之后

new PageInfo(List list, int navegatePage);
list:  分页查询的返回数据
navegatePage:  用来定义导航分页的页码显示数量

PageInfo{
   pageNum=2, 
   pageSize=3, 
   size=1, startRow=4, endRow=4, 
   total=19, 
   pages=7, 
   prePage=1, nextPage=3, 
   isFirstPage=false, 
   isLastPage=false, 
   hasPreviousPage=true, 
   hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=5, navigatepageNums=[1, 2, 3, 4, 5]}

4.11 注解完成增删改查

使用注解开发会比配置文件开发更方便。

  • @Select 查询

  • @Insert 添加

  • @Update 修改

  • @Delete 删除

案例演示

1)Mapper接口里:

package com.sldl.mapper;
​
import com.sldl.pojo.Student;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
​
import java.util.List;
​
public interface StudentMapper1 {@Select("select * from student ")List<Student> findAll();
​@Select("select * from student where id = #{id}")Student findById(int id);
​@Insert("insert into student values (null,#{name},#{age},#{gender},#{idcard},#{address})")void addStudent(Student s);
​@Update("update student set name=#{name},age=#{age} where id=#{id}")void modStudent(Student s);
​@Delete("delete from student where id = #{id}")void delStudent(int id);
}

2)测试:

package com.sldl.test;

import com.sldl.mapper.ComputerMapper;
import com.sldl.mapper.StudentMapper;
import com.sldl.mapper.StudentMapper1;
import com.sldl.pojo.Computer;
import com.sldl.pojo.Student;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class MyBatisTest3 {
    SqlSession  sqlSession = null;
    @Before
    public void testBefore() throws IOException {
        String mybatis_config = "mybatis-config.xml";
        InputStream stream = Resources.getResourceAsStream(mybatis_config);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream);
        sqlSession = factory.openSession();
    }
    @After
    public void testAfter(){
        sqlSession.close();
    }
    @Test
    public void test1(){
        StudentMapper1 mapper = sqlSession.getMapper(StudentMapper1.class);
        //测试查询方法
        List<Student> all = mapper.findAll();
        for (Student student : all) {
            System.out.println(student);
        }
    }
    @Test
    public void test2(){
        StudentMapper1 mapper = sqlSession.getMapper(StudentMapper1.class);
        //测试查询方法
        Student student = mapper.findById(3);
        System.out.println(student);
    }
    @Test
    public void test3(){
        StudentMapper1 mapper = sqlSession.getMapper(StudentMapper1.class);

        Student s1  = new Student();
        s1.setName("sunny");
        s1.setAge(18);
        s1.setGender("女");
        s1.setIdcard("1234567890");
        s1.setAddress("长春绿园");

        mapper.addStudent(s1);

        sqlSession.commit();
    }
    @Test
    public void test4(){
        StudentMapper1 mapper = sqlSession.getMapper(StudentMapper1.class);
        Student s1  = new Student();
        s1.setId(19);
        s1.setName("sun");
        s1.setAge(28);
        mapper.modStudent(s1);
        sqlSession.commit();
    }
    @Test
    public void test5(){
        StudentMapper1 mapper = sqlSession.getMapper(StudentMapper1.class);
        mapper.delStudent(19);
        sqlSession.commit();
    }
}


http://www.mrgr.cn/news/35275.html

相关文章:

  • 小版本大不同 | Navicat 17 新增 TiDB 功能
  • 微信小程序内嵌h5页面(uniapp写的),使用uni.openLocation无法打开页面问题
  • 数字化转型企业架构设计手册(交付版),企业数字化转型建设思路、本质、数字化架构、数字化规划蓝图(PPT原件获取)
  • C++中的栈(Stack)和堆(Heap)
  • 前端开发中常用的包管理器(npm、yarn、pnpm、bower、parcel)
  • Hadoop学习--第一章 Hello大数据分布式
  • 最新版C/C++通过CLion2024进行Linux远程开发保姆级教学
  • 毛竹泛基因组-文献精读52
  • 【代码随想录Day27】贪心算法Part01
  • 电商效果图渲染神器:轻松高效出图
  • gorm.io/sharding:改造,当查询条件中不包含分表键时,从自定义方法中获取对应的表进行查询
  • 【JVM】JVM执行流程和内存区域划分
  • 浅析Android中的View事件分发机制
  • 2024 年最新 Protobuf 结构化数据序列化和反序列化详细教程
  • 【alist】宝塔面板docker里的alist默认admin无法登录
  • 分享6个icon在线生成网站,支持AI生成
  • “被卷”还是“破卷”,咱有得选
  • 虚幻引擎的射线检测/射线追踪
  • 水墨风度——书圣故里书画名家晋京展亮相荣宝斋大厦
  • 【machine learning-17-分类(逻辑回归sigmod)】
  • YOLOX预测图片是无法保存
  • Vue|插件
  • `#include <vector>`
  • Unity图形用户界面!*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。(万字解析)
  • 【C++】检测TCP链接超时——时间轮组件设计
  • CF542E Playing on Graph 题解