Mybatis框架技术总结
Posted 生命是有光的
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis框架技术总结相关的知识,希望对你有一定的参考价值。
0、目录总览
1、分页插件
1.1、分页插件介绍
- 分页可以将很多条结果进行分页显示。
- 如果当前在第一页,则没有上一页。如果当前在最后一页,则没有下一页。
- 需要明确当前是第几页,这一页中显示多少条结果。
- MyBatis分页插件总结
- 在企业级开发中,分页也是一种常见的技术。而目前使用的 MyBatis 是不带分页功能的,如果想实现分页的 功能,需要我们手动编写 LIMIT 语句。但是不同的数据库实现分页的 SQL 语句也是不同的,所以手写分页 成本较高。这个时候就可以借助分页插件来帮助我们实现分页功能。
- PageHelper:第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单。
1.2、SQL语句分页
limit
- 参数
- 当前页( *(当前页-1)每页显示的条数 )
- 每页显示的条数
-- 第一页,每页显示三条
select * from student limit 0,3;
-- 第二页,每页显示三条
select * from student limit 3,3;
-- 第三页,每页显示三条
select * from student limit 6,3;
1.3、分页插件的使用
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
开发步骤:
- 导入与PageHelper相关的jar包
<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
- 在mybatis核心配置文件中配置PageHelper插件
<!--集成分页助手插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"
</plugins>
- 测试分页数据获取
public void selectPaging() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession("true");
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类的方法,接受结果
List<Student> list = mapper.selectAll();
//通过分页助手来实现分页功能
//第一页:显示3条数据
PageHelper.startPage(1,3);
//第二页:显示3条数据
PageHelper.startPage(2,3);
//第二页:显示3条数据
PageHelper.startPage(3,3);
//6.处理结果
for(Student student:list){
System.out.println(student);
}
}
1.4、分页插件的参数获取
public void selectPaging() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession("true");
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类的方法,接受结果
List<Student> list = mapper.selectAll();
//其他分页的数据
PageInfo<Student> pageInfo = new PageInfo<>(list);
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("每页显示条数:"+pageInfo.getPageSize());
System.out.println("上一页:"+pageInfo.getPrePage());
System.out.println("下一页:"+pageInfo.getNextPage());
System.out.println("是否第一页:"+pageInfo.isIsFirstPage());
System.out.println("是否最后一页:"+pageInfo.isIsLastPage());
//6.处理结果
for(Student student:list){
System.out.println(student);
}
}
1.5、分页插件小结
分页:可以将很多条结果进行分页显示。
-
分页插件 jar 包: pagehelper-5.1.10.jar jsqlparser-3.1.jar
-
<plugins>
:集成插件标签。 -
分页助手相关 API
1.PageHelper:分页助手功能类。
- startPage():设置分页参数
- PageInfo:分页相关参数功能类。
- getTotal():获取总条数
- getPages():获取总页数
- getPageNum():获取当前页
- getPageSize():获取每页显示条数
- getPrePage():获取上一页
- getNextPage():获取下一页
- isIsFirstPage():获取是否是第一页
- isIsLastPage():获取是否是最后一页
2、Mybatis多表操作
2.1、多表模型介绍
我们之前学习的都是基于单表操作的,而实际开发中,随着业务难度的加深,肯定需要多表操作的。
- 多表模型分类
- 一对一:在任意一方建立外键,关联对方的主键。
- 一对多:在多的一方建立外键,关联一的一方的主键。
- 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键。
2.2、多表模型一对一操作
-
一对一模型: 人和身份证,一个人只有一个身份证
-
代码实现
-
步骤一: sql语句准备
CREATE TABLE person( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT ); INSERT INTO person VALUES (NULL,'张三',23); INSERT INTO person VALUES (NULL,'李四',24); INSERT INTO person VALUES (NULL,'王五',25); CREATE TABLE card( id INT PRIMARY KEY AUTO_INCREMENT, number VARCHAR(30), pid INT, -- 银行卡表的pid指向person表中的主键id CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id) ); INSERT INTO card VALUES (NULL,'12345',1); INSERT INTO card VALUES (NULL,'23456',2); INSERT INTO card VALUES (NULL,'34567',3);
-
步骤二:实体类和接口
public class Person{ private Integer id; //主键id private String name; //人的姓名 private Integer age; //人的年龄 //省略get/set,有参/无参方法 }
public class Card{ private Integer id; //主键id private String number; //身份证号 private Person p; //所属人的对象 //省略get/set,有参/无参方法 }
public interface OneToOneMapper{ //查询全部 public abstract List<Card> selectAll(); }
-
步骤三:配置文件
<?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.itheima.table01.OneToOneMapper"> <!--配置表中字段和实体对象属性的映射关系--> <resultMap id="oneToOne" type="card"> <id column="cid" property="id" /> <result column="number" property="number" /> <!-- association:配置被包含对象的映射关系 property:被包含对象的变量名 javaType:被包含对象的数据类型 --> <association property="p" javaType="person"> <id column="pid" property="id" /> <result column="name" property="name" /> <result column="age" property="age" /> </association> </resultMap> <select id="selectAll" resultMap="oneToOne"> SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id </select> </mapper>
-
步骤四:在MyBatisConfig.xml中引入配置文件
<!--mappers引入映射配置文件--> <mappers> <mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"></mapper> </mappers>
-
步骤五:测试类
@Test public void selectAll() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取OneToOneMapper接口的实现类对象 OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class); //5.调用实现类的方法,接收结果 List<Card> list = mapper.selectAll(); //6.处理结果 for (Card c : list) { System.out.println(c); } //7.释放资源 sqlSession.close(); is.close(); }
-
2.2.1、ResultMap
-
当涉及多表操作时,用resultMap
-
当只是单表操作时,用resultType
- resultMap:用来自定义结果集和实体类的映射
id
属性:相当于这个resultMap的唯一标识type
属性:用来指定映射到哪个实体类
- id 标签:用来指定主键列的映射规则
-
column
属性::数据库表的列名 -
property
属性:: 对应实体类的属性名
- result 标签:用来指定普通列的映射规则
column
属性::数据库表的列名property
属性: : 对应实体类的属性名
- association标签:配置被包含对象的映射规则
property
属性:被包含对象的变量名javaType
属性:被包含对象的数据类型
- collection标签:配置被包含集合对象的映射规则。
property
属性:被包含集合对象的变量名ofType
属性:集合中保存的对象数据类型
结果集映射ResultMap
要解决的问题:属性名和字段名不一致
2.2.2、查询为null问题
- 例如数据库字段名
- Java中实体类设计
public class User {
private int id; //id
private String name; //姓名
private String password; //密码和数据库不一样!
//构造
//set/get
//toString()
}
- UserMapper接口
public interface UserMapper {
//根据id查询用户
User selectUserById(int id);
}
- mapper 映射文件
<select id="selectUserById" resultType="com.kuang.pojo.User">
select * from user where id = #{id}
</select>
- 测试
@Test
public void testSelectUserById() {
SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
session.close();
}
结果
User{id=1,name='狂神',password='null'}
- password 字段为空,因为实体类和数据库字段不一致,一个是pwd,一个是password
分析
select * from mybatis.user where id = #{id}
可以看作select id,name,pwd from mybatisuser where id = #{}
- mybatis 会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写),去对应的实体类中查找相应列名的 set 方法设值,由于找不到 setPwd() ,所以password返回null
2.2.3、解决方案
方案一:为列名指定别名,别名和 java 实体类的属性名一致
<select id="selectUserById" resultType="com.kuang.pojo.User">
select id , name , pwd as password from mybatis.user where id = #{id}
</select>
方案二:使用结果集映射 ➡ ResultMap (推荐)
<resultMap id="UserMap" type="User">
<!-- id为主键 -->
<id column="id" property="id"/>
<!-- column是数据库表的列名 , property是对应实体类的属性名 -->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<!--使用我们自定义的映射规则-->
<select id="selectUserById" resultMap="UserMap">
select id , name , pwd from mybatis.user where id = #{id}
</select>
2.3、多表模型一对多操作
-
一对多模型: 一对多模型:班级和学生,一个班级可以有多个学生。
-
sql语句准备
-- 班级表
CREATE TABLE classes(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
INSERT INTO classes VALUES (NULL,'黑马一班');
INSERT INTO classes VALUES (NULL,'黑马二班');
-- 学生表的cid指向班级表的主键id
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
age INT,
cid INT,
CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id)
);
INSERT INTO student VALUES (NULL,'张三',23,1);
INSERT INTO student VALUES (NULL,'李四',24,1);
INSERT INTO student VALUES (NULL,'王五',25,2);
INSERT INTO student VALUES (NULL,'赵六',26,2);
- 实体类和接口
public class Student {
private Integer id; //主键id
private String name;//学生姓名
private Integer agel//学生年龄
//省略get/set,有参/无参方法
}
public class Classes {
private Integer id; //主键id
private String name;//班级名称
private List<Student> students; //班级中所有学生对象
}
public interface OneToManyMapper {
//查询全部
public abstract List<Classes> selectAll();
}
- 配置文件
<mapper namespace="com.itheima.table02.OneToManyMapper">
<resultMap id="oneToMany" type="classes">
<id column="cid" property="id"/>
<result column="cname" property="name"/>
<!--
collection:配置被包含的集合对象映射关系
property:被包含对象的变量名
ofType:被包含对象的实际数据类型
-->
<collection property="students" ofType="student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="oneToManyMybatis框架技术总结
Spring+SpringMVC+MyBatis+Maven框架整合
MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段