Java(Mybatis02)

Java(Mybatis02)

参考视频:13. Limit实现分页(狂神)

7. 分页

  • 思考:为啥要分页?
    • 减少数据的处理量

7.1 使用Limit分页

-- 语法
select * from `user` limit startIndex,pageSize;
select * from `user` limit 2;
-- 相当于
select * from `user` limit 0,2;
select * from `user` limit 0,-1;//原来可以查,但其实是一个bug,目前已被修复。(-1应该“代表”:到最后)
  • 使用mybatis实现分页,核心SQL
  1. 接口
    //分页
    List<User> getUserByLimit(Map<String,Integer> map);
  1. UserMapper.xml
	<!--分页-->
	<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
		select *
		from mybatis.user
		limit #{startIndex},#{pageSize};
	</select>
  1. 测试
    //分页
    @Test
    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        HashMap<String,Integer> map = new HashMap<>();
        map.put("startIndex",0);
        map.put("pageSize",4);
        
        List<User> userList = mapper.getUserByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }

7.2 RowBounds分页(不重要)

  • 不再使用SQL实现分页
  1. 接口
    //分页2
    List<User> getUserByRowBounds();
  1. UserMapper.xml
	<!--分页2-->
	<select id="getUserByRowBounds" resultMap="UserMap">
		select *
		from mybatis.user;
	</select>
  1. 测试
    //分页
    @Test
    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        HashMap<String,Integer> map = new HashMap<>();
        map.put("startIndex",0);
        map.put("pageSize",4);
        
        List<User> userList = mapper.getUserByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    
    //分页2
    public void getUserByRowBounds(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        
        //RowBounds实现
        RowBounds rowBounds = new RowBounds(0, 4);
        
        //通过Java代码层面实现分页
        List<User> userList = sqlSession.selectList("com.zach.UserMapper.getUserByRowBounds", null, rowBounds);
    
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }

7.3 分页插件

在这里插入图片描述

  • 了解,知道是什么东西即可。

8. 使用注解开发

8.1 面向接口编程

  • 大家之前都学过面向对象编程,也学习过接口。实际上,在真正的开发中,很多时候我们会选择面向接口编程
  • 根本原因:解耦, 可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好。
  • 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不用那么重要了。
  • 而各个对象之前的协作关系则成为系统设计的关键。小到不同类之前的通讯,大到各模块之间的交互,在系统设计之初都是要着重要考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

  • 关于接口的理解:
    • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。
    • 接口的本身反映了系统设计人员对系统的抽象理解。
    • 接口应有两类:
      • 第一类是对一个个体的抽象,它对应为一个抽象体(abstract class)。
      • 第二类是对一个个体某一方便的抽象,即形成一个抽象面(interface)。
    • 一个个体有可能有多个抽象面。抽象体和抽象面是有区别的。

  • 三个面向区别:
    • 面向对象,我们考虑问题时,以对象为单位,考虑它的属性及方法。
    • 面向过程,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
    • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题。更多的体现就是对系统整体的架构。

8.2 使用注解开发

  1. 注解在接口上实现
    @Select("select * from user")
    List<User> getUsers();
  1. 需要在核心配置文件中绑定接口!
  • mybatis-config.xml
	<!--绑定接口-->
	<mappers>
		<mapper class="com.zach.dao.UserMapper"/>
	</mappers>
  1. 测试
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUsers();
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
  • 本质:反射机制实现
  • 底层:动态代理!
    在这里插入图片描述
8.2.* Mybatis的详细的执行流程!

8.3 CRUD(注解版)

  • 我们可以在工具类创建的时候实现自动提交事务!
  • MybatisUtils (在最后)
package com.zach.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;

//sqlSessionFactory --> sqlSession
public class MybatisUtils {
    
    private static SqlSessionFactory sqlSessionFactory;
    
    static {
        try {
            //使用Mybatis的第一步:获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);//自动提交事务为true
    }
    
}
  • 编写接口,增加注解
  • UserMapper
package com.zach.dao;

import com.zach.pojo.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    List<User> getUsers();
    
    //方法存在多个参数时,所有的参数前面必须加上 @Param("id")注解
    @Select("select * from user where id = #{id}")
    User getUserById(@Param("id") int id);
    
    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password});")
    int addUser(User user);
    
    @Update("update user set name=#{name},pwd=#{password} where id=#{id}")
    int updateUser(User user);
    
    @Delete("delete from user where id=#{id}")
    int deleteUser(@Param("id") int id);
}
  • 测试类
  • UserDaoTest
package com.zach.dao;

import com.zach.pojo.User;
import com.zach.utils.MybatisUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;

public class UserDaoTest {

    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        
        //底层主要应用反射
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        
        //1. @Select("select * from user")
//        List<User> userList = mapper.getUsers();
//        for (User user : userList) {
//            System.out.println(user);
//        }
        
        //2. @Select("select * from user where id = #{id}")
//        User userById = mapper.getUserById(1);
//        System.out.println(userById);
        
        //3. @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password});")
//        mapper.addUser(new User(4, "张天道", "123456"));
        
        //4. @Update("update user set name=#{name},pwd=#{password} where id=#{id}")
//        mapper.updateUser(new User(4,"张酬勤","654321"));
    
        //5. @Delete("delete from user where id=#{id}")
        mapper.deleteUser(5);
        
        sqlSession.close();
    }
    
}
  • 注意: 我们必须要把接口注册绑定到我们的核心配置文件中!
  • mybatis-config.xml
	<!--绑定接口-->
	<mappers>
		<mapper class="com.zach.dao.UserMapper"/>
	</mappers>

  • 关于@Param()注解
    • 基本类型的参数 或者 String类型的参数,需要加。
    • 引用类型 不加。
    • 如果只有一个基本类型,可不加,但建议加。
    • 我们在SQL中引用的就是这里的 @Param() 中设定的属性名!

  • Tip:
  • #{}${} 的区别
    • 都能取值, 但常用#{},因为相对于后者,#{} 能更好的防止SQL注入问题!

9. Lombok

9.1 什么是Lombok

  • 官网原文:
  • Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
  • Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
  • 中文翻译:
  • Project Lombok 是一个 java 库,可自动插入您的编辑器和构建工具,为您的 java 增添趣味。
  • 永远不要再编写另一个 getter 或 equals 方法,使用一个 注解 ,您的类就有一个功能齐全的构建器、自动化您的日志变量等等。
  • 关键词:
  • java library
  • plugs
  • build tools
  • with one annotation

9.2 使用步骤

  1. 在IDEA中安装Lombok插件!
  • 但IDEA2021.2版本自带(大概2020版本以后都内置了)
  1. 在项目中导入lombok的jar包。
  • 在pom.xml中添加依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>
  • 各种注解
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
... ...
  1. 在实体类上加注解即可。
//实体类
@Data//无参构造(可能不是它生成的?),get、set、toString、hashcode、equals
@AllArgsConstructor//有参构造
@NoArgsConstructor//无参构造
@EqualsAndHashCode
@ToString
@Getter
//...
public class User {
    private int id;
    private String name;
    private String password;
    
}
  • 评价:除非必须,否则不用。

10. 多对一处理

10.1 分析

多对一:
在这里插入图片描述

  • 多个学生,对应一个老师。
  • 对于学生而言, 关联: 多个学生 关联 一个老师【多对一】
  • 对于老师而言, 集合: 一个老师 拥有 多个学生【一对多】
  • SQL
CREATE TABLE `teacher`(
	`id`   INT(10) NOT NULL,
	`name` VARCHAR(30) DEFAULT NULL,
	PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');

CREATE TABLE `student`(
	`id`   INT(10) NOT NULL,
	`name` VARCHAR(30) DEFAULT NULL,
	`tid`  INT(10)     DEFAULT NULL,
	PRIMARY KEY (`id`),
	KEY `fktid` (`tid`),
	CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;

INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

在这里插入图片描述

10.2 测试环境搭建

  1. 导入lombok(依赖)
  2. 新建实体类 Teacher,Student(用lombok方式)
  3. 建立Mapper接口
package com.zach.dao;

import com.zach.pojo.Teacher;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface TeacherMapper {
    
    @Select("select * from teacher where id = #{tid}")
    Teacher getTeacher(@Param("tid") int id);
}
  1. 建立Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
		PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
		"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zach.dao.TeacherMapper">

</mapper>
  1. 在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式随意】
  • 主要是最后的mappers标签
<?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核心配置文件-->
<configuration>
	<!--引入外部配置文件-->
	<properties resource="db.properties"/>
	
	<!--日志-->
	<settings>
		<!--标准的日志工厂实现-->
		<setting name="logImpl" value="STDOUT_LOGGING"/>
	</settings>
	
	<!--可以给实体类起别名-->
	<typeAliases>
		<package name="com.zach.pojo"/>
	</typeAliases>
	
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${driver}"/>
				<property name="url" value="${url}"/>
				<property name="username" value="${username}"/>
				<property name="password" value="${password}"/>
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<mapper class="com.zach.dao.TeacherMapper"/>
		<mapper class="com.zach.dao.StudentMapper"/>
	</mappers>
</configuration>
  1. 测试查询是否能够成功!
package com.zach.dao;

import com.zach.pojo.Teacher;
import com.zach.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

public class MyTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        
        sqlSession.close();
    }
}

10.3 按照查询嵌套处理

  • StudentMapper.xml
	<!--按照查询嵌套处理(类似子查询)
	思路:
		1. 查询所有的学生信息
		2. 根据查询出来的学生的tid,寻找对应的老师!
	-->
	<!--select-->
	<select id="getStudent" resultMap="StudentTeacher">
		select * from student;
	</select>
	<resultMap id="StudentTeacher" type="Student">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
		<!--复杂的属性,我们需要单独处理  对象:association  集合:collection-->
		<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
	</resultMap>
	
	<select id="getTeacher" resultType="Teacher">
		select * from teacher where id = #{id};
	</select>
  • testStudent
    @Test
    public void testStudent(){//查出来teacher=Teacher(id=1, name=秦老师))
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    
        List<Student> studentList = mapper.getStudent();
        for (Student student : studentList) {
            System.out.println(student);
        }
        
        sqlSession.close();
    }

10.4 按照结果嵌套处理

  • StudentMapper.xml
	<!--按照结果嵌套处理(类似连表查询)-->
	<select id="getStudent2" resultMap="StudentTeacher2">
		select s.id sid, s.name sname, t.name tname
		from student s, teacher t
		where s.tid = t.id;
	</select>
	
	<resultMap id="StudentTeacher2" type="Student">
		<result property="id" column="sid"/>
		<result property="name" column="sname"/>
		<association property="teacher" javaType="Teacher">
			<result property="name" column="tname"/>
		</association>
	</resultMap>
  • testStudent2
    @Test
    public void testStudent2(){//查出来teacher=Teacher(id=0, name=秦老师))
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        
        List<Student> studentList = mapper.getStudent2();
        for (Student student : studentList) {
            System.out.println(student);
        }
        
        sqlSession.close();
    }
  • 回顾Mysql多对一查询方式:
    • 子查询
    • 连表查询

11. 一对多处理

  • 比如:一个老师拥有多个学生!
  • 对于老师而言,就是一对多的关系!

11.1 环境搭建

  • 和前面的一样。

  • 改变:

    • 实体类:
@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
@Data
public class Teacher {
    private int id;
    private String name;
    
    //老师拥有多个学生
    private List<Student> students;
}

11.2 按照结果嵌套处理

  • TeacherMapper.xml
	<!--按照结果嵌套查询-->
	<!--select-->
	<select id="getTeacher" resultMap="TeacherStudent">
		select s.id sid, s.name sname, t.name tname, t.id tid
		from student s, teacher t
		where s.tid = t.id and t.id = #{tid}
	</select>

	<resultMap id="TeacherStudent" type="Teacher">
		<result property="id" column="tid"/>
		<result property="name" column="tname"/>
		<!--复杂的属性,我们需要单独处理  对象:association  集合:collection
		javaType="" 制定属性的类型!
		集合中的泛型信息,我们使用ofType获取
		-->
		<collection property="students" ofType="Student">
			<result property="id" column="sid"/>
			<result property="name" column="sname"/>
			<result property="tid" column="tid"/>
		</collection>
	</resultMap>
  • test
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        
        //Teacher(id=1, name=秦老师,
        // students=
        // [Student(id=1, name=小明, tid=1),
        // Student(id=2, name=小红, tid=1),
        // Student(id=3, name=小张, tid=1),
        // Student(id=4, name=小李, tid=1),
        // Student(id=5, name=小王, tid=1)]
        // )
        
        sqlSession.close();
    }

11.3 按照查询嵌套处理

  • TeacherMapper.xml
<select id="getTeacher2" resultMap="TeacherStudent2">
		select *
		from teacher
		where id = #{tid};
	</select>
	
	<resultMap id="TeacherStudent2" type="Teacher">
		<!--相同的可以不写-->
		<!--但是去掉id,id将=0-->
		<result property="id" column="id"/>
		<!--但是去掉name,name不会=null-->
<!--		<result property="name" column="name"/>-->
		<!--javaType不写结果一样-->
		<collection property="students" javaType="ArrayList" column="id" ofType="Student" select="getStudentByTeacherId"/>
	</resultMap>
	
	<select id="getStudentByTeacherId" resultType="Student">
		select *
		from student
		where tid = #{随便写什么都可以,id或者tid,甚至这句话本身};
	</select>
  • test
    @Test
    public void test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    
        Teacher teacher2 = mapper.getTeacher2(1);
        System.out.println(teacher2);
        
        //Teacher(id=1, name=秦老师, students=
        // [Student(id=1, name=小明, tid=1),
        // Student(id=2, name=小红, tid=1),
        // Student(id=3, name=小张, tid=1),
        // Student(id=4, name=小李, tid=1),
        // Student(id=5, name=小王, tid=1)]
        // )
    
        sqlSession.close();
    }

11.4 小结

  • 关联 - association 【多对一】
  • 集合 - collection 【一对多】
  • javaType & ofType
    • javaType :用来指定实体类中属性的类型
    • ofType :用来指定映射到List或者集合中pojo类型,即泛型中的约束类型。
  • 注意点:
    • 保证sql的可读性,尽量保证通俗易懂
    • 注意一对多和多对一中,属性和字段的问题
    • 如果问题不好排查错误,可以使用日志,建议使用Log4j

  • 面试高频:
    • mysql引擎
    • innoDB底层原理
    • 索引
    • 索引优化!

 
 

—————— THE END ——————
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zachsj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值