1.分页
我们为什么要分页呢?
- 减少数据的处理量
使用Limit分页
select * from mybatis.user limit startIndex,pageSize;
select * from mybatis.user limit 0,5;
使用mybatis实现分页,核心SQL
1.接口,这里我们使用万能的Map进行传参数(可以去找我前面写的文章关于CRUD的)
//分页
List<User> getUserByLimit(Map<String,Integer> map);
2.Mapper.xml
<select id="getUserByLimit" resultType="com.lwq.pojo.User" parameterType="map">
select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
3.测试
public void getUserByLimit() {
HashMap<String, Integer> HashMap = new HashMap<String, Integer>();
HashMap.put("startIndex",0);
HashMap.put("pageSize",5);
SqlSession sqlSession = MbatisUtlis.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userByLimit = mapper.getUserByLimit(HashMap);
for (User user : userByLimit) {
System.out.println(user);
}
sqlSession.close();
}
2.分页插件
3.注解开发
3.1 面向接口编程
大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程
- 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好
- 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;
- 而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。
关于接口的理解
- 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。
- 接口的本身反映了系统设计人员对系统的抽象理解。
- 接口应有两类:
- 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);
- 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);
- 一个体有可能有多个抽象面。抽象体与抽象面是有区别的。
3.2使用注解开发
1.注解在接口上面实现
@Select("select * from user")
List<User> getUserList();
2.需要在核心配置文件中绑定接口
<mappers>
<mapper class="com.lwq.dao.UserMapper"></mapper>
</mappers>
3.测试
@Test
public void Test1() {
SqlSession sqlSession = null;
try {
sqlSession = MbatisUtlis.getSqlSession();
//底层主要应用放射
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.getUserList();
for (User user : list) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//不要忘记关闭sqlSession哟
sqlSession.close();
}
}
4.测试结果成功
mybatis详细流程图
4.注解实现CRUD
我们可以在工具类中创建的时候实现自动提交事务(设置为true)
4.1查询操作
接口
@Select("select * from user")
List<User> getUserList();
//方法存在多个参数,所有的参数必须加上@Param
@Select("select * from user where id=#{id}")
User getUserById(@Param("id") int id);
测试类
@Test
public void Test1() {
SqlSession sqlSession = null;
try {
sqlSession = MbatisUtlis.getSqlSession();
//底层主要应用放射
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.getUserList();
for (User user : list) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//不要忘记关闭sqlSession哟
sqlSession.close();
}
}
@Test
public void getByIdTest() {
SqlSession sqlSession = MbatisUtlis.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(5);
System.out.println(userById);
sqlSession.close();
}
运行结果
4.2增加操作
接口
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})")
int addUser(User user);
测试类
@Test
public void addUser() {
SqlSession sqlSession = MbatisUtlis.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.addUser(new User(18, "开学啦", "123456"));
if (i>0){
System.out.println("插入成功");
}else {
System.out.println("插入失败");
}
sqlSession.close();
}
测试结果
4.3更新操作
接口
@Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")
int updateUser(User user);
测试类
@Test
public void updateUser() {
SqlSession sqlSession = MbatisUtlis.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.updateUser(new User(18, "开学啦哟", "1234567"));
if (i>0){
System.out.println("修改成功");
}else {
System.out.println("修改失败");
}
sqlSession.close();
}
测试结果
4.4删除操作
接口
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
测试类
@Test
public void deleteUser() {
SqlSession sqlSession = MbatisUtlis.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deleteUser(16);
if (i>0){
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
sqlSession.close();
}
测试结果
5.多对一处理
- 多个学生,对应一个老师
- 对于学生来说,关联…多个学生,关联一个老师【多对一】
- 对于老师来说,集合,一个老师有很多学生【一对多】
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=utf8INSERT 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');
测试环境搭建
1.新建实体类Teacher,Student
2.建立Mapper接口
3.建立Mapper.xml文件
4.在核心配置文件在绑定注册我们的Mapper接口或者文件
4.测试查询是否能成功
按照查询嵌套处理
<?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.lwq.dao.StudentMapper">
<!-- 思路:
1.查询所有的学生信息
2.根据学生的tid,寻找对应的老师
-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"></result>
<result property="name" column="name"></result>
<!-- 复杂的属性需要单独处理- -->
<!-- 对象:association-->
<!-- 集合:collection-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"></association>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id=#{id};
</select>
</mapper>
按照结果嵌套处理
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname, t.id tid
from student s,teacher t
where s.tid=t.id;
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"></result>
<result property="name" column="sname"></result>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"></result>
<result property="id" column="tid"></result>
</association>
</resultMap>
回顾一下MySQL多对一查询方式:
- 子查询
- 联表查询
6.一对多处理
比如:一个老师拥有好多好多个学生
对于老师而言,就是一对多的关系
1.环境搭建,和刚才一样的
按照结果嵌套处理
<?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.lwq.dao.TeacherMapper">
<!-- 按照结果嵌套查询-->
<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>
<result property="name" column="tname"></result>
<!-- 复杂的属性,我们需要单独处理 对象association 集合collection-->
<!-- javaType="" 指定属性的类型-->
<!-- 集合中的泛型信息,我们使用ofType获取-->
<collection property="students" ofType="Student">
<result property="id" column="sid"></result>
<result property="name" column="sname"></result>
<result property="tid" column="tid"></result>
</collection>
</resultMap>
</mapper>
按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id=#{tid};
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id">
</collection>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid=#{tid}
</select>
注意的点
- 关联- association [多对一]
- 集合- collection[一对多]
- javaType & ofType
1.javaType 用来指定实体类中的属性的类型
2.ofType 用来指定映射到List或者集合中pojo类型,泛型中的约束类型 - 保证SQL的可读性 ,尽量保证读的懂
- 注意一对多喝多对一中,属性和字段的问题
7.动态SQL
什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句
要进行练习首先需搭建环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
创建一个基础工程
1.编写配置文件
<?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"></properties>
<!-- 配置日志-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!-- 可以给实体类写别名-->
<typeAliases>
<!-- <typeAlias type="com.lwq.pojo.User" alias="User"></typeAlias>-->
<package name="com.lwq.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 事务管理,jdbc-->
<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.lwq.dao.BlogMapper"></mapper>
</mappers>
</configuration>
db.properties配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT
username=root
password=147258
2.编写实体类
package com.lwq.pojo;
import java.util.Date;
/**
* 2 * @Author: lwq
* 3 * @Date: 2020/6/3 20:54
* 4
*/
public class Blog {
private String id;
private String title;
public Blog(String id, String title, String author, Date create_time, int views) {
this.id = id;
this.title = title;
this.author = author;
this.create_time = create_time;
this.views = views;
}
public Blog() {
}
private String author;
private Date create_time;
private int views;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getCreate_time() {
return create_time;
}
public void setCreate_time(Date create_time) {
this.create_time = create_time;
}
public int getViews() {
return views;
}
public void setViews(int views) {
this.views = views;
}
@Override
public String toString() {
return "Blog{" +
"id='" + id + '\'' +
", title='" + title + '\'' +
", author='" + author + '\'' +
", create_time=" + create_time +
", views=" + views +
'}';
}
}
3.编写实体类对应Mapper接口 和Mapper.XML文件
package com.lwq.dao;
import com.lwq.pojo.Blog;
import org.apache.ibatis.annotations.Insert;
/**
* 2 * @Author: lwq
* 3 * @Date: 2020/6/3 20:13
* 4
*/
//插入数据
public interface BlogMapper {
int addBook(Blog blog);
}
<?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.lwq.dao.BlogMapper">
<insert id="addBook" parameterType="blog">
insert into blog(id,title,author,create_time,views)
values(#{id},#{title},#{author},#{create_time},#{views})
</insert>
</mapper>
4.在核心配置文件在绑定注册我们的Mapper接口或者文件
1.动态SQL之 if
接口
List<Blog> queryBlogIf(Map map);
xml配置文件(关于where标签的作用 :where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。)
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title !=null">
and title=#{title}
</if>
<if test="author !=null">
and author=#{author}
</if>
</where>
</select>
测试类
@Test
public void queryBlogIf() {
SqlSession sqlSession = MbatisUtlis.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap hashMap = new HashMap();
// hashMap.put("title", "java如此简单");
hashMap.put("author","小罗老师");
List<Blog> list = mapper.queryBlogIf(hashMap);
for (Blog blog : list) {
System.out.println(blog);
}
sqlSession.close();
}
2.choose、when、otherwise
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title!=null">
and title=#{title}
</when>
<otherwise>
and views=#{views}
</otherwise>
</choose>
</where>
</select>
3.trim、where、set
select * from blog
<where>
<if test="title !=null">
and title=#{title}
</if>
<if test="author !=null">
and author=#{author}
</if>
</where>
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title!=null">
title=#{title},
</if>
<if test="author!=null">
author=#{author},
</if>
<if test="views!=null">
views=#{views}
</if>
</set>
where id=#{id}
</update>
其实动态SQL,本质上还是SQL语句,只是可以在SQL语句的基础上加一些逻辑代码。
if
where,set,choose,when
8.SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用
SQL标签抽取的公共的部分
<sql id="if-title-author">
<if test="title !=null">
and title=#{title}
</if>
<if test="author !=null">
and author=#{author}
</if>
</sql>
在需要的地方使用include标签引入
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
解释:
注意事项:
- 最好基于单表来定义SQL片段(简单来说就是写的东西简单一点,这样重复利用的机会更多)
- 不要存在where标签
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,安装SQL的格式,去排列组合就可以了
建议:
- 先在mysql中写出完整的SQL,在对应的去修改成为我们的动态SQL实现通用即可。